SidebarNav

Vertical navigation for application sidebars, with groups, icons and trailing counts.

StableSource

Import

tsx
import { SidebarNav } from "@merid/react";

SidebarNavItem is also exported on its own and is the same component as SidebarNav.Item.

Anatomy

tsx
<SidebarNav aria-label="…">
  <SidebarNav.Item href="…" icon={…} trailing={…} active />
  <SidebarNav.Group label="…">
    <SidebarNav.Item href="…" />
  </SidebarNav.Group>
</SidebarNav>
  • SidebarNav (also SidebarNav.Root) — a <nav> with a list.
  • SidebarNav.Item — a link wrapped in its own <li>, with optional icon and trailing element.
  • SidebarNav.Group — an <li> with a visible label that names a nested list.

Examples

With a router

Pass your router's link component through as. Extra props are forwarded to it.

tsx
import Link from "next/link";
import { usePathname } from "next/navigation";
import { SidebarNav } from "@merid/react";

export function AppNav() {
  const pathname = usePathname();
  return (
    <SidebarNav aria-label="Main">
      <SidebarNav.Item as={Link} href="/settings" active={pathname === "/settings"}>
        Settings
      </SidebarNav.Item>
    </SidebarNav>
  );
}

API reference

SidebarNav

Renders <nav> and accepts all its HTML attributes.

PropTypeDefaultDescription
aria-labelstring–Accessible name of the landmark (required when a page has several navs).
refRef<HTMLElement>–Forwarded ref to the nav element.

SidebarNav.Item

Renders <a> (or as) inside an <li> and accepts all anchor attributes plus any props for as.

PropTypeDefaultDescription
activebooleanfalseMarks the current page: sets aria-current="page" and the selected style.
iconReactNode–Icon shown before the label (decorative).
trailingReactNode–Trailing element such as a count Badge.
asElementType"a"Element or component to render instead of <a>, e.g. a router Link.
refRef<HTMLAnchorElement>–Forwarded ref to the link.

SidebarNav.Group

Renders <li> and accepts its HTML attributes except title.

PropTypeDefaultDescription
labelRequiredReactNode–Visible group heading; also labels the nested list.

Styling

  • .mrd-sidebar-nav, .mrd-sidebar-nav__list — root and each list, 2px gap between items.
  • .mrd-sidebar-nav__item — the link: 36px min height (44px on coarse pointers), --mrd-radius-md.
  • .mrd-sidebar-nav__item[aria-current="page"] (also data-state="active") — --mrd-accent-soft fill with --mrd-accent-strong text.
  • .mrd-sidebar-nav__icon, .mrd-sidebar-nav__label, .mrd-sidebar-nav__trailing — icon slot, truncating label, trailing slot.
  • .mrd-sidebar-nav__group, .mrd-sidebar-nav__group-label — group spacing and its muted label.

Accessibility

Follows the APG landmark regions guidance for a navigation landmark; there is no widget pattern because items are plain links.

  • Name the landmark with aria-label when the page has more than one nav.
  • The active link has aria-current="page".
  • Each group's nested list is labelled by its visible heading via aria-labelledby.
  • Icons are aria-hidden; the label must carry the meaning.
KeyAction
TabMoves focus to the next link.
ShiftTabMoves focus to the previous link.
EnterFollows the focused link.

Guidelines

Do

Keep labels to one or two words and mark exactly one item active.

Avoid

Put actions such as “New project” buttons in the list; they are not destinations.

Do

Use trailing for counts people act on, like unread items.

Avoid

Rely on the icon alone; the label is always required.