Skip to main content

SideNav

Organismbeta@macaw-ds/ui · since 0.1.0

The product's primary navigation in the left column of AppShell. Not for sections within a page; that is TabNav.

When to use

The product's main destinations: Home, Balances, Invoices, Customers, Settings. It lives in AppShell's left column, which gives it the full viewport height and its own scroll.

When not to use

  • Sections of one page. Use TabNav under the page title.
  • Actions. "New invoice" is a Button in the page header, not a nav item.

Anatomy

Groups, each with an optional short heading, contain items. An item is a link with an optional decorative icon and a label. The active item has a tinted accent background and accent text.

With a router

<SideNav.Item asChild active={pathname.startsWith('/invoices')} icon={<Icon name="receipt" />}>
  <Link href="/invoices">Invoices</Link>
</SideNav.Item>

Density

Item height is size.control.sm: 28px comfortable, 24px compact. Spacing between groups follows layout.stack-lg.

Accessibility

  • A nav landmark named by aria-label, with one aria-current="page".
  • Every item is a link and a Tab stop, and Enter follows it.
  • Group headings are plain text, not headings, so screen reader heading navigation stays on the page content.

Do and don't

Do

  • Use icons for every item in a group or for none of them.

Don't

  • Do not put actions (buttons) in SideNav; it is for navigation only.

  • Do not nest groups.

Rules

Hard rules an agent must follow. The reviewer agent and the lint config check the ones that can be checked.

  1. Exactly one item is active, and it matches the current route.
  2. Group related destinations under a short heading; keep fewer than ten items per group.
  3. With a router, pass the Link through asChild so client-side navigation keeps working.
  4. Place SideNav in AppShell's sideNav slot; it does not set its own width or background.