CHORE(style): add responsive Tailwind CSS
- Implement responsive design - Add custom Tailwind styles
This commit is contained in:
@@ -13,7 +13,7 @@ commonLabels:
|
||||
# 이미지 태그 설정
|
||||
images:
|
||||
- name: ghcr.io/mayne0213/portfolio
|
||||
newTag: main-sha-02f540cea01f2abd0a572d2baf8042958cd0f318
|
||||
newTag: main-sha-3ced4c6a71df7e56b99b22c5aa7399b186d6311d
|
||||
|
||||
patchesStrategicMerge:
|
||||
- deployment-patch.yaml
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@theme {
|
||||
--breakpoint-tablet: 768px;
|
||||
--breakpoint-pc: 1024px;
|
||||
--breakpoint-smalltablet: 600px;
|
||||
--breakpoint-tablet: 990px;
|
||||
--breakpoint-desktop: 1200px;
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
@@ -25,8 +26,9 @@
|
||||
--color-ring: var(--ring);
|
||||
}
|
||||
|
||||
@custom-variant tablet (@media (width >= 768px));
|
||||
@custom-variant pc (@media (width >= 1024px));
|
||||
@custom-variant smalltablet (@media (width >= 600px));
|
||||
@custom-variant tablet (@media (width >= 990px));
|
||||
@custom-variant desktop (@media (width >= 1200px));
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
@@ -110,7 +112,7 @@
|
||||
}
|
||||
|
||||
.page-container {
|
||||
@apply flex flex-col items-center justify-center gap-16 p-4 tablet:p-8 py-20 mt-[70px];
|
||||
@apply flex flex-col items-center justify-center gap-12 smalltablet:gap-14 tablet:gap-16 p-4 smalltablet:p-6 tablet:p-8 py-16 smalltablet:py-18 tablet:py-20 mt-[70px];
|
||||
}
|
||||
|
||||
.theme-background {
|
||||
|
||||
@@ -11,13 +11,13 @@ interface InfoItemProps {
|
||||
|
||||
function InfoItem({ icon: Icon, label, value }: InfoItemProps) {
|
||||
return (
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="flex items-center justify-center min-w-10 min-h-10 rounded-full theme-background">
|
||||
<Icon className="w-5 h-5" />
|
||||
<div className="flex items-start gap-3 smalltablet:gap-4">
|
||||
<div className="flex items-center justify-center min-w-8 min-h-8 smalltablet:min-w-10 smalltablet:min-h-10 rounded-full theme-background">
|
||||
<Icon className="w-4 h-4 smalltablet:w-5 smalltablet:h-5" />
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-semibold">{label}</span>
|
||||
<span className="text-muted-foreground">{value}</span>
|
||||
<span className="text-sm smalltablet:text-base font-semibold">{label}</span>
|
||||
<span className="text-xs smalltablet:text-sm text-muted-foreground">{value}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -35,19 +35,19 @@ const PERSONAL_INFO = [
|
||||
export default function About() {
|
||||
return (
|
||||
<div className="bg-muted">
|
||||
<main className="flex flex-col items-center justify-center gap-16 p-4 tablet:p-8 py-20">
|
||||
<main className="flex flex-col items-center justify-center gap-12 smalltablet:gap-14 tablet:gap-16 p-4 smalltablet:p-6 tablet:p-8 py-16 smalltablet:py-18 tablet:py-20">
|
||||
<SectionHeader
|
||||
title="About Me"
|
||||
description="Passionate full-stack developer with expertise in building scalable web applications and cloud infrastructure"
|
||||
/>
|
||||
|
||||
<section className="grid grid-cols-1 tablet:grid-cols-2 gap-8 max-w-7xl w-full">
|
||||
<section className="grid grid-cols-1 tablet:grid-cols-2 gap-6 smalltablet:gap-7 tablet:gap-8 max-w-7xl w-full">
|
||||
{/* Personal Info */}
|
||||
<div className="flex flex-col gap-4 h-full">
|
||||
<Card className="p-6 flex-1 gap-4">
|
||||
<h3 className="text-2xl font-bold">Personal Info</h3>
|
||||
<div className="flex flex-col gap-3 smalltablet:gap-4 h-full">
|
||||
<Card className="p-4 smalltablet:p-5 tablet:p-6 flex-1 gap-3 smalltablet:gap-4">
|
||||
<h3 className="text-xl smalltablet:text-2xl font-bold">Personal Info</h3>
|
||||
<Separator/>
|
||||
<div className="grid grid-cols-2 gap-6 items-center h-full">
|
||||
<div className="grid grid-cols-1 smalltablet:grid-cols-2 gap-4 smalltablet:gap-5 tablet:gap-6 items-center h-full">
|
||||
{PERSONAL_INFO.map((info, index) => (
|
||||
<InfoItem
|
||||
key={index}
|
||||
@@ -61,21 +61,21 @@ export default function About() {
|
||||
</div>
|
||||
|
||||
{/* Who I Am */}
|
||||
<div className="flex flex-col gap-4 h-full">
|
||||
<Card className="p-6 flex-1">
|
||||
<div className="flex flex-col gap-4">
|
||||
<h3 className="text-2xl font-bold">Who I Am</h3>
|
||||
<div className="flex flex-col gap-3 smalltablet:gap-4 h-full">
|
||||
<Card className="p-4 smalltablet:p-5 tablet:p-6 flex-1">
|
||||
<div className="flex flex-col gap-3 smalltablet:gap-4">
|
||||
<h3 className="text-xl smalltablet:text-2xl font-bold">Who I Am</h3>
|
||||
<Separator/>
|
||||
<p className="text-muted-foreground tablet:text-justify">
|
||||
<p className="text-sm smalltablet:text-base text-muted-foreground tablet:text-justify leading-relaxed">
|
||||
I'm Minjo Kim, a Full-Stack Developer and Bachelor in Computer Science at Seoul National University, Korea.
|
||||
I have experience in web development and cloud infrastructure, passionate about building scalable and efficient systems.
|
||||
</p>
|
||||
<p className="text-muted-foreground tablet:text-justify">
|
||||
<p className="text-sm smalltablet:text-base text-muted-foreground tablet:text-justify leading-relaxed">
|
||||
My academic background gave me solid knowledge in Algorithms, Data Structures, System Design, and Databases
|
||||
which I apply to create efficient and modern systems. I've delivered impactful solutions using TypeScript,
|
||||
React, Next.js, and Tailwind CSS.
|
||||
</p>
|
||||
<p className="text-muted-foreground tablet:text-justify">
|
||||
<p className="text-sm smalltablet:text-base text-muted-foreground tablet:text-justify leading-relaxed">
|
||||
I'm responsible for building full-stack applications, setting up Kubernetes clusters with ArgoCD for GitOps workflows,
|
||||
and implementing monitoring systems with Prometheus and Grafana. I focus on creating maintainable code and
|
||||
improving system performance and scalability.
|
||||
|
||||
@@ -62,52 +62,52 @@ export default function Contact() {
|
||||
|
||||
return (
|
||||
<div className="bg-muted">
|
||||
<main className="flex flex-col items-center justify-center gap-16 p-4 tablet:p-8 py-20">
|
||||
<main className="flex flex-col items-center justify-center gap-12 smalltablet:gap-14 tablet:gap-16 p-4 smalltablet:p-6 tablet:p-8 py-16 smalltablet:py-18 tablet:py-20">
|
||||
<SectionHeader
|
||||
title="Get In Touch"
|
||||
description="Have a project in mind or want to collaborate? I'd love to hear from you. Feel free to reach out through any of the channels below."
|
||||
/>
|
||||
|
||||
<div className="grid pc:grid-cols-2 gap-8 max-w-6xl mx-auto">
|
||||
<div className="grid tablet:grid-cols-2 gap-6 smalltablet:gap-7 tablet:gap-8 max-w-6xl mx-auto w-full">
|
||||
{/* Contact Info & Social Links */}
|
||||
<Card className="p-8 hover:shadow-lg transition-shadow">
|
||||
<h3 className="font-bold text-xl mb-6 flex items-center gap-2">
|
||||
<MapPin className="w-5 h-5 text-primary" />
|
||||
<Card className="p-5 smalltablet:p-6 tablet:p-8 hover:shadow-lg transition-shadow">
|
||||
<h3 className="font-bold text-lg smalltablet:text-xl mb-4 smalltablet:mb-5 tablet:mb-6 flex items-center gap-2">
|
||||
<MapPin className="w-4 h-4 smalltablet:w-5 smalltablet:h-5 text-primary" />
|
||||
Contact Information
|
||||
</h3>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-3 smalltablet:gap-4">
|
||||
{contactMethods.map((method, index) => (
|
||||
<a
|
||||
key={index}
|
||||
href={method.link}
|
||||
target={method.link.startsWith('http') ? '_blank' : undefined}
|
||||
rel={method.link.startsWith('http') ? 'noopener noreferrer' : undefined}
|
||||
className="flex items-center gap-4 p-4 rounded-lg hover:bg-accent transition-colors group"
|
||||
className="flex items-center gap-3 smalltablet:gap-4 p-3 smalltablet:p-4 rounded-lg hover:bg-accent transition-colors group"
|
||||
>
|
||||
<div className={`flex items-center justify-center w-12 h-12 rounded-full bg-muted group-hover:scale-110 transition-transform ${method.color}`}>
|
||||
<method.icon className="w-6 h-6" />
|
||||
<div className={`flex items-center justify-center w-10 h-10 smalltablet:w-12 smalltablet:h-12 rounded-full bg-muted group-hover:scale-110 transition-transform ${method.color}`}>
|
||||
<method.icon className="w-5 h-5 smalltablet:w-6 smalltablet:h-6" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm text-muted-foreground">{method.label}</p>
|
||||
<p className="font-medium truncate">{method.value}</p>
|
||||
<p className="text-xs smalltablet:text-sm text-muted-foreground">{method.label}</p>
|
||||
<p className="text-sm smalltablet:text-base font-medium truncate">{method.value}</p>
|
||||
</div>
|
||||
<ExternalLink className="w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" />
|
||||
<ExternalLink className="w-3.5 h-3.5 smalltablet:w-4 smalltablet:h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" />
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Contact Form */}
|
||||
<Card className="p-8 hover:shadow-xl transition-shadow">
|
||||
<h3 className="font-bold text-2xl mb-2">Send Me a Message</h3>
|
||||
<p className="text-muted-foreground mb-8">
|
||||
<Card className="p-5 smalltablet:p-6 tablet:p-8 hover:shadow-xl transition-shadow">
|
||||
<h3 className="font-bold text-xl smalltablet:text-2xl mb-1.5 smalltablet:mb-2">Send Me a Message</h3>
|
||||
<p className="text-sm smalltablet:text-base text-muted-foreground mb-6 smalltablet:mb-8">
|
||||
Fill out the form below and I'll get back to you as soon as possible.
|
||||
</p>
|
||||
|
||||
<form onSubmit={handleSubmit} className="flex flex-col gap-6">
|
||||
<div className="grid tablet:grid-cols-2 gap-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<label htmlFor="name" className="text-sm font-medium">
|
||||
<form onSubmit={handleSubmit} className="flex flex-col gap-4 smalltablet:gap-5 tablet:gap-6">
|
||||
<div className="grid tablet:grid-cols-2 gap-4 smalltablet:gap-5 tablet:gap-6">
|
||||
<div className="flex flex-col gap-1.5 smalltablet:gap-2">
|
||||
<label htmlFor="name" className="text-xs smalltablet:text-sm font-medium">
|
||||
Your Name <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<Input
|
||||
@@ -117,12 +117,12 @@ export default function Contact() {
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="h-12"
|
||||
className="h-10 smalltablet:h-12"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label htmlFor="email" className="text-sm font-medium">
|
||||
<div className="flex flex-col gap-1.5 smalltablet:gap-2">
|
||||
<label htmlFor="email" className="text-xs smalltablet:text-sm font-medium">
|
||||
Your Email <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<Input
|
||||
@@ -133,13 +133,13 @@ export default function Contact() {
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="h-12"
|
||||
className="h-10 smalltablet:h-12"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label htmlFor="subject" className="text-sm font-medium">
|
||||
<div className="flex flex-col gap-1.5 smalltablet:gap-2">
|
||||
<label htmlFor="subject" className="text-xs smalltablet:text-sm font-medium">
|
||||
Subject <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<Input
|
||||
@@ -149,12 +149,12 @@ export default function Contact() {
|
||||
value={formData.subject}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="h-12"
|
||||
className="h-10 smalltablet:h-12"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label htmlFor="message" className="text-sm font-medium">
|
||||
<div className="flex flex-col gap-1.5 smalltablet:gap-2">
|
||||
<label htmlFor="message" className="text-xs smalltablet:text-sm font-medium">
|
||||
Message <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<Textarea
|
||||
@@ -164,15 +164,15 @@ export default function Contact() {
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
required
|
||||
rows={8}
|
||||
className="resize-none"
|
||||
rows={6}
|
||||
className="resize-none smalltablet:rows-8"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button type="submit" size="lg" className="w-full tablet:w-auto tablet:self-end group">
|
||||
<span className="flex items-center gap-2">
|
||||
Send Message
|
||||
<Send className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
|
||||
<Send className="w-3.5 h-3.5 smalltablet:w-4 smalltablet:h-4 group-hover:translate-x-1 transition-transform" />
|
||||
</span>
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useRef } from "react";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { useTheme } from "next-themes";
|
||||
import SectionHeader from "@/components/landing/section-header";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -14,6 +14,16 @@ const sections: { id: Section; label: string; panels: number }[] = [
|
||||
{ id: "network", label: "Network", panels: 6 },
|
||||
];
|
||||
|
||||
// Loading Skeleton 컴포넌트
|
||||
const LoadingSkeleton = () => (
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-gray-100 dark:bg-gray-800 animate-pulse">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="w-8 h-8 border-4 border-gray-300 dark:border-gray-600 border-t-gray-600 dark:border-t-gray-300 rounded-full animate-spin" />
|
||||
<div className="text-sm text-gray-500 dark:text-gray-400">Loading dashboard...</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default function GrafanaPage() {
|
||||
const [activeSection, setActiveSection] = useState<Section>("overview");
|
||||
const { theme } = useTheme();
|
||||
@@ -30,15 +40,6 @@ export default function GrafanaPage() {
|
||||
const GrafanaPanel = ({ panelId }: { panelId: number }) => {
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
// Grafana 섹션이 화면에 보이지 않으면 로딩하지 않음
|
||||
// if (!isVisible) {
|
||||
// return (
|
||||
// <div className="relative w-full h-full">
|
||||
// <LoadingSkeleton />
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
return (
|
||||
<div className="relative w-full h-full">
|
||||
{/* {(!loaded || isLoading) && <LoadingSkeleton />} */}
|
||||
@@ -46,7 +47,7 @@ export default function GrafanaPage() {
|
||||
<iframe
|
||||
key={`${panelId}-dark-${theme}`}
|
||||
src={getGrafanaUrl(panelId, "dark")}
|
||||
className="w-full h-full"
|
||||
className="w-full h-full border"
|
||||
style={{ display: loaded ? 'block' : 'none' }}
|
||||
onLoad={() => setLoaded(true)}
|
||||
/>
|
||||
@@ -64,23 +65,23 @@ export default function GrafanaPage() {
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="page-container" ref={sectionRef}>
|
||||
<main className="flex flex-col items-center justify-center gap-12 smalltablet:gap-14 tablet:gap-16 p-4 smalltablet:p-6 tablet:p-8 py-16 smalltablet:py-18 tablet:py-20" ref={sectionRef}>
|
||||
<SectionHeader
|
||||
title="Monitoring"
|
||||
description="Real-time Kubernetes cluster monitoring with Grafana dashboards"
|
||||
/>
|
||||
|
||||
{/* 섹션 선택 버튼 */}
|
||||
<div className="flex gap-2 flex-wrap justify-center mb-4">
|
||||
<div className="flex gap-1.5 smalltablet:gap-2 flex-wrap justify-center">
|
||||
{sections.map((section) => (
|
||||
<Button
|
||||
key={section.id}
|
||||
onClick={() => setActiveSection(section.id)}
|
||||
variant={activeSection === section.id ? "default" : "outline"}
|
||||
className="transition-all text-xs sm:text-sm"
|
||||
className="transition-all text-[10px] smalltablet:text-xs tablet:text-sm px-2 smalltablet:px-3 py-1 smalltablet:py-2 h-auto"
|
||||
>
|
||||
{section.label}
|
||||
<span className="ml-1 sm:ml-2 text-xs opacity-60">
|
||||
<span className="ml-1 smalltablet:ml-1.5 tablet:ml-2 text-[9px] smalltablet:text-xs opacity-60">
|
||||
({section.panels})
|
||||
</span>
|
||||
</Button>
|
||||
@@ -89,29 +90,29 @@ export default function GrafanaPage() {
|
||||
|
||||
{/* Overview 섹션 */}
|
||||
{activeSection === "overview" && (
|
||||
<div className="flex flex-col lg:flex-row gap-2 justify-center w-full h-full">
|
||||
<div className="flex flex-col desktop:flex-row gap-1.5 smalltablet:gap-2 justify-center w-full h-full">
|
||||
{/* 왼쪽 2개 열 (CPU, RAM) */}
|
||||
<div className="flex flex-col sm:flex-row gap-2 w-full lg:flex-1">
|
||||
<div className="flex flex-col smalltablet:flex-row gap-1.5 smalltablet:gap-2 w-full desktop:flex-1">
|
||||
{/* Global CPU Usage 열 */}
|
||||
<div className="flex flex-col gap-2 w-full sm:flex-1">
|
||||
<div className="flex flex-col gap-1.5 smalltablet:gap-2 w-full smalltablet:flex-1">
|
||||
{/* Global CPU Usage (id:77) - w:6, h:8 */}
|
||||
<div className="w-full aspect-5/4 theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full aspect-5/4 theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={77} />
|
||||
</div>
|
||||
{/* CPU Usage (id:37) - w:6, h:4 */}
|
||||
<div className="w-full aspect-5/2 theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full aspect-5/2 theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={37} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Global RAM Usage 열 */}
|
||||
<div className="flex flex-col gap-2 w-full sm:flex-1">
|
||||
<div className="flex flex-col gap-1.5 smalltablet:gap-2 w-full smalltablet:flex-1">
|
||||
{/* Global RAM Usage (id:78) - w:6, h:8 */}
|
||||
<div className="w-full aspect-5/4 theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full aspect-5/4 theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={78} />
|
||||
</div>
|
||||
{/* RAM Usage (id:39) - w:6, h:4 */}
|
||||
<div className="w-full aspect-5/2 theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full aspect-5/2 theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={39} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -119,7 +120,7 @@ export default function GrafanaPage() {
|
||||
|
||||
{/* 오른쪽 넓은 열 (Kubernetes Resource Count) */}
|
||||
{/* Kubernetes Resource Count (id:52) - w:10, h:12 */}
|
||||
<div className="w-full lg:flex-1 lg:max-w-[40%] theme-background rounded-lg overflow-hidden flex items-stretch">
|
||||
<div className="w-full aspect-5/7 smalltablet:aspect-video desktop:flex-1 desktop:max-w-[40%] theme-background rounded-md smalltablet:rounded-lg overflow-hidden flex items-stretch">
|
||||
<GrafanaPanel panelId={52} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -127,51 +128,51 @@ export default function GrafanaPage() {
|
||||
|
||||
{/* Resources 섹션 */}
|
||||
{activeSection === "resources" && (
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<div className="flex flex-col gap-1.5 smalltablet:gap-2 w-full">
|
||||
{/* Row 1 */}
|
||||
<div className="flex flex-col lg:flex-row gap-2 justify-center w-full">
|
||||
<div className="flex flex-col desktop:flex-row gap-1.5 smalltablet:gap-2 justify-center w-full">
|
||||
{/* Cluster CPU Utilization (id:72) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={72} />
|
||||
</div>
|
||||
{/* Cluster Memory Utilization (id:55) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={55} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<div className="flex flex-col lg:flex-row gap-2 justify-center w-full">
|
||||
<div className="flex flex-col desktop:flex-row gap-1.5 smalltablet:gap-2 justify-center w-full">
|
||||
{/* CPU Utilization by namespace (id:46) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={46} />
|
||||
</div>
|
||||
{/* Memory Utilization by namespace (id:50) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={50} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 3 */}
|
||||
<div className="flex flex-col lg:flex-row gap-2 justify-center w-full">
|
||||
<div className="flex flex-col desktop:flex-row gap-1.5 smalltablet:gap-2 justify-center w-full">
|
||||
{/* CPU Utilization by instance (id:54) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={54} />
|
||||
</div>
|
||||
{/* Memory Utilization by instance (id:73) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={73} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 4 */}
|
||||
<div className="flex flex-col lg:flex-row gap-2 justify-center w-full">
|
||||
<div className="flex flex-col desktop:flex-row gap-1.5 smalltablet:gap-2 justify-center w-full">
|
||||
{/* CPU Throttled seconds by namespace (id:82) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={82} />
|
||||
</div>
|
||||
{/* CPU Core Throttled by instance (id:83) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={83} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -180,27 +181,27 @@ export default function GrafanaPage() {
|
||||
|
||||
{/* Kubernetes 섹션 */}
|
||||
{activeSection === "kubernetes" && (
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<div className="flex flex-col gap-1.5 smalltablet:gap-2 w-full">
|
||||
{/* Row 1 */}
|
||||
<div className="flex flex-col lg:flex-row gap-2 justify-center w-full">
|
||||
<div className="flex flex-col desktop:flex-row gap-1.5 smalltablet:gap-2 justify-center w-full">
|
||||
{/* Kubernetes Pods QoS classes (id:84) - w:12, h:9 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={84} />
|
||||
</div>
|
||||
{/* Kubernetes Pods Status Reason (id:85) - w:12, h:9 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={85} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<div className="flex flex-col lg:flex-row gap-2 justify-center w-full">
|
||||
<div className="flex flex-col desktop:flex-row gap-1.5 smalltablet:gap-2 justify-center w-full">
|
||||
{/* OOM Events by namespace (id:87) - w:12, h:9 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={87} />
|
||||
</div>
|
||||
{/* Container Restarts by namespace (id:88) - w:12, h:9 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={88} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -209,39 +210,39 @@ export default function GrafanaPage() {
|
||||
|
||||
{/* Network 섹션 */}
|
||||
{activeSection === "network" && (
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<div className="flex flex-col gap-1.5 smalltablet:gap-2 w-full">
|
||||
{/* Row 1 */}
|
||||
<div className="flex flex-col lg:flex-row gap-2 justify-center w-full">
|
||||
<div className="flex flex-col desktop:flex-row gap-1.5 smalltablet:gap-2 justify-center w-full">
|
||||
{/* Global Network Utilization by device (id:44) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={44} />
|
||||
</div>
|
||||
{/* Network Saturation - Packets dropped (id:53) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={53} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<div className="flex flex-col lg:flex-row gap-2 justify-center w-full">
|
||||
<div className="flex flex-col desktop:flex-row gap-1.5 smalltablet:gap-2 justify-center w-full">
|
||||
{/* Network Received by namespace (id:79) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={79} />
|
||||
</div>
|
||||
{/* Total Network Received by instance (id:80) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={80} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 3 */}
|
||||
<div className="flex flex-col lg:flex-row gap-2 justify-center w-full">
|
||||
<div className="flex flex-col desktop:flex-row gap-1.5 smalltablet:gap-2 justify-center w-full">
|
||||
{/* Network Received (without loopback) by instance (id:56) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={56} />
|
||||
</div>
|
||||
{/* Network Received (loopback only) by instance (id:81) - w:12, h:8 */}
|
||||
<div className="w-full lg:flex-1 aspect-video theme-background rounded-lg overflow-hidden">
|
||||
<div className="w-full desktop:flex-1 aspect-5/4 smalltablet:aspect-video theme-background rounded-md smalltablet:rounded-lg overflow-hidden">
|
||||
<GrafanaPanel panelId={81} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,13 +16,13 @@ export default function Hero() {
|
||||
className="absolute inset-0 -z-10"
|
||||
/>
|
||||
<div className="relative w-full h-full flex items-center justify-center">
|
||||
<div className="flex flex-col items-center justify-center gap-12 text-center">
|
||||
<div className="flex flex-col items-center justify-center gap-12 px-5">
|
||||
<h2 className="font-bold text-5xl tablet:text-7xl text-center bg-linear-to-r from-gray-900 to-gray-600 dark:from-gray-100 dark:to-gray-400 bg-clip-text text-transparent">
|
||||
<div className="flex flex-col items-center justify-center gap-8 smalltablet:gap-10 tablet:gap-12 text-center">
|
||||
<div className="flex flex-col items-center justify-center gap-8 smalltablet:gap-10 tablet:gap-12 px-4 smalltablet:px-5">
|
||||
<h2 className="font-bold text-4xl smalltablet:text-5xl tablet:text-6xl desktop:text-7xl text-center bg-linear-to-r from-gray-900 to-gray-600 dark:from-gray-100 dark:to-gray-400 bg-clip-text text-transparent">
|
||||
Full Stack Developer
|
||||
</h2>
|
||||
<div className="max-w-3xl">
|
||||
<p className="text-2xl tablet:text-3xl text-center leading-[160%]">
|
||||
<div className="max-w-sm smalltablet:max-w-xl tablet:max-w-2xl desktop:max-w-3xl">
|
||||
<p className="text-lg smalltablet:text-xl tablet:text-2xl desktop:text-3xl text-center leading-[150%] smalltablet:leading-[160%]">
|
||||
Creating beautiful and functional web experiences with modern technologies
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -35,56 +35,56 @@ function ProjectCard({ title, description, tags, imageSrc, githubUrl, liveUrl, d
|
||||
fill
|
||||
className="object-cover border-b-2 border-gray-200"
|
||||
placeholder="blur"
|
||||
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
||||
sizes="(max-width: 600px) 100vw, (max-width: 990px) 100vw, (max-width: 1200px) 50vw, 50vw"
|
||||
/>
|
||||
</div>
|
||||
<div className="px-6 pt-6 pb-4 flex flex-col gap-3">
|
||||
<h3 className="font-semibold text-2xl">{title}</h3>
|
||||
<p className="text-muted-foreground font-extralight">{description}</p>
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<div className="px-4 smalltablet:px-5 tablet:px-6 pt-4 smalltablet:pt-5 tablet:pt-6 pb-3 smalltablet:pb-4 flex flex-col gap-2 smalltablet:gap-3">
|
||||
<h3 className="font-semibold text-lg smalltablet:text-xl tablet:text-2xl">{title}</h3>
|
||||
<p className="text-sm smalltablet:text-base text-muted-foreground font-extralight">{description}</p>
|
||||
<div className="flex gap-1.5 smalltablet:gap-2 flex-wrap">
|
||||
{tags.map((tag) => (
|
||||
<Button key={tag} variant="outline" className="text-xs px-3 py-1">
|
||||
<Button key={tag} variant="outline" className="text-[10px] smalltablet:text-xs px-2 smalltablet:px-3 py-0.5 smalltablet:py-1 h-auto">
|
||||
{tag}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-6">
|
||||
<div className="px-4 smalltablet:px-5 tablet:px-6">
|
||||
<Separator />
|
||||
</div>
|
||||
<div className="px-6 py-4 flex gap-4 flex-wrap">
|
||||
<div className="px-4 smalltablet:px-5 tablet:px-6 py-3 smalltablet:py-4 flex gap-3 smalltablet:gap-4 flex-wrap">
|
||||
{liveUrl && (
|
||||
<Link href={liveUrl} target="_blank" rel="noopener noreferrer" aria-label="Live Demo">
|
||||
<div className="flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors cursor-pointer">
|
||||
<ExternalLink className="w-5 h-5" />
|
||||
<ExternalLink className="w-4 h-4 smalltablet:w-5 smalltablet:h-5" />
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
{githubUrl && (
|
||||
<Link href={githubUrl} target="_blank" rel="noopener noreferrer" aria-label="GitHub">
|
||||
<div className="flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors cursor-pointer">
|
||||
<Github className="w-5 h-5" />
|
||||
<Github className="w-4 h-4 smalltablet:w-5 smalltablet:h-5" />
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
{docsUrl && (
|
||||
<Link href={docsUrl} target="_blank" rel="noopener noreferrer" aria-label="Documentation">
|
||||
<div className="flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors cursor-pointer">
|
||||
<BookOpen className="w-5 h-5" />
|
||||
<BookOpen className="w-4 h-4 smalltablet:w-5 smalltablet:h-5" />
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
{docusaurusUrl && (
|
||||
<Link href={docusaurusUrl} target="_blank" rel="noopener noreferrer" aria-label="Docusaurus">
|
||||
<div className="flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors cursor-pointer">
|
||||
<FileText className="w-5 h-5" />
|
||||
<FileText className="w-4 h-4 smalltablet:w-5 smalltablet:h-5" />
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
{monitoringUrl && (
|
||||
<Link href={monitoringUrl} target="_blank" rel="noopener noreferrer" aria-label="Monitoring">
|
||||
<div className="flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors cursor-pointer">
|
||||
<BarChart3 className="w-5 h-5" />
|
||||
<BarChart3 className="w-4 h-4 smalltablet:w-5 smalltablet:h-5" />
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
@@ -95,13 +95,13 @@ function ProjectCard({ title, description, tags, imageSrc, githubUrl, liveUrl, d
|
||||
|
||||
export default function Projects() {
|
||||
return (
|
||||
<main className="flex bg-muted flex-col items-center justify-center gap-16 p-4 tablet:p-8 py-20">
|
||||
<main className="flex bg-muted flex-col items-center justify-center gap-12 smalltablet:gap-14 tablet:gap-16 p-4 smalltablet:p-6 tablet:p-8 py-16 smalltablet:py-18 tablet:py-20">
|
||||
<SectionHeader
|
||||
title="Featured Projects"
|
||||
description="Some of my recent work and side projects"
|
||||
/>
|
||||
|
||||
<section className="grid grid-cols-1 pc:grid-cols-2 gap-6 pc:gap-8 max-w-[1440px] w-full">
|
||||
<section className="grid grid-cols-1 desktop:grid-cols-2 gap-4 smalltablet:gap-5 tablet:gap-6 desktop:gap-8 max-w-[1440px] w-full">
|
||||
<ProjectCard
|
||||
title="Joossam English"
|
||||
description="English learning platform for Korean students"
|
||||
|
||||
@@ -5,11 +5,11 @@ interface SectionHeaderProps {
|
||||
|
||||
export default function SectionHeader({ title, description }: SectionHeaderProps) {
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-4 max-w-3xl text-center">
|
||||
<h2 className="font-bold text-4xl tablet:text-5xl pc:text-6xl bg-linear-to-r from-gray-900 to-gray-600 dark:from-gray-100 dark:to-gray-400 bg-clip-text text-transparent">
|
||||
<div className="flex flex-col items-center gap-3 smalltablet:gap-4 max-w-xl smalltablet:max-w-2xl tablet:max-w-3xl text-center px-4">
|
||||
<h2 className="font-bold text-3xl smalltablet:text-4xl tablet:text-5xl desktop:text-6xl bg-linear-to-r from-gray-900 to-gray-600 dark:from-gray-100 dark:to-gray-400 bg-clip-text text-transparent">
|
||||
{title}
|
||||
</h2>
|
||||
<p className="text-lg tablet:text-xl text-muted-foreground max-w-2xl">
|
||||
<p className="text-base smalltablet:text-lg tablet:text-xl text-muted-foreground max-w-sm smalltablet:max-w-lg tablet:max-w-2xl">
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -19,36 +19,36 @@ function SkillCard({ icon: Icon, title, description, mainSkills, subSkills }: Sk
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
|
||||
return (
|
||||
<Card className="p-5 w-full h-full gap-4 relative">
|
||||
<Card className="p-4 smalltablet:p-5 w-full h-full gap-3 smalltablet:gap-4 relative">
|
||||
{/* Toggle Button - Top Right Corner */}
|
||||
{subSkills.length > 0 && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
className="absolute top-6 right-6 p-2 h-8 w-8"
|
||||
className="absolute top-4 right-4 smalltablet:top-6 smalltablet:right-6 p-2 h-8 w-8"
|
||||
>
|
||||
<ChevronDown className={`w-16 h-16 transition-transform ${isExpanded ? 'rotate-180' : ''}`} />
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex items-center justify-center min-w-12 min-h-12 rounded-full bg-muted w-fit">
|
||||
<Icon className="min-w-8 min-h-8" />
|
||||
<div className="flex flex-col gap-3 smalltablet:gap-4">
|
||||
<div className="flex items-center justify-center min-w-10 min-h-10 smalltablet:min-w-12 smalltablet:min-h-12 rounded-full bg-muted w-fit">
|
||||
<Icon className="min-w-6 min-h-6 smalltablet:min-w-8 smalltablet:min-h-8" />
|
||||
</div>
|
||||
<CardTitle>
|
||||
<h3 className="text-lg">{title}</h3>
|
||||
<h3 className="text-base smalltablet:text-lg">{title}</h3>
|
||||
</CardTitle>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-6 justify-between h-full">
|
||||
<p className="font-extralight">{description}</p>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-4 smalltablet:gap-6 justify-between h-full">
|
||||
<p className="text-sm smalltablet:text-base font-extralight">{description}</p>
|
||||
<div className="flex flex-col gap-3 smalltablet:gap-4">
|
||||
<Separator />
|
||||
{/* Main Skills */}
|
||||
<div className="flex gap-3 flex-wrap">
|
||||
<div className="flex gap-2 smalltablet:gap-3 flex-wrap">
|
||||
{mainSkills.map((skill) => (
|
||||
<span key={skill} className="text-sm font-medium text-gray-800 dark:text-gray-100">
|
||||
<span key={skill} className="text-xs smalltablet:text-sm font-medium text-gray-800 dark:text-gray-100">
|
||||
{skill}
|
||||
</span>
|
||||
))}
|
||||
@@ -56,10 +56,10 @@ function SkillCard({ icon: Icon, title, description, mainSkills, subSkills }: Sk
|
||||
{/* Sub Skills - Toggleable */}
|
||||
{subSkills.length > 0 && (
|
||||
<div className={`overflow-hidden transition-all duration-300 ease-in-out ${isExpanded ? 'max-h-96' : 'max-h-0'}`}>
|
||||
<Separator className="opacity-50 mb-4" />
|
||||
<div className="flex gap-3 flex-wrap">
|
||||
<Separator className="opacity-50 mb-3 smalltablet:mb-4" />
|
||||
<div className="flex gap-2 smalltablet:gap-3 flex-wrap">
|
||||
{subSkills.map((skill) => (
|
||||
<span key={skill} className="text-sm font-extralight text-gray-600 dark:text-gray-300 opacity-80">
|
||||
<span key={skill} className="text-xs smalltablet:text-sm font-extralight text-gray-600 dark:text-gray-300 opacity-80">
|
||||
{skill}
|
||||
</span>
|
||||
))}
|
||||
@@ -74,13 +74,13 @@ function SkillCard({ icon: Icon, title, description, mainSkills, subSkills }: Sk
|
||||
|
||||
export default function Skills() {
|
||||
return (
|
||||
<main className="flex max-w-7xl mx-auto flex-col items-center justify-center gap-16 p-4 tablet:p-8 py-20">
|
||||
<main className="flex max-w-7xl mx-auto flex-col items-center justify-center gap-12 smalltablet:gap-14 tablet:gap-16 p-4 smalltablet:p-6 tablet:p-8 py-16 smalltablet:py-18 tablet:py-20">
|
||||
<SectionHeader
|
||||
title="Skills & Expertise"
|
||||
description="Technologies and tools I work with to build amazing web applications"
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-1 tablet:grid-cols-2 pc:grid-cols-3 gap-6">
|
||||
<div className="grid grid-cols-1 smalltablet:grid-cols-2 desktop:grid-cols-3 gap-4 smalltablet:gap-5 tablet:gap-6">
|
||||
<SkillCard
|
||||
icon={Code}
|
||||
title="Frontend Development"
|
||||
|
||||
@@ -26,25 +26,25 @@ const Footer = () => {
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
return (
|
||||
<footer className="my-12 mx-6 tablet:m-12 pc:mx-24 pc:mt-20">
|
||||
<div className="flex items-center gap-8 mb-6 px-4">
|
||||
<footer className="my-8 mx-4 smalltablet:my-10 smalltablet:mx-6 tablet:m-12 desktop:mx-24 desktop:mt-20">
|
||||
<div className="flex flex-wrap items-center gap-4 smalltablet:gap-6 tablet:gap-8 mb-4 smalltablet:mb-6 px-2 smalltablet:px-4">
|
||||
{FOOTER_MENU_ITEMS.map((item) => (
|
||||
<Link
|
||||
key={item.name}
|
||||
href={item.path}
|
||||
className="text-lg font-light hover:opacity-70 transition-opacity"
|
||||
className="text-sm smalltablet:text-base tablet:text-lg font-light hover:opacity-70 transition-opacity"
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<Separator />
|
||||
<div className="flex w-full pt-4">
|
||||
<div className="w-full flex flex-col justify-between items-center gap-4 tablet:flex-row">
|
||||
<p className="text-sm text-center text-muted-foreground">
|
||||
<div className="flex w-full pt-3 smalltablet:pt-4">
|
||||
<div className="w-full flex flex-col justify-between items-center gap-3 smalltablet:gap-4 tablet:flex-row">
|
||||
<p className="text-xs smalltablet:text-sm text-center text-muted-foreground">
|
||||
© {currentYear} All rights reserved
|
||||
</p>
|
||||
<div className="flex justify-center gap-8">
|
||||
<div className="flex justify-center gap-6 smalltablet:gap-8">
|
||||
{SOCIAL_MEDIA.map(({ name, icon: Icon, href }) => (
|
||||
<Link
|
||||
key={name}
|
||||
@@ -53,7 +53,7 @@ const Footer = () => {
|
||||
rel="noopener noreferrer"
|
||||
className="hover:opacity-70 transition-opacity"
|
||||
>
|
||||
<Icon className="w-6 h-6" />
|
||||
<Icon className="w-5 h-5 smalltablet:w-6 smalltablet:h-6" />
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -31,14 +31,14 @@ const HeaderProfile = ({
|
||||
href="/"
|
||||
className={hasOrder ? 'order-2 tablet:order-1' : ''}
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-3 smalltablet:gap-4">
|
||||
{showImage && (
|
||||
<div
|
||||
className={`w-10 h-10 pc:w-14 pc:h-14 rounded-full bg-gray-300 dark:bg-gray-600 ${imageClassName || ''}`}
|
||||
className={`w-9 h-9 smalltablet:w-10 smalltablet:h-10 desktop:w-14 desktop:h-14 rounded-full bg-gray-300 dark:bg-gray-600 ${imageClassName || ''}`}
|
||||
/>
|
||||
)}
|
||||
{showName && (
|
||||
<h1 className="text-base pc:text-lg transition-colors font-bold">
|
||||
<h1 className="text-sm smalltablet:text-base desktop:text-lg transition-colors font-bold">
|
||||
MINJO KIM
|
||||
</h1>
|
||||
)}
|
||||
@@ -72,12 +72,12 @@ const HeaderMenuItemsDesktop = () => {
|
||||
{HEADER_MENU_ITEMS.map((item) => (
|
||||
<div
|
||||
key={item.name}
|
||||
className="px-2 pc:px-6 transition-all"
|
||||
className="px-2 tablet:px-4 desktop:px-6 transition-all"
|
||||
>
|
||||
<Link
|
||||
href={item.path}
|
||||
onClick={(e) => handleScrollClick(e, item.path, item.isScroll)}
|
||||
className="font-extralight text-sm pc:text-base duration-100 ease-in hover:border-b-2 hover:border-b-black hover:dark:border-b-white pb-1"
|
||||
className="font-extralight text-xs tablet:text-sm desktop:text-base duration-100 ease-in hover:border-b-2 hover:border-b-black hover:dark:border-b-white pb-1"
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
@@ -131,22 +131,22 @@ const HeaderMenuItemsMobile = () => {
|
||||
<X className="w-6 h-6" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-between h-full py-16">
|
||||
<div className="flex flex-col w-full h-full justify-center items-center gap-20">
|
||||
<div className="flex flex-col items-center justify-between h-full py-12 smalltablet:py-16">
|
||||
<div className="flex flex-col w-full h-full justify-center items-center gap-16 smalltablet:gap-20">
|
||||
<HeaderProfile
|
||||
showImage={false}
|
||||
hasOrder={false}
|
||||
/>
|
||||
<div className="flex flex-col items-center gap-12">
|
||||
<div className="flex flex-col items-center gap-8 smalltablet:gap-12">
|
||||
{HEADER_MENU_ITEMS.map(item => (
|
||||
<div
|
||||
key={item.name}
|
||||
className="px-4 pc:px-8 transition-all items-center"
|
||||
className="px-4 smalltablet:px-6 desktop:px-8 transition-all items-center"
|
||||
>
|
||||
<Link
|
||||
href={item.path}
|
||||
onClick={(e) => handleScrollClick(e, item.path, item.isScroll)}
|
||||
className="text-xl duration-100 ease-in hover:border-b-2 hover:border-b-brand-primary hover:dark:border-b-white pb-1"
|
||||
className="text-lg smalltablet:text-xl duration-100 ease-in hover:border-b-2 hover:border-b-brand-primary hover:dark:border-b-white pb-1"
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
@@ -167,7 +167,7 @@ const Header = () => {
|
||||
<header
|
||||
className="fixed h-[70px] top-0 z-50 w-full border-b border-border bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60"
|
||||
>
|
||||
<div className="flex justify-between items-center tracking-wider tablet:tracking-widest font-brand-book px-4 pc:px-8 py-4 max-w-[1920px] mx-auto">
|
||||
<div className="flex justify-between items-center tracking-wider tablet:tracking-widest font-brand-book px-4 smalltablet:px-6 desktop:px-8 py-4 max-w-[1920px] mx-auto">
|
||||
<HeaderProfile
|
||||
showImage={false}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user