Zetta v1.6

Components · App chrome

Sidebar

The 240px navigation rail — a brand block, grouped nav items, and a footer profile. The active item takes a primary-bg tint with a primary-coloured icon and bold weight. The rail to your left is the real one; the preview below is a static instance.

Preview

Build with the skill

No package to install — hand this to your AI to generate or migrate the component in your stack.

Prompt for your AI
Apply the Zetta "Sidebar" component to this project using the zetta-design-md skill.

WHEN TO USE
- Migrating or fixing existing code (the common case): audit the current implementation against the `sidebar` spec (variants: nav-item, nav-item-active, section-label) and CORRECT every deviation — replace off-spec values, don't only add new ones.
- New component: build it to the `sidebar` spec in this project's stack.

AUDIT & FIX (when the component already exists)
Compare it to the skill's spec and fix, don't just append: hardcoded colors/hex, off-scale radius, wrong fonts, dark/navy fills, shadows used in place of borders (or missing borders), brand lime used as a CTA or interaction (must be primary indigo), and any missing or wrong hover / focus / active / disabled / invalid state or missing 2px focus ring. Replace each with the correct Zetta token.

ALWAYS
- Pull the authoritative spec and tokens from the skill — never guess or hardcode values.
- Use this project's own component conventions and framework idioms.
- Honor the Zetta guardrails (brand = identity only, primary = interaction, shadows for overlays) and verify in Light, Dark, and Accessibility.

Anatomy & rules

╭──────────────────────────╮
│  ⬡  Zetta Product        │  ← sidebar-brand-block (Inter 700, 16px)
│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│  ◈  Dashboard            │  ← sidebar-nav-item (active — primary-bg fill)
│  ◉  Reports              │  ← sidebar-nav-item (rest)
│  ◉  Settings             │
│                          │
│  TEAM                    │  ← sidebar-nav-section-label (muted, 12px)
│  ◉  Members              │
│  ◉  Billing              │
│─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│  [●] Alice Johnson       │  ← sidebar-footer-profile
│      Admin               │
╰──────────────────────────╯
  240px wide, full viewport height
State Visual
Expanded Full width, label + icon per nav item
Collapsed Icon-only rail, tooltips on hover
Nav item — default transparent fill, {colors.muted} icon + text
Nav item — hover {colors.surface-muted} fill
Nav item — focus 2px solid {colors.border-focus} inset outline
Nav item — active {colors.primary-bg} fill, {colors.primary} text, 2px solid {colors.primary} left border
Nav group — collapsed Chevron pointing right
Nav group — expanded Chevron pointing down, children visible

When to use

  • Application layouts with 5 or more primary navigation destinations.
  • Product surfaces where the user needs persistent wayfinding across sections.

When not to use

  • Simple single-page tools with fewer than 4 nav items — use a top navigation bar (Header) instead.
  • Marketing or public-facing pages — sidebar implies an authenticated application shell.

Do

  • Group related nav items under section labels when the list exceeds 6 items.
  • Mark exactly one item as active at a time — never zero, never multiple.
  • Keep brand block content to logo + product name only; no interactive elements.

Don't

  • Don't put actions (buttons, dropdowns) in the sidebar nav column — nav items are links only.
  • Don't nest sidebar inside a scrollable parent — sidebar must span full viewport height.
  • Nav item labels: concise nouns or noun phrases. 1–2 words. Title case. "Dashboard", "Team Members", "Billing".
  • Section labels: short all-caps nouns. Under 15 characters. "WORKSPACE", "TEAM", "ADMIN".
  • Profile block: show display name + role or email. Truncate long strings with ellipsis — do not wrap.
  • Brand block: product name only. Do not include marketing copy, taglines, or version numbers.

Keyboard

Key Behavior
Tab Move focus through nav items
Enter Navigate to the focused item destination
Space Expand / collapse a collapsible nav group
Escape Collapse expanded group (if in group context)
Escape Close sidebar drawer (mobile only)

Accessibility

  • Landmark: wrap the sidebar in <nav aria-label="Main navigation"> or use role="navigation".
  • Active item: aria-current="page" on the active nav item — not just a visual change.
  • Section labels: use <li role="presentation"> or a visually-hidden heading so screen readers announce the group.
  • Keyboard trap (mobile): when sidebar opens as a drawer, trap focus inside until dismissed. Restore focus to the trigger element on close.
  • Accessibility theme: nav item height must be 44px minimum — override the standard 32px token. See zetta-accessibility.md Section 7.

Spec

Values and token references resolved straight from the Zetta spec.

sidebar
backgroundColor
{colors.surface-sidebar}
borderRightColor
{colors.hairline}
borderRightWidth
1px
width
240px
sidebar-brand-block
paddingX
16px
paddingY
24px
fontFamily
Inter
fontSize
16px
fontWeight
700
lineHeight
1.3
letterSpacing
-0.01em
textColor
{colors.ink}
sidebar-nav-item
textColor
{colors.body}
iconColor
{colors.muted}
fontFamily
Geist
fontSize
14px
fontWeight
500
lineHeight
1.4
borderRadius
{rounded.base}
height
32px
paddingX
12px
paddingY
8px
gap
8px
iconSize
20px
cursor
pointer
sidebar-nav-item-hover
backgroundColor
{colors.surface-muted}
textColor
{colors.ink}
iconColor
{colors.ink}
sidebar-nav-item-active
backgroundColor
{colors.primary-bg}
textColor
{colors.ink}
iconColor
{colors.primary}
fontWeight
600
sidebar-nav-item-focus
outline
2px solid {colors.border-focus}
outlineOffset
2px
sidebar-nav-section-label
textColor
{colors.muted}
fontFamily
Geist
fontSize
12px
fontWeight
500
letterSpacing
0.01em
paddingX
12px
paddingY
4px
marginTop
8px
sidebar-footer-profile
display
flex
flexDirection
row
alignItems
center
paddingX
16px
paddingY
16px
borderTopColor
{colors.hairline}
borderTopWidth
1px
gap
8px
sidebar-collapsed
width
60px
overflow
hidden
sidebar-collapsed-nav-item
width
36px
height
36px
borderRadius
{rounded.base}
display
flex
alignItems
center
justifyContent
center
margin
0 auto
sidebar-collapse-trigger
position
absolute
right
-12px
top
24px
width
24px
height
24px
borderRadius
{rounded.full}
backgroundColor
{colors.surface-card}
borderColor
{colors.hairline}
borderWidth
1px
shadow
{elevation.shadow.raised}
iconSize
12px
iconColor
{colors.muted}
cursor
pointer
zIndex
1
sidebar-nav-item-badge
marginLeft
auto
minWidth
18px
height
18px
borderRadius
{rounded.full}
backgroundColor
{colors.danger}
textColor
{colors.danger-text}
fontFamily
Geist
fontSize
10px
fontWeight
700
display
flex
alignItems
center
justifyContent
center
paddingX
4px
sidebar-nav-group-trigger
chevronSize
14px
chevronColor
{colors.muted}
chevronTransition
transform {motion.duration-base} {motion.easing-default}
sidebar-nav-group-trigger-open
chevronTransform
rotate(90deg)
sidebar-nav-group-content
paddingLeft
28px
overflow
hidden
transition
height {motion.duration-base} {motion.easing-default}
sidebar-nav-sub-item
textColor
{colors.body}
fontFamily
Geist
fontSize
13px
fontWeight
400
height
28px
paddingX
{spacing.sm}
borderRadius
{rounded.base}
cursor
pointer
sidebar-nav-sub-item-hover
backgroundColor
{colors.surface-muted}
textColor
{colors.ink}
sidebar-nav-sub-item-active
backgroundColor
{colors.primary-bg}
textColor
{colors.primary}
fontWeight
500

Known gaps

  • Sidebar resize (user-draggable width between 60px and 320px) — not yet specified.
  • Sidebar pinned/unpinned state persistence — runtime/product concern.