Skip to content
LuoForge/Tungsten
Components/Nav·Experimental

Nav

since v13.2.0

Vertical 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/tungsten
pnpm add @hey-mike/tungsten
import { 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 />.

PropTypeDefaultDescription
aria-labelstringNavigationAccessible label for the nav landmark. @defaultValue 'Navigation'
activeIdstringid of the active item — receives aria-current="page" and the brand stripe.
linkComponentElementTypeaElement 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>.
collapsedbooleanfalseReserved for the icon-rail variant (fast-follow). Typed now so consumers can wire it; currently renders identically to the expanded sidebar.
classNamestring

Sub-components

Composition slots re-exported from the same module.

NavGroup

PropTypeDefaultDescription
labelReactNodeOptional section label, rendered mono-caps above the items.
collapsiblebooleanfalseWhen true, the label becomes a Disclosure toggle that collapses the items.
defaultOpenbooleantrueInitial open state when collapsible. @defaultValue true
classNamestring

NavItem

PropTypeDefaultDescription
item*NavItemSpecThe item: a link (href) xor an action (onClick).
iconReactElement<unknown, string | JSXElementConstructor<any>>Optional leading icon.
trailingReactNodeOptional trailing content (counts, badges).
disabledbooleanfalseDims the row, removes pointer events, and makes it non-focusable.
classNamestring

Source