Site Nav

Minimal Navbar

Minimal navbar for the Eudoxia wordmark: three text links, a ghost log in link and an outline get started button, collapsing to a Sheet menu in narrow containers.

Free, MIT licenseOpen in Browse
"use client"

import { useState } from "react"
import { ListIcon } from "@phosphor-icons/react/dist/ssr"
import { cn } from "cn"

import {
  Navbar,
  NavbarActions,
  NavbarLink,
  NavbarLinks,
  NavbarLogo,
} from "@/components/site-nav/navbar"
import { Button, buttonVariants } from "@/components/ui/button"
import {
  NavigationMenuItem,
  NavigationMenuList,
} from "@/components/ui/navigation-menu"
import {
  Sheet,
  SheetContent,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet"

// The copy: change text here, not in the markup.
const COPY = {
  brand: "Eudoxia.",
  homeLabel: "Eudoxia home",
  navLabel: "Main",
  links: [
    { label: "Product", href: "#" },
    { label: "Pricing", href: "#" },
    { label: "Docs", href: "#" },
  ],
  login: { label: "Log in", href: "#" },
  cta: { label: "Get started", href: "#" },
  menu: "Menu",
  openMenu: "Open menu",
} as const

export default function MinimalNavbar01() {
  // Controlled, so a link can close the sheet as it navigates.
  const [open, setOpen] = useState(false)
  const close = () => setOpen(false)

  return (
    <Navbar>
      <NavbarLogo href="#" aria-label={COPY.homeLabel}>
        {COPY.brand}
      </NavbarLogo>
      <NavbarLinks aria-label={COPY.navLabel}>
        <NavigationMenuList className="gap-8">
          {COPY.links.map((link) => (
            <NavigationMenuItem key={link.label}>
              <NavbarLink render={<a href={link.href} />}>
                {link.label}
              </NavbarLink>
            </NavigationMenuItem>
          ))}
        </NavigationMenuList>
      </NavbarLinks>
      <NavbarActions>
        <a
          href={COPY.login.href}
          data-slot="button"
          className={cn(
            buttonVariants({ variant: "ghost" }),
            "hidden @5xl/navbar:inline-flex"
          )}
        >
          {COPY.login.label}
        </a>
        <a
          href={COPY.cta.href}
          data-slot="button"
          className={cn(buttonVariants({ variant: "outline", size: "lg" }))}
        >
          {COPY.cta.label}
        </a>
        <Sheet open={open} onOpenChange={setOpen}>
          <SheetTrigger
            render={
              <Button
                variant="ghost"
                size="icon-lg"
                aria-label={COPY.openMenu}
                className="@5xl/navbar:hidden"
              />
            }
          >
            <ListIcon aria-hidden="true" />
          </SheetTrigger>
          <SheetContent>
            <SheetHeader>
              <SheetTitle>{COPY.menu}</SheetTitle>
            </SheetHeader>
            <nav aria-label={COPY.navLabel} className="grid gap-1 px-6">
              {COPY.links.map((link) => (
                <a
                  key={link.label}
                  href={link.href}
                  onClick={close}
                  data-slot="button"
                  className={cn(
                    buttonVariants({ variant: "ghost", size: "lg" }),
                    "justify-start"
                  )}
                >
                  {link.label}
                </a>
              ))}
            </nav>
            <SheetFooter>
              <a
                href={COPY.login.href}
                onClick={close}
                data-slot="button"
                className={cn(buttonVariants({ variant: "outline" }))}
              >
                {COPY.login.label}
              </a>
            </SheetFooter>
          </SheetContent>
        </Sheet>
      </NavbarActions>
    </Navbar>
  )
}

Installation

pnpm dlx shadcn add @01orbital/minimal-navbar-01
npx shadcn add @01orbital/minimal-navbar-01
yarn shadcn add @01orbital/minimal-navbar-01
bunx --bun shadcn add @01orbital/minimal-navbar-01

Free under the MIT license. Add the @01orbital registry to components.json once (install guide), then run the command.

It lands at components/blocks/site-nav/minimal-navbar-01/index.tsx, as source you own and edit.

Usage

import MinimalNavbar01 from "@/components/blocks/site-nav/minimal-navbar-01"

export default function Example() {
  return <MinimalNavbar01 />
}

Dependencies

npm: @phosphor-icons/react, cn. The CLI installs them for you.

Registry pieces it installs with it:

  • button
  • navbar
  • navigation-menu
  • sheet