feat: migrate header component

This commit is contained in:
ArraysID
2025-04-27 05:28:37 +07:00
parent 53b069f242
commit b4708ab2aa
9 changed files with 196 additions and 20 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

+143
View File
@@ -0,0 +1,143 @@
'use client';
import {
Button,
MenuIcon,
XIcon,
} from '@imphnen-frontend-service/shadcn-ui/atoms';
import { cn } from '@imphnen-frontend-service/utils';
import Image from 'next/image';
import Link from 'next/link';
import { useEffect, useState } from 'react';
export function Header() {
const [isScrolled, setIsScrolled] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 10);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
return (
<header
className={cn(
'sticky top-0 z-50 w-full transition-all duration-300',
isScrolled
? 'bg-background/80 backdrop-blur-md border-b shadow-sm'
: 'bg-transparent'
)}
>
<div className="container flex h-16 items-center justify-between">
<div className="flex items-center gap-2">
<div className="relative overflow-hidden rounded">
<Image
src="/logo.png"
alt="IMPHNEN Logo"
width={64}
height={64}
className="object-cover"
/>
</div>
</div>
{/* Desktop Navigation */}
<nav className="hidden md:flex items-center gap-8">
<Link href="#fitur" className="text-sm font-medium relative group">
<span className="transition-colors hover:text-primary">Fitur</span>
<span className="absolute -bottom-1 left-0 w-0 h-0.5 bg-primary transition-all duration-300 group-hover:w-full"></span>
</Link>
<Link
href="#komunitas"
className="text-sm font-medium relative group"
>
<span className="transition-colors hover:text-primary">
Komunitas
</span>
<span className="absolute -bottom-1 left-0 w-0 h-0.5 bg-primary transition-all duration-300 group-hover:w-full"></span>
</Link>
<Link
href="#sumber-belajar"
className="text-sm font-medium relative group"
>
<span className="transition-colors hover:text-primary">
Sumber Belajar
</span>
<span className="absolute -bottom-1 left-0 w-0 h-0.5 bg-primary transition-all duration-300 group-hover:w-full"></span>
</Link>
<Link
href="#testimoni"
className="text-sm font-medium relative group"
>
<span className="transition-colors hover:text-primary">
Testimoni
</span>
<span className="absolute -bottom-1 left-0 w-0 h-0.5 bg-primary transition-all duration-300 group-hover:w-full"></span>
</Link>
</nav>
<div className="flex items-center gap-4">
<Button className="hidden md:flex bg-gradient-to-r from-primary to-blue-400 hover:from-primary/90 hover:to-blue-400/90 transition-all duration-300">
Gabung Discord
</Button>
{/* Mobile Menu Button */}
<Button
variant="ghost"
size="icon"
className="md:hidden"
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
>
{mobileMenuOpen ? (
<XIcon className="h-6 w-6" />
) : (
<MenuIcon className="h-6 w-6" />
)}
</Button>
</div>
</div>
{/* Mobile Menu */}
{mobileMenuOpen && (
<div className="md:hidden border-t bg-background/95 backdrop-blur-md">
<nav className="container flex flex-col py-4 text-center">
<Link
href="#fitur"
className="py-3 text-sm font-medium border-b border-border/50"
onClick={() => setMobileMenuOpen(false)}
>
Fitur
</Link>
<Link
href="#komunitas"
className="py-3 text-sm font-medium border-b border-border/50"
onClick={() => setMobileMenuOpen(false)}
>
Komunitas
</Link>
<Link
href="#sumber-belajar"
className="py-3 text-sm font-medium border-b border-border/50"
onClick={() => setMobileMenuOpen(false)}
>
Sumber Belajar
</Link>
<Link
href="#testimoni"
className="py-3 text-sm font-medium"
onClick={() => setMobileMenuOpen(false)}
>
Testimoni
</Link>
<Button className="mt-4 bg-gradient-to-r from-primary to-blue-400 hover:from-primary/90 hover:to-blue-400/90">
Gabung Discord
</Button>
</nav>
</div>
)}
</header>
);
}
+6 -2
View File
@@ -1,8 +1,12 @@
import { type Metadata } from 'next';
import { Inter } from 'next/font/google';
import '../styles/globals.css';
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
title: 'IMPHNEN',
title: 'IMPHNEN - Ingin Menjadi Programmer Handal?',
description: 'Komunitas belajar programming untuk semua level',
};
export default function RootLayout({
@@ -12,7 +16,7 @@ export default function RootLayout({
}) {
return (
<html lang="id" suppressHydrationWarning>
<body>{children}</body>
<body className={inter.className}>{children}</body>
</html>
);
}
+5 -5
View File
@@ -1,10 +1,10 @@
import { Button } from '@imphnen-frontend-service/shadcn-ui/atoms';
import { Header } from './_components/header';
export default function Page() {
return (
<>
<h1 className="text-2xl underline">Hello World</h1>
<Button>Click Me</Button>
</>
<div className="flex min-h-screen flex-col">
<Header />
<main className="flex-1"></main>
</div>
);
}
+10
View File
@@ -13,6 +13,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.503.0",
"react-icons": "^5.5.0",
"tailwind-merge": "^3.2.0",
"tailwindcss": "^4.1.4"
},
@@ -1463,6 +1464,15 @@
"node": ">=0.10.0"
}
},
"node_modules/react-icons": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
"integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
"license": "MIT",
"peerDependencies": {
"react": "*"
}
},
"node_modules/rollup": {
"version": "4.40.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.0.tgz",
+1
View File
@@ -15,6 +15,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.503.0",
"react-icons": "^5.5.0",
"tailwind-merge": "^3.2.0",
"tailwindcss": "^4.1.4"
},
+3
View File
@@ -0,0 +1,3 @@
import { LuMenu as MenuIcon, LuX as XIcon } from 'react-icons/lu';
export { MenuIcon, XIcon };
+1
View File
@@ -1 +1,2 @@
export * from './button';
export * from './icons';
+27 -13
View File
@@ -42,15 +42,15 @@
}
:root {
--radius: 0.625rem;
--radius: 1rem;
--background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823);
--card: oklch(1 0 0);
--card-foreground: oklch(0.141 0.005 285.823);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.141 0.005 285.823);
--primary: oklch(0.21 0.006 285.885);
--primary-foreground: oklch(0.985 0 0);
--primary: oklch(0.623 0.214 259.815);
--primary-foreground: oklch(0.97 0.014 254.604);
--secondary: oklch(0.967 0.001 286.375);
--secondary-foreground: oklch(0.21 0.006 285.885);
--muted: oklch(0.967 0.001 286.375);
@@ -60,7 +60,7 @@
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.92 0.004 286.32);
--input: oklch(0.92 0.004 286.32);
--ring: oklch(0.705 0.015 286.067);
--ring: oklch(0.623 0.214 259.815);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
@@ -68,12 +68,12 @@
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.141 0.005 285.823);
--sidebar-primary: oklch(0.21 0.006 285.885);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.623 0.214 259.815);
--sidebar-primary-foreground: oklch(0.97 0.014 254.604);
--sidebar-accent: oklch(0.967 0.001 286.375);
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
--sidebar-border: oklch(0.92 0.004 286.32);
--sidebar-ring: oklch(0.705 0.015 286.067);
--sidebar-ring: oklch(0.623 0.214 259.815);
}
.dark {
@@ -83,8 +83,8 @@
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.21 0.006 285.885);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.92 0.004 286.32);
--primary-foreground: oklch(0.21 0.006 285.885);
--primary: oklch(0.546 0.245 262.881);
--primary-foreground: oklch(0.379 0.146 265.522);
--secondary: oklch(0.274 0.006 286.033);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.274 0.006 286.033);
@@ -94,7 +94,7 @@
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.552 0.016 285.938);
--ring: oklch(0.488 0.243 264.376);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
@@ -102,12 +102,12 @@
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.21 0.006 285.885);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.546 0.245 262.881);
--sidebar-primary-foreground: oklch(0.379 0.146 265.522);
--sidebar-accent: oklch(0.274 0.006 286.033);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.552 0.016 285.938);
--sidebar-ring: oklch(0.488 0.243 264.376);
}
@layer base {
@@ -118,3 +118,17 @@
@apply bg-background text-foreground;
}
}
/* https://github.com/tailwindlabs/tailwindcss/issues/13129 */
.container {
margin-left: auto;
margin-right: auto;
padding-left: 2rem;
padding-right: 2rem;
width: 100%;
}
@media (min-width: 1536px) {
.container {
max-width: 1400px;
}
}