Nav
since v13.2.0Vertical sidebar navigation. Composes {@link NavGroup} sections and
{@link NavItem} rows; renders a <nav> landmark. The active item carries
the sidebar's single brand moment — a 2px left-edge stripe.
Install
Add the package and import the component.
pnpm add @hey-mike/tungstenpnpm add @hey-mike/tungstenimport { Nav } from '@hey-mike/tungsten';import { Nav } from '@hey-mike/tungsten';Preview
Same fixtures used by the visual-regression suite.
Usage
apps/docs/app/snapshots/nav/page.tsx
import { Nav, NavGroup, NavItem } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';
export default function NavSnapshot() {
return (
<VariantGrid
title="Nav"
variants={[
{
label: 'sidebar',
node: (
<div className="w-60">
<Nav aria-label="Primary" activeId="usage">
<NavGroup label="Workspace">
<NavItem item={{ id: 'overview', label: 'Overview', href: '#' }} />
<NavItem item={{ id: 'usage', label: 'Usage', href: '#' }} trailing={<span>12</span>} />
<NavItem item={{ id: 'members', label: 'Members', href: '#' }} />
</NavGroup>
<NavGroup label="Account" collapsible defaultOpen>
<NavItem item={{ id: 'billing', label: 'Billing', href: '#' }} />
<NavItem item={{ id: 'logout', label: 'Sign out', href: '#' }} />
<NavItem item={{ id: 'archived', label: 'Archived', href: '#' }} disabled />
</NavGroup>
</Nav>
</div>
),
},
]}
/>
);
}
import { Nav, NavGroup, NavItem } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';
export default function NavSnapshot() {
return (
<VariantGrid
title="Nav"
variants={[
{
label: 'sidebar',
node: (
<div className="w-60">
<Nav aria-label="Primary" activeId="usage">
<NavGroup label="Workspace">
<NavItem item={{ id: 'overview', label: 'Overview', href: '#' }} />
<NavItem item={{ id: 'usage', label: 'Usage', href: '#' }} trailing={<span>12</span>} />
<NavItem item={{ id: 'members', label: 'Members', href: '#' }} />
</NavGroup>
<NavGroup label="Account" collapsible defaultOpen>
<NavItem item={{ id: 'billing', label: 'Billing', href: '#' }} />
<NavItem item={{ id: 'logout', label: 'Sign out', href: '#' }} />
<NavItem item={{ id: 'archived', label: 'Archived', href: '#' }} disabled />
</NavGroup>
</Nav>
</div>
),
},
]}
/>
);
}
Props
Surface specific to <Nav />.
| Prop | Type | Default | Description |
|---|---|---|---|
| aria-label | string | Navigation | Accessible label for the nav landmark. @defaultValue 'Navigation' |
| activeId | string | — | id of the active item — receives aria-current="page" and the brand stripe. |
| linkComponent | ElementType | a | Element used to render link items (those with href). Defaults to 'a'.
Pass a router link (e.g. Next.js <Link>) for client-side navigation.
Action items (those with onClick) always render a <button>. |
| collapsed | boolean | false | Reserved for the icon-rail variant (fast-follow). Typed now so consumers can wire it; currently renders identically to the expanded sidebar. |
| className | string | — | — |
Sub-components
Composition slots re-exported from the same module.
NavGroup
| Prop | Type | Default | Description |
|---|---|---|---|
| label | ReactNode | — | Optional section label, rendered mono-caps above the items. |
| collapsible | boolean | false | When true, the label becomes a Disclosure toggle that collapses the items. |
| defaultOpen | boolean | true | Initial open state when collapsible.
@defaultValue true |
| className | string | — | — |
NavItem
| Prop | Type | Default | Description |
|---|---|---|---|
| item* | NavItemSpec | — | The item: a link (href) xor an action (onClick). |
| icon | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Optional leading icon. |
| trailing | ReactNode | — | Optional trailing content (counts, badges). |
| disabled | boolean | false | Dims the row, removes pointer events, and makes it non-focusable. |
| className | string | — | — |