Skip to content
HyperDesign System

Nav item

The sidebar row: a full-width pill with a tint hover and a stronger tint when active. The icon, label and any trailing count or key are yours to compose. Source: src/components/ui/nav-item.tsx.

Click a row to make it current. Primary destinations use the default tone; secondary ones under an Overline use muted.

Tones and states

default, muted and active. NavItem has no disabled style of its own, so add one if you need it, and avoid disabled rows in navigation where you can.

asChild around a Link for real navigation. A trailing chevron hints at a drill-in.

With a shortcut

Push a Kbd or a count to the end with ml-auto.

Props

Nav item props
PropTypeDefaultDescription
tone"default" | "muted""default"default starts on the first text tier; muted starts on the second and lifts to the first on hover.
activebooleanfalseA stronger tint fill, first-tier text and medium weight; sets data-active. It does not set aria-current.
asChildbooleanfalseRender the single child (a Link) as the row, via Radix Slot. type is dropped.
type"button" | "submit" | "reset""button"Only when NavItem renders its own <button>.
...propsComponentProps<"button">—Native attributes pass through (onClick, disabled, aria-*); className merges last.

Best practices

When to use

  • Rows in a sidebar or a settings rail that move you somewhere. Commands that act in place belong in a menu or a Button.

Behavior

  • Active adds font-medium, so the label widens by a hair when selected. Keep labels short and truncating so the row never reflows.
  • Hover fades on the normal duration with plain ease-out (Button uses fast with ease-out-quart; the two differ today).
  • Wrap labels in a span with truncate; the row clips overflow rather than wrapping.

Accessibility

  • Set aria-current="page" on the active row yourself; NavItem's active prop is visual only.
  • No focus style of its own: keyboard focus shows the global focus-visible outline.
  • Wrap the list in a <nav> with an aria-label. Icons take aria-hidden; the label is the name.

Content

  • One or two words, nouns, sentence case. Counts as a secondary Badge, not in the label.