feature/share-libs
tsx 97 lines 2.75 KB
Raw
1 'use client';
2
3 import { menus, type Item } from '../_lib/menus';
4 import Link from 'next/link';
5 import { useSelectedLayoutSegment } from 'next/navigation';
6 import { MenuAlt2Icon, XIcon } from '@heroicons/react/solid';
7 import clsx from 'clsx';
8 import { useState } from 'react';
9 import Image from 'next/image';
10
11 export function GlobalNav() {
12 const [isOpen, setIsOpen] = useState(false);
13 const close = () => setIsOpen(false);
14
15 return (
16 <div className="fixed top-0 z-10 flex w-full flex-col border-b border-gray-800 bg-black lg:bottom-0 lg:z-auto lg:w-72 lg:border-b-0 lg:border-r lg:border-gray-800">
17 <div className="flex h-14 items-center px-4 py-4 lg:h-auto">
18 <Link
19 href="/"
20 className="group flex w-full items-center gap-x-2.5"
21 onClick={close}
22 >
23 <div className="h-7 w-7 rounded-sm border border-white/30 group-hover:border-white/50">
24 <Image src="/logo192.png" alt="Tauri on Bazel" width={40} height={40} />
25 </div>
26
27 <h3 className="font-semibold tracking-wide text-gray-400 group-hover:text-gray-50">
28 Tauri on Bazel
29 </h3>
30 </Link>
31 </div>
32 <button
33 type="button"
34 className="group absolute right-0 top-0 flex h-14 items-center gap-x-2 px-4 lg:hidden"
35 onClick={() => setIsOpen(!isOpen)}
36 >
37 <div className="font-medium text-gray-100 group-hover:text-gray-400">
38 Menu
39 </div>
40 {isOpen ? (
41 <XIcon className="block w-6 text-gray-400" />
42 ) : (
43 <MenuAlt2Icon className="block w-6 text-gray-400" />
44 )}
45 </button>
46
47 <div
48 className={clsx('overflow-y-auto lg:static lg:block', {
49 'fixed inset-x-0 bottom-0 top-14 mt-px bg-black': isOpen,
50 hidden: !isOpen,
51 })}
52 >
53 <nav className="space-y-6 px-2 pb-24 pt-5">
54 {menus.map((section, index) => {
55 return (
56 <div key={index}>
57
58 <div className="space-y-1">
59 {section.items.map((item) => (
60 <GlobalNavItem key={item.slug} item={item} close={close} />
61 ))}
62 </div>
63 </div>
64 );
65 })}
66 </nav>
67 </div>
68 </div>
69 );
70 }
71
72 function GlobalNavItem({
73 item,
74 close,
75 }: {
76 item: Item;
77 close: () => false | void;
78 }) {
79 const segment = useSelectedLayoutSegment();
80 const isActive = item.slug === segment;
81
82 return (
83 <Link
84 onClick={close}
85 href={`/${item.slug}`}
86 className={clsx(
87 'block rounded-md px-3 py-2 text-sm font-medium hover:text-gray-300',
88 {
89 'text-gray-400 hover:bg-gray-800': !isActive,
90 'text-white': isActive,
91 },
92 )}
93 >
94 {item.name}
95 </Link>
96 );
97 }