Navigation
A primary navigation component with active state indicators.
$ npx @beaket/ui add navigationSource
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
All Variants
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
| Name | Type | Default | Description |
|---|---|---|---|
| value | string | undefined | — | The current page's value. `Navigation.Link` compares its own `value` to it. |
| match | undefined | prefix | exact | exact | Exact 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.active | boolean | — | Whether this link represents the current page. Overrides the derived state. |
| Link.value | string | — | This link's value, compared against the root's `value` to derive `active`. |
| Link.asChild | boolean | false | Renders the consumer's own element (a router `Link`) instead of an `<a>` |