Skip to content
Protocore Design Systemv1.6.9

/// Navigation

NavLink

Navigation link row for sidebars and menus — leading icon, label, optional description and trailing count/chevron, an inked active row with a 2px accent leading rule, and collapsible nested sub-links.

import { NavLink } from "@protocore/pds";
View as Markdown

Basics

Each row is a NavLink.Root with an icon and label. Mark the current row active — it inks and grows the 2px accent leading rule. Add a count for an at-a-glance total.

Descriptions

A description adds a sans-13 muted second line — useful when a label alone is ambiguous. Keep both lines to one line each; the row truncates rather than wraps.

When to use it

NavLink is the row primitive for a Sidebar, a slide-in Sheet menu, or any vertical navigation list. Sidebar gives you the rail, groups, and mono UPPERCASE group labels; NavLink is the richer item when you need an icon, a count, a description, or collapsible children.

  • Reach for Sidebar.Item for a plain label row; reach for NavLink.Root when the row carries an icon, count, or description.
  • Use NavLink.Sub for one level of nesting. Deeper trees read better in a TreeView.
  • The count is metadata (mono, muted) — not a status. For a colored status use a Badge in rightSection.
  • active is a visual promise of the current location: set it on exactly one row per view.

Usage

Do

  • Set `active` on exactly one row — the current location — driven by your router.
  • Use `NavLink.Sub` for collapsible sections; the caret signals expandability.
  • Pass `asChild` to keep client-side navigation with a framework `<Link>`.
  • Keep labels short; add a description only when the label is ambiguous.

Don't

  • Mark more than one row active — the accent is a single-location signal.
  • Put a colored status pill in `count`; count is muted metadata.
  • Nest `NavLink.Sub` more than one level deep — use TreeView for real trees.
  • Rely on the trailing chevron alone to convey state — it is decorative.

Accessibility

KeysAction
TabMove focus to the next row (link or Sub trigger)
EnterFollow the focused link, or toggle a Sub disclosure
SpaceToggle the focused Sub disclosure
  • The active row carries `aria-current="page"` so assistive tech announces the current location.
  • NavLink.Sub renders a Radix Collapsible: the trigger is a real `<button>` with `aria-expanded` and its content is associated for screen readers.
  • A disabled row sets `aria-disabled` and drops pointer events; give every icon-only affordance a text label via the row's `label`.
  • Wrap a set of rows in a `<nav aria-label>` so the group is announced as a navigation landmark.

Related

  • SidebarA left navigation rail of grouped items — mono uppercase group labels over sans links, with an accent rule on the active item.
  • AppShellThe application frame — an optional env strip and top bar over a sidebar + main body row, with an optional footer and a responsive mobile drawer.
  • MenubarApplication menubar — a horizontal row of mono UPPERCASE menu triggers (File/Edit/View) opening raised panels of items, checkbox/radio items and submenus.
  • BreadcrumbBreadcrumb trail — a mono UPPERCASE, "/"-separated path where crumbs are links and the last is the inked current page.