Navigation

A primary navigation component with active state indicators.

$ npx @beaket/ui add navigation
Source
import { useState } from "react";
import { Navigation } from "@/components/ui/navigation";

const items = ["Home", "Docs", "About"];

export default function Example() {
  const [active, setActive] = useState("Home");

  return (
    <div className="relative h-full w-full">
      <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
        <Navigation>
          <Navigation.List>
            {items.map((item) => (
              <Navigation.Item key={item}>
                <Navigation.Link
                  href={`#${item.toLowerCase()}`}
                  active={active === item}
                  onClick={() => setActive(item)}
                >
                  {item}
                </Navigation.Link>
              </Navigation.Item>
            ))}
          </Navigation.List>
        </Navigation>
      </div>
    </div>
  );
}

Examples

Horizontal navigation

Vertical navigation

Source
import { Navigation } from "@/components/ui/navigation";

export default () => (
  <div className="space-y-6">
    <div>
      <p className="text-fg-muted mb-2 text-xs">Horizontal navigation</p>
      <Navigation>
        <Navigation.List>
          <Navigation.Item>
            <Navigation.Link href="#home" active>
              Home
            </Navigation.Link>
          </Navigation.Item>
          <Navigation.Item>
            <Navigation.Link href="#docs">Docs</Navigation.Link>
          </Navigation.Item>
          <Navigation.Item>
            <Navigation.Link href="#about">About</Navigation.Link>
          </Navigation.Item>
        </Navigation.List>
      </Navigation>
    </div>
    <div>
      <p className="text-fg-muted mb-2 text-xs">Vertical navigation</p>
      <Navigation>
        <Navigation.List className="w-48 flex-col [&>li+li]:-mt-px [&>li+li]:border-l">
          <Navigation.Item>
            <Navigation.Link href="#dashboard" active className="w-full">
              Dashboard
            </Navigation.Link>
          </Navigation.Item>
          <Navigation.Item>
            <Navigation.Link href="#settings" className="w-full">
              Settings
            </Navigation.Link>
          </Navigation.Item>
        </Navigation.List>
      </Navigation>
    </div>
  </div>
);

Props

NameTypeDefaultDescription
valuestring | undefined—The current page's value. `Navigation.Link` compares its own `value` to it.
matchundefined | prefix | exactexactExact by default. Prefix selects the longest segment-boundary match after links mount, so server-rendered HTML and the first paint mark no link; the active link appears after hydration. When the server HTML must carry it, pass `active` on the link or an `isActive` matcher.
isActive((pathname: string, value: string) => boolean) | undefined—Custom router matching. Explicit active on a link still wins.
Link.activeboolean—Whether this link represents the current page. Overrides the derived state.
Link.valuestring—This link's value, compared against the root's `value` to derive `active`.
Link.asChildbooleanfalseRenders the consumer's own element (a router `Link`) instead of an `<a>`