AcheryWorkshop
Layout

Sidebar

Vertical navigation sidebar. Groups of items can be labelled with an eyebrow heading. Each item can be a link (href) or a button (onItemClick). Active state is driven by activeId matching an item's id — the active item gets a filled accent background.

Examples

Loading examples…

API

From COMPONENTS.md.

Vertical navigation with labelled groups.

import { Sidebar, type NavGroupDef } from 'achery-ui'

const groups: NavGroupDef[] = [
  {
    label: 'Library',
    items: [
      { id: '/recipes', label: 'All Recipes', glyph: 'scroll', count: 8 },
      { id: '/archive', label: 'Archived',    href: '/archive' },
    ],
  },
]

<Sidebar
  groups={groups}
  activeId={currentPath}           // string
  onItemClick={id => navigate(id)}
  footer={<Node />}
  collapsed={isCollapsed}          // boolean — icon-only mode (52px)
  onCollapsedChange={setCollapsed} // (boolean) => void — shows the collapse toggle (desktop mode only)
  mobileOpen={menuOpen}            // boolean — passing it (even false) switches to fixed overlay mode
  onMobileOpenChange={setMenuOpen} // (boolean) => void — backdrop click and Escape fire this
/>

Items render as <a> when href is set, otherwise <button>.

Overlay mode (mobileOpen passed): pass it only on narrow viewports, with useIsDesktop() (see Hooks). While open, Escape closes it, focus moves to the active item, and focus returns where it was (usually the menu button) on close. While closed the panel is inert, so its links are out of the tab order. mobileBreakpoint is deprecated and has no effect.

NavItemDef props: id, label, glyph?, icon?, iconColor?, href?, count?, countTone?: 'accent' | 'neutral'
countTone='accent' renders the count badge in the current accent colour.
icon — a custom leading ReactNode (monogram, avatar, bespoke mark) rendered in place of glyph; takes precedence over it. Keep it ~14–18px square.
iconColor — tints the leading glyph via currentColor (any CSS colour). Ignored when a custom icon is supplied — colour that yourself.