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.
Sidebar
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.
As link
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
| Prop | Type | Default | Description |
|---|---|---|---|
| tone | "default" | "muted" | "default" | default starts on the first text tier; muted starts on the second and lifts to the first on hover. |
| active | boolean | false | A stronger tint fill, first-tier text and medium weight; sets data-active. It does not set aria-current. |
| asChild | boolean | false | Render 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>. |
| ...props | ComponentProps<"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.