SideNav

Two-level app navigation with expandable branches and a collapsed mode.

Overview

  • Show app sections and the active destination within a two-level hierarchy.

Aliases

sidebar navigation

When to use

  • Use SideNav for persistent app navigation with two levels.
  • Use collapsed mode when navigation needs less space.

When not to use

  • Do not use SideNav for one-off subsection navigation inside a content page.
  • Do not treat it like a breadcrumb or progress indicator.

Structural parts

nav row

item

Single navigation destination or expandable parent.

expand and collapse control

branch

Toggles nested child visibility.

auxiliary status

badge

Optional compact count or state marker.

Public interface

Props
NameTypeDefaultDescription
itemsArray<{ id: string; label: string; href?: string; icon?: string; badge?: string; disabled?: boolean; children?: SideNavItem[] }>—Navigation items with at most two visible levels.
activeIdstring—Controlled active navigation ID.
collapsedbooleanfalseEnables the denser collapsed shell mode.
onChange(detail: { id: string }) => void—Runs when the active navigation item changes.
themeThemeContract—Sets the theme used to resolve component styles.
Events
NamePayloadDescription
change{ id: string }Fires when the active item changes.
Slots
NameDescription
defaultSideNav is data-driven and does not expose item slots.

Variants, sizes, and states

Variants

  • expanded: Full labels and nested branch state are visible.
  • collapsed: Top-level items compress into a denser shell mode.

Sizes

  • default: SideNav uses one shell density tuned for application navigation.

States

  • rest: Inactive navigation row
  • selected: Current route or section
  • expanded: Parent branch is open

Accessibility

Semantics

  • Uses navigation semantics with explicit active and expanded state cues.

Keyboard

  • Arrow keys move through visible items. ArrowRight expands; ArrowLeft collapses or moves to the parent. Enter activates the item.

Screen readers

  • Branch state, current location, and disabled state remain explicit through the row semantics.

Checklist

  • Verify that the control has an accessible name.
  • Verify that keyboard focus is visible in every state and size.
  • Identify disabled, selected, and error states with text or symbols as well as color.

Tokens and CSS variables

root

--dk-side-nav-bg
#e5e8ed
--dk-side-nav-fg
#16181c
--dk-side-nav-border
#95989d
--dk-side-nav-gap
0.4rem
--dk-side-nav-padding
0.75rem

item

--dk-side-nav-item-bg
#e5e8ed
--dk-side-nav-item-fg
#16181c
--dk-side-nav-item-radius
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
--dk-side-nav-item-min-height
44px
--dk-side-nav-item-inline-padding
0.75rem

label

--dk-side-nav-label-size
0.92rem
--dk-side-nav-label-weight
600

badge

--dk-side-nav-badge-size
0.75rem

branch

--dk-side-nav-branch-size
0.85rem

Implementation notes

  • Navigation items support at most two visible levels.

Examples

Starter

App shell navigation

A persistent shell navigation with one expanded branch.

<SideNav items={navItems} activeId="overview" onChange={(detail) => activeId = detail.id} />

Common patterns

Collapsed shell mode

Collapsed mode preserves the active section marker.

<SideNav items={navItems} activeId="overview" collapsed={true} />

Edge cases

Navigation with counts

Badges can call attention to queues or inbox-like sections without changing the base navigation contract.

<SideNav items={[{ id: 'inbox', label: 'Inbox', badge: '12' }, { id: 'releases', label: 'Releases', children: [{ id: 'planned', label: 'Planned' }] }]} activeId="inbox" />

Mathematical fixtures

Calculated fixtures; browser evidence is not collected. Layout estimates use declared text behavior and maximum token values.

default

pass

  • Evidence: mathematical
  • Coverage: complete (3 / 3 declared kinds evaluated)
  • Declared: contrast, target, layout
  • Evaluated: contrast, target, layout
  • Contrast: 90.8 Lc
  • Target: 44 px
  • Layout: root · single-line 0 px single-line estimate; 0 px minimum width
    240 px: pass 320 px: pass

selected

pass

  • Evidence: mathematical
  • Coverage: complete (3 / 3 declared kinds evaluated)
  • Declared: contrast, target, layout
  • Evaluated: contrast, target, layout
  • Contrast: 89.9 Lc
  • Target: 44 px
  • Layout: root · single-line 0 px single-line estimate; 0 px minimum width
    240 px: pass 320 px: pass