98 lines
3.0 KiB
TypeScript
98 lines
3.0 KiB
TypeScript
'use client';
|
|
|
|
import type { LucideIcon } from 'lucide-react';
|
|
import Link from 'next/link';
|
|
import { ExternalLink, Menu } from 'lucide-react';
|
|
|
|
import {
|
|
Button,
|
|
Sheet,
|
|
SheetClose,
|
|
SheetContent,
|
|
SheetDescription,
|
|
SheetHeader,
|
|
SheetTitle,
|
|
SheetTrigger,
|
|
} from '@gib/ui';
|
|
|
|
export type NavItem = {
|
|
href: string;
|
|
icon: LucideIcon;
|
|
label: string;
|
|
external?: boolean;
|
|
};
|
|
|
|
type NavigationProps = {
|
|
items: NavItem[];
|
|
};
|
|
|
|
const DesktopNavigation = ({ items }: NavigationProps) => {
|
|
return (
|
|
<nav className='hidden items-center gap-4 text-xs font-medium sm:flex md:gap-6 lg:text-base'>
|
|
{items.map(({ href, icon: Icon, label, external }) => (
|
|
<Link
|
|
key={label}
|
|
href={href}
|
|
target={external ? '_blank' : undefined}
|
|
rel={external ? 'noopener noreferrer' : undefined}
|
|
className='text-foreground/60 hover:text-foreground flex items-center gap-2 transition-colors'
|
|
>
|
|
<Icon width={18} height={18} />
|
|
{label}
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
);
|
|
};
|
|
|
|
const MobileNavigation = ({ items }: NavigationProps) => {
|
|
return (
|
|
<Sheet>
|
|
<SheetTrigger asChild>
|
|
<Button
|
|
variant='outline'
|
|
size='icon-sm'
|
|
className='sm:hidden'
|
|
aria-label='Open navigation menu'
|
|
>
|
|
<Menu className='size-4.5' />
|
|
<span className='sr-only'>Open navigation menu</span>
|
|
</Button>
|
|
</SheetTrigger>
|
|
<SheetContent side='right' className='w-[min(88vw,22rem)] px-0'>
|
|
<SheetHeader className='border-border/60 from-background to-muted/40 border-b bg-linear-to-br from-35% px-5 py-5 text-left'>
|
|
<SheetTitle className='text-left text-lg'>Navigation</SheetTitle>
|
|
<SheetDescription className='text-left'>
|
|
Quick access to the links that collapse out of the header.
|
|
</SheetDescription>
|
|
</SheetHeader>
|
|
|
|
<div className='flex flex-col gap-3 px-4 py-5'>
|
|
{items.map(({ href, icon: Icon, label, external }) => (
|
|
<SheetClose asChild key={label}>
|
|
<Link
|
|
href={href}
|
|
target={external ? '_blank' : undefined}
|
|
rel={external ? 'noopener noreferrer' : undefined}
|
|
className='bg-card hover:bg-muted/70 border-border/60 text-card-foreground flex items-center justify-between rounded-2xl border px-4 py-3 transition-colors'
|
|
>
|
|
<span className='flex items-center gap-3'>
|
|
<span className='bg-muted text-foreground flex h-9 w-9 items-center justify-center rounded-xl'>
|
|
<Icon className='size-4.5' />
|
|
</span>
|
|
<span className='text-sm font-medium'>{label}</span>
|
|
</span>
|
|
{external ? (
|
|
<ExternalLink className='text-muted-foreground size-4' />
|
|
) : null}
|
|
</Link>
|
|
</SheetClose>
|
|
))}
|
|
</div>
|
|
</SheetContent>
|
|
</Sheet>
|
|
);
|
|
};
|
|
|
|
export { DesktopNavigation, MobileNavigation };
|