mirror of
https://github.com/vercel/commerce.git
synced 2025-07-23 04:36:49 +00:00
@@ -4,9 +4,9 @@ import LogoSquare from 'components/logo-square';
|
||||
import Profile from 'components/profile';
|
||||
import OpenProfile from 'components/profile/open-profile';
|
||||
import { getMenu } from 'lib/shopify';
|
||||
import { Menu } from 'lib/shopify/types';
|
||||
import Link from 'next/link';
|
||||
import { Suspense } from 'react';
|
||||
import MainMenu from './main-menu';
|
||||
import MobileMenu from './mobile-menu';
|
||||
import Search, { SearchSkeleton } from './search';
|
||||
const { SITE_NAME } = process.env;
|
||||
@@ -15,7 +15,7 @@ export default async function Navbar() {
|
||||
const menu = await getMenu('main-menu');
|
||||
|
||||
return (
|
||||
<nav className="relative mb-4 flex items-center justify-between bg-white pb-3 pt-4 md:pb-0 dark:bg-neutral-900">
|
||||
<nav className="relative mb-4 flex items-center justify-between bg-white pb-3 pt-4 dark:bg-neutral-900 md:pb-0">
|
||||
<div className="block flex-none pl-4 md:hidden">
|
||||
<Suspense fallback={null}>
|
||||
<MobileMenu menu={menu} />
|
||||
@@ -29,7 +29,7 @@ export default async function Navbar() {
|
||||
className="mr-2 flex w-full items-center justify-center md:w-auto lg:mr-6"
|
||||
>
|
||||
<LogoSquare />
|
||||
<div className="flex-none font-league-spartan text-xl font-semibold tracking-tight text-dark md:hidden md:text-2xl lg:block lg:text-3xl lg:leading-tight dark:text-white">
|
||||
<div className="flex-none font-league-spartan text-xl font-semibold tracking-tight text-dark dark:text-white md:hidden md:text-2xl lg:block lg:text-3xl lg:leading-tight">
|
||||
{SITE_NAME}
|
||||
</div>
|
||||
</Link>
|
||||
@@ -49,22 +49,7 @@ export default async function Navbar() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{menu.length ? (
|
||||
<div className="hidden w-full items-center justify-center border-b px-4 pb-3 pt-4 md:flex">
|
||||
<ul className="hidden gap-8 text-sm font-medium md:flex md:items-center lg:gap-16">
|
||||
{menu.map((item: Menu) => (
|
||||
<li key={item.title}>
|
||||
<Link
|
||||
href={item.path}
|
||||
className="text-neutral-600 hover:text-black dark:text-neutral-400 dark:hover:text-neutral-300"
|
||||
>
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
) : null}
|
||||
<MainMenu menu={menu} />
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
|
95
components/layout/navbar/main-menu.tsx
Normal file
95
components/layout/navbar/main-menu.tsx
Normal file
@@ -0,0 +1,95 @@
|
||||
'use client';
|
||||
|
||||
import { Popover, Transition } from '@headlessui/react';
|
||||
import clsx from 'clsx';
|
||||
import { Menu } from 'lib/shopify/types';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { Fragment, useState } from 'react';
|
||||
|
||||
const MainMenu = ({ menu }: { menu: Menu[] }) => {
|
||||
const pathname = usePathname();
|
||||
const [open, setOpen] = useState('');
|
||||
|
||||
return menu.length ? (
|
||||
<div className="mt-2 hidden h-11 w-full border-b text-sm font-medium md:flex">
|
||||
<Popover.Group as={Fragment}>
|
||||
<div className="z-10 flex h-full w-full items-center justify-center gap-8 px-4 lg:gap-16">
|
||||
{menu.map((item: Menu) => {
|
||||
const isActiveItem =
|
||||
item.path === pathname ||
|
||||
item.items.some((subItem: Menu) => subItem.path === pathname);
|
||||
if (!item.items.length) {
|
||||
return (
|
||||
<Link
|
||||
key={item.title}
|
||||
href={item.path}
|
||||
className={`flex h-full items-center ${isActiveItem ? 'text-black' : 'text-neutral-600 hover:text-black'}`}
|
||||
>
|
||||
{item.title}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
const isOpen = open === item.path;
|
||||
return (
|
||||
<Popover key={item.title} className="relative flex h-full">
|
||||
<div
|
||||
className="relative flex"
|
||||
onMouseOver={() => setOpen(item.path)}
|
||||
onMouseLeave={() => setOpen('')}
|
||||
>
|
||||
<Link
|
||||
href={item.path}
|
||||
className={clsx(
|
||||
'relative z-10 flex items-center border-b-2 px-2 pt-px transition-colors duration-200 ease-out focus-visible:ring-0 focus-visible:ring-offset-0',
|
||||
{
|
||||
'border-gray-500 text-black': isOpen || isActiveItem,
|
||||
'border-transparent text-neutral-600 hover:text-black':
|
||||
!isOpen && !isActiveItem
|
||||
}
|
||||
)}
|
||||
>
|
||||
{item.title}
|
||||
</Link>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-200"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="transition ease-in duration-150"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
show={isOpen}
|
||||
>
|
||||
<Popover.Panel
|
||||
static
|
||||
className="absolute inset-x-0 left-1/2 top-full z-10 mt-0.5 min-w-32 max-w-sm -translate-x-1/2 transform text-sm"
|
||||
>
|
||||
<div className="overflow-hidden rounded-md shadow-lg ring-1 ring-black/5">
|
||||
<ul className="flex flex-col space-y-2 bg-white px-4 py-3">
|
||||
{item.items.map((subItem: Menu) => (
|
||||
<li key={subItem.title}>
|
||||
<Link
|
||||
href={subItem.path}
|
||||
className={`border-b ${subItem.path === pathname ? 'border-black text-black' : 'border-transparent text-neutral-600 hover:text-black'}`}
|
||||
>
|
||||
{subItem.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</Popover.Panel>
|
||||
</Transition>
|
||||
</div>
|
||||
</Popover>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Popover.Group>
|
||||
</div>
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default MainMenu;
|
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { Dialog, Disclosure, Transition } from '@headlessui/react';
|
||||
import Link from 'next/link';
|
||||
import { usePathname, useSearchParams } from 'next/navigation';
|
||||
import { Fragment, Suspense, useEffect, useState } from 'react';
|
||||
@@ -35,7 +35,7 @@ export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
||||
<button
|
||||
onClick={openMobileMenu}
|
||||
aria-label="Open mobile menu"
|
||||
className="flex h-11 w-11 items-center justify-center rounded-md border border-neutral-200 text-black transition-colors md:hidden dark:border-neutral-700 dark:text-white"
|
||||
className="flex h-11 w-11 items-center justify-center rounded-md border border-neutral-200 text-black transition-colors dark:border-neutral-700 dark:text-white md:hidden"
|
||||
>
|
||||
<Bars3Icon className="h-4" />
|
||||
</button>
|
||||
@@ -80,12 +80,29 @@ export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
||||
<ul className="flex w-full flex-col">
|
||||
{menu.map((item: Menu) => (
|
||||
<li
|
||||
className="py-2 text-xl text-black transition-colors hover:text-neutral-500 dark:text-white"
|
||||
className="py-2 text-xl text-neutral-600 transition-colors hover:text-black"
|
||||
key={item.title}
|
||||
>
|
||||
<Link href={item.path} onClick={closeMobileMenu}>
|
||||
{item.title}
|
||||
</Link>
|
||||
{item.items.length ? (
|
||||
<Disclosure>
|
||||
<Disclosure.Button>{item.title}</Disclosure.Button>
|
||||
<Disclosure.Panel className="flex flex-col space-y-2 px-3 py-2 text-lg text-neutral-600 hover:text-black">
|
||||
{item.items.map((subItem: Menu) => (
|
||||
<Link
|
||||
key={subItem.title}
|
||||
href={subItem.path}
|
||||
onClick={closeMobileMenu}
|
||||
>
|
||||
{subItem.title}
|
||||
</Link>
|
||||
))}
|
||||
</Disclosure.Panel>
|
||||
</Disclosure>
|
||||
) : (
|
||||
<Link href={item.path} onClick={closeMobileMenu}>
|
||||
{item.title}
|
||||
</Link>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
Reference in New Issue
Block a user