Skip to main content

Sidebar

The side navigation of an app, open while people work.

Left out of Accessible first Sidebar is for apps people move around all session. Here people do this once or twice a year, and breadcrumb shows where they are. Use instead: Breadcrumb, Progress

See it live​

Start Storybook to see it live: npm run storybook

When to use it​

  • Use it when: Apps with several sections people move between all session.
  • Not when: A website's main navigation (navigation menu), or a few sections that fit in tabs.

Instead:

Variants​

What each variant is for in any design system, then what Accessible first decided and why. Each sample is the live story with that variant set.

defaultvariantNot decided yet
Start Storybook to see it live

What it is for

Menu items with no border; hover shows the item.

✓Most apps: quiet next to the content.
✕Items that need extra separation.

In Accessible first

Not decided yet.

outlinevariantNot decided yet
Start Storybook to see it live

What it is for

Menu items with a border.

✓Items that need extra separation from a busy background.
✕A quiet sidebar next to dense content.

In Accessible first

Not decided yet.

defaultsizeNot decided yet
Start Storybook to see it live

What it is for

The normal row height.

✓Most menu items.
✕Very long lists.

In Accessible first

Not decided yet.

smsizeNot decided yet
Start Storybook to see it live

What it is for

A smaller row.

✓Long or secondary lists.
✕Touch screens.

In Accessible first

Not decided yet.

lgsizeNot decided yet
Start Storybook to see it live

What it is for

A taller row with room for an icon and two lines.

✓A workspace or account switcher at the top.
✕Ordinary menu items.

In Accessible first

Not decided yet.

Words​

  • Use common words. Explain any term you must use.
  • One idea per sentence. Put the action first.
  • Never blame the person.
  • Use: Continue, Change, Start, You. Avoid: Invalid, Utilise, Submit, Error code.

The labels components use, from the voice tokens:

  • content.action.commit: Continue
  • content.action.cancel: Go back
  • content.action.destroy: Delete
  • content.action.retry: Try again
  • content.action.empty-action: Start a new application

See Voice and tone for the whole voice.

Accessibility and keyboard​

Test before you ship:

  • It is a navigation landmark; the current section is marked; collapsing keeps names for icons. undefined

Use it in code​

npx open-ds add sidebar

The component reads only component keys and semantic tokens, so it follows the brand and mode on <html>.

Tokens it reads​

Sidebar reads 113 tokens of its own, each an alias of a semantic token. Each row is one part: its own token, the semantic it aliases, and the value it ends at. Change a semantic and every component that reads it follows; override one of Sidebar's tokens to change Sidebar alone.

Changes with theme

Accessible first decides what changes when you switch theme. Here a switch changes colors only, so the marked rows differ between light and dark; everything else holds steady.

PartIts token and the semantic it aliasesValue
Wrapper
Fill
Changes with theme
component.sidebar.wrapper.backgroundcolor.surface.defaultvar(--sidebar-wrapper-background)Lightgray.light.0:#FFFFFFDarkgray.dark.50:#141414
Sidebar
Fill
Changes with theme
component.sidebar.backgroundcolor.surface.defaultvar(--sidebar-background)Lightgray.light.0:#FFFFFFDarkgray.dark.50:#141414
Text
Changes with theme
component.sidebar.labelcolor.text.primaryvar(--sidebar-label)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Paddingcomponent.sidebar.paddingcomponent-spacing-map.x2var(--sidebar-padding)space.8:0.5rem
Background hover
Changes with theme
on hover
component.sidebar.background-hovercolor.surface.defaultvar(--sidebar-background-hover)Lightgray.light.0:#FFFFFFDarkgray.dark.50:#141414
Cornercomponent.sidebar.radiusradius.controlvar(--sidebar-radius)radius.6:0.375rem
Text sizecomponent.sidebar.font-sizetype.body.font-sizevar(--sidebar-font-size)font.size.19:1.1875rem
Focus ring
Changes with theme
component.sidebar.focus-ringcolor.border.focusvar(--sidebar-focus-ring)Lightblue.light.600:#0B4FC0Darkblue.dark.600:#8AB4F8
Padding rightcomponent.sidebar.padding-rightcomponent-spacing-map.x8var(--sidebar-padding-right)space.56:3.5rem
Sizecomponent.sidebar.sizesize.control.defaultvar(--sidebar-size)size.52:3.25rem
Background hover 2
Changes with theme
on hover
component.sidebar.background-hover-2color.surface.sunkenvar(--sidebar-background-hover-2)Lightgray.light.100:#EDEDEDDarkgray.dark.100:#222222
Label hover
Changes with theme
on hover
component.sidebar.label-hovercolor.text.primaryvar(--sidebar-label-hover)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Background active
Changes with theme
component.sidebar.background-activecolor.surface.sunkenvar(--sidebar-background-active)Lightgray.light.100:#EDEDEDDarkgray.dark.100:#222222
Label active
Changes with theme
component.sidebar.label-activecolor.text.primaryvar(--sidebar-label-active)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Disabled opacity disabled
when disabled
component.sidebar.disabled-opacity-disabledopacity.disabledvar(--sidebar-disabled-opacity-disabled)opacity.50:0.5
Background 2
Changes with theme
component.sidebar.background-2color.surface.sunkenvar(--sidebar-background-2)Lightgray.light.100:#EDEDEDDarkgray.dark.100:#222222
Weightcomponent.sidebar.font-weighttype.label.font-weightvar(--sidebar-font-weight)font.weight.700:700
Focuscomponent.sidebar.focusborder-width.focusvar(--sidebar-focus)border-width.3:3px
Background open hover
Changes with theme
when open, on hover
component.sidebar.background-open-hovercolor.surface.sunkenvar(--sidebar-background-open-hover)Lightgray.light.100:#EDEDEDDarkgray.dark.100:#222222
Label open hover
Changes with theme
when open, on hover
component.sidebar.label-open-hovercolor.text.primaryvar(--sidebar-label-open-hover)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Icon sizecomponent.sidebar.icon-sizesize.iconvar(--sidebar-icon-size)size.20:1.25rem
Focus ring focus
Changes with theme
on focus
component.sidebar.focus-ring-focuscolor.border.focusvar(--sidebar-focus-ring-focus)Lightblue.light.600:#0B4FC0Darkblue.dark.600:#8AB4F8
Focus ring offset focus
Changes with theme
on focus
component.sidebar.focus-ring-offset-focuscolor.surface.canvasvar(--sidebar-focus-ring-offset-focus)Lightgray.light.50:#F7F7F7Darkgray.dark.0:#0A0A0A
Heightcomponent.sidebar.heightsize.iconvar(--sidebar-height)size.20:1.25rem
Font size 2component.sidebar.font-size-2type.caption.font-sizevar(--sidebar-font-size-2)font.size.16:1rem
Gap
Speedcomponent.sidebar.gap.durationmotion.duration.feedbackvar(--sidebar-gap-duration)duration.moderate:200ms
Valuecomponent.sidebar.gapspace.gap.defaultvar(--sidebar-gap)space.16:1rem
Container
Speedcomponent.sidebar.container.durationmotion.duration.feedbackvar(--sidebar-container-duration)duration.moderate:200ms
Inner
Fill
Changes with theme
component.sidebar.inner.backgroundcolor.surface.defaultvar(--sidebar-inner-background)Lightgray.light.0:#FFFFFFDarkgray.dark.50:#141414
Cornercomponent.sidebar.inner.radiusradius.containervar(--sidebar-inner-radius)radius.8:0.5rem
Border
Changes with theme
component.sidebar.inner.bordercolor.border.defaultvar(--sidebar-inner-border)Lightgray.light.200:#D6D6D6Darkgray.dark.100:#222222
Shadowcomponent.sidebar.inner.shadowelevation.cardvar(--sidebar-inner-shadow)shadow.none
Rail
Background hover
Changes with theme
on hover
component.sidebar.rail.background-hovercolor.border.defaultvar(--sidebar-rail-background-hover)Lightgray.light.200:#D6D6D6Darkgray.dark.100:#222222
Inset
Fill
Changes with theme
component.sidebar.inset.backgroundcolor.surface.canvasvar(--sidebar-inset-background)Lightgray.light.50:#F7F7F7Darkgray.dark.0:#0A0A0A
Cornercomponent.sidebar.inset.radiusradius.containervar(--sidebar-inset-radius)radius.8:0.5rem
Shadowcomponent.sidebar.inset.shadowelevation.cardvar(--sidebar-inset-shadow)shadow.none
Input
Heightcomponent.sidebar.input.heightsize.control.defaultvar(--sidebar-input-height)size.52:3.25rem
Fill
Changes with theme
component.sidebar.input.backgroundcolor.surface.canvasvar(--sidebar-input-background)Lightgray.light.50:#F7F7F7Darkgray.dark.0:#0A0A0A
Header
Gapcomponent.sidebar.header.gapspace.gap.defaultvar(--sidebar-header-gap)space.16:1rem
Paddingcomponent.sidebar.header.paddingcomponent-spacing-map.x2var(--sidebar-header-padding)space.8:0.5rem
Footer
Gapcomponent.sidebar.footer.gapspace.gap.defaultvar(--sidebar-footer-gap)space.16:1rem
Paddingcomponent.sidebar.footer.paddingcomponent-spacing-map.x2var(--sidebar-footer-padding)space.8:0.5rem
Separator
Fill
Changes with theme
component.sidebar.separator.backgroundcolor.border.defaultvar(--sidebar-separator-background)Lightgray.light.200:#D6D6D6Darkgray.dark.100:#222222
Content
Gapcomponent.sidebar.content.gapspace.gap.defaultvar(--sidebar-content-gap)space.16:1rem
Group
Paddingcomponent.sidebar.group.paddingcomponent-spacing-map.x2var(--sidebar-group-padding)space.8:0.5rem
Label heightcomponent.sidebar.group.label.heightsize.control.defaultvar(--sidebar-group-label-height)size.52:3.25rem
Label radiuscomponent.sidebar.group.label.radiusradius.controlvar(--sidebar-group-label-radius)radius.6:0.375rem
Label padding xcomponent.sidebar.group.label.padding-xcomponent-spacing-map.x2var(--sidebar-group-label-padding-x)space.8:0.5rem
Label font sizecomponent.sidebar.group.label.font-sizetype.caption.font-sizevar(--sidebar-group-label-font-size)font.size.16:1rem
Label font weightcomponent.sidebar.group.label.font-weighttype.label.font-weightvar(--sidebar-group-label-font-weight)font.weight.700:700
Label label
Changes with theme
component.sidebar.group.label.labelcolor.text.primaryvar(--sidebar-group-label-label)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Label focus ring
Changes with theme
component.sidebar.group.label.focus-ringcolor.border.focusvar(--sidebar-group-label-focus-ring)Lightblue.light.600:#0B4FC0Darkblue.dark.600:#8AB4F8
Label durationcomponent.sidebar.group.label.durationmotion.duration.feedbackvar(--sidebar-group-label-duration)duration.moderate:200ms
Label icon sizecomponent.sidebar.group.label.icon-sizesize.iconvar(--sidebar-group-label-icon-size)size.20:1.25rem
Label focus
on focus
component.sidebar.group.label.focusborder-width.focusvar(--sidebar-group-label-focus)border-width.3:3px
Label focus ring focus
Changes with theme
on focus
component.sidebar.group.label.focus-ring-focuscolor.border.focusvar(--sidebar-group-label-focus-ring-focus)Lightblue.light.600:#0B4FC0Darkblue.dark.600:#8AB4F8
Label focus ring offset focus
Changes with theme
on focus
component.sidebar.group.label.focus-ring-offset-focuscolor.surface.canvasvar(--sidebar-group-label-focus-ring-offset-focus)Lightgray.light.50:#F7F7F7Darkgray.dark.0:#0A0A0A
Action radiuscomponent.sidebar.group.action.radiusradius.controlvar(--sidebar-group-action-radius)radius.6:0.375rem
Action label
Changes with theme
component.sidebar.group.action.labelcolor.text.primaryvar(--sidebar-group-action-label)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Action focus ring
Changes with theme
component.sidebar.group.action.focus-ringcolor.border.focusvar(--sidebar-group-action-focus-ring)Lightblue.light.600:#0B4FC0Darkblue.dark.600:#8AB4F8
Action background hover
Changes with theme
on hover
component.sidebar.group.action.background-hovercolor.surface.sunkenvar(--sidebar-group-action-background-hover)Lightgray.light.100:#EDEDEDDarkgray.dark.100:#222222
Action label hover
Changes with theme
on hover
component.sidebar.group.action.label-hovercolor.text.primaryvar(--sidebar-group-action-label-hover)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Action icon sizecomponent.sidebar.group.action.icon-sizesize.iconvar(--sidebar-group-action-icon-size)size.20:1.25rem
Action focus
on focus
component.sidebar.group.action.focusborder-width.focusvar(--sidebar-group-action-focus)border-width.3:3px
Action focus ring focus
Changes with theme
on focus
component.sidebar.group.action.focus-ring-focuscolor.border.focusvar(--sidebar-group-action-focus-ring-focus)Lightblue.light.600:#0B4FC0Darkblue.dark.600:#8AB4F8
Action focus ring offset focus
Changes with theme
on focus
component.sidebar.group.action.focus-ring-offset-focuscolor.surface.canvasvar(--sidebar-group-action-focus-ring-offset-focus)Lightgray.light.50:#F7F7F7Darkgray.dark.0:#0A0A0A
Content font sizecomponent.sidebar.group.content.font-sizetype.body.font-sizevar(--sidebar-group-content-font-size)font.size.19:1.1875rem
Menu
Gapcomponent.sidebar.menu.gapspace.gap.tightvar(--sidebar-menu-gap)space.12:0.75rem
Action radiuscomponent.sidebar.menu.action.radiusradius.controlvar(--sidebar-menu-action-radius)radius.6:0.375rem
Action label
Changes with theme
component.sidebar.menu.action.labelcolor.text.primaryvar(--sidebar-menu-action-label)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Action focus ring
Changes with theme
component.sidebar.menu.action.focus-ringcolor.border.focusvar(--sidebar-menu-action-focus-ring)Lightblue.light.600:#0B4FC0Darkblue.dark.600:#8AB4F8
Action background hover
Changes with theme
on hover
component.sidebar.menu.action.background-hovercolor.surface.sunkenvar(--sidebar-menu-action-background-hover)Lightgray.light.100:#EDEDEDDarkgray.dark.100:#222222
Action label hover
Changes with theme
on hover
component.sidebar.menu.action.label-hovercolor.text.primaryvar(--sidebar-menu-action-label-hover)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Action icon sizecomponent.sidebar.menu.action.icon-sizesize.iconvar(--sidebar-menu-action-icon-size)size.20:1.25rem
Action focus
on focus
component.sidebar.menu.action.focusborder-width.focusvar(--sidebar-menu-action-focus)border-width.3:3px
Action focus ring focus
Changes with theme
on focus
component.sidebar.menu.action.focus-ring-focuscolor.border.focusvar(--sidebar-menu-action-focus-ring-focus)Lightblue.light.600:#0B4FC0Darkblue.dark.600:#8AB4F8
Action focus ring offset focus
Changes with theme
on focus
component.sidebar.menu.action.focus-ring-offset-focuscolor.surface.canvasvar(--sidebar-menu-action-focus-ring-offset-focus)Lightgray.light.50:#F7F7F7Darkgray.dark.0:#0A0A0A
Badge radiuscomponent.sidebar.menu.badge.radiusradius.controlvar(--sidebar-menu-badge-radius)radius.6:0.375rem
Badge padding xcomponent.sidebar.menu.badge.padding-xcomponent-spacing-map.x1var(--sidebar-menu-badge-padding-x)space.4:0.25rem
Badge font sizecomponent.sidebar.menu.badge.font-sizetype.caption.font-sizevar(--sidebar-menu-badge-font-size)font.size.16:1rem
Badge font weightcomponent.sidebar.menu.badge.font-weighttype.label.font-weightvar(--sidebar-menu-badge-font-weight)font.weight.700:700
Badge label
Changes with theme
component.sidebar.menu.badge.labelcolor.text.primaryvar(--sidebar-menu-badge-label)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Skeleton heightcomponent.sidebar.menu.skeleton.heightsize.control.defaultvar(--sidebar-menu-skeleton-height)size.52:3.25rem
Skeleton gapcomponent.sidebar.menu.skeleton.gapspace.gap.defaultvar(--sidebar-menu-skeleton-gap)space.16:1rem
Skeleton radiuscomponent.sidebar.menu.skeleton.radiusradius.controlvar(--sidebar-menu-skeleton-radius)radius.6:0.375rem
Skeleton padding xcomponent.sidebar.menu.skeleton.padding-xcomponent-spacing-map.x2var(--sidebar-menu-skeleton-padding-x)space.8:0.5rem
Sub gapcomponent.sidebar.menu.sub.gapspace.gap.tightvar(--sidebar-menu-sub-gap)space.12:0.75rem
Sub border
Changes with theme
component.sidebar.menu.sub.bordercolor.border.defaultvar(--sidebar-menu-sub-border)Lightgray.light.200:#D6D6D6Darkgray.dark.100:#222222
Sub padding xcomponent.sidebar.menu.sub.padding-xcomponent-spacing-map.x3var(--sidebar-menu-sub-padding-x)space.20:1.25rem
Sub padding ycomponent.sidebar.menu.sub.padding-ycomponent-spacing-map.hairlinevar(--sidebar-menu-sub-padding-y)space.2:0.125rem
Sub button gapcomponent.sidebar.menu.sub.button.gapspace.gap.defaultvar(--sidebar-menu-sub-button-gap)space.16:1rem
Sub button radiuscomponent.sidebar.menu.sub.button.radiusradius.controlvar(--sidebar-menu-sub-button-radius)radius.6:0.375rem
Sub button padding xcomponent.sidebar.menu.sub.button.padding-xcomponent-spacing-map.x2var(--sidebar-menu-sub-button-padding-x)space.8:0.5rem
Sub button label
Changes with theme
component.sidebar.menu.sub.button.labelcolor.text.primaryvar(--sidebar-menu-sub-button-label)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Sub button focus ring
Changes with theme
component.sidebar.menu.sub.button.focus-ringcolor.border.focusvar(--sidebar-menu-sub-button-focus-ring)Lightblue.light.600:#0B4FC0Darkblue.dark.600:#8AB4F8
Sub button background hover
Changes with theme
on hover
component.sidebar.menu.sub.button.background-hovercolor.surface.sunkenvar(--sidebar-menu-sub-button-background-hover)Lightgray.light.100:#EDEDEDDarkgray.dark.100:#222222
Sub button label hover
Changes with theme
on hover
component.sidebar.menu.sub.button.label-hovercolor.text.primaryvar(--sidebar-menu-sub-button-label-hover)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Sub button background active
Changes with theme
component.sidebar.menu.sub.button.background-activecolor.surface.sunkenvar(--sidebar-menu-sub-button-background-active)Lightgray.light.100:#EDEDEDDarkgray.dark.100:#222222
Sub button label active
Changes with theme
component.sidebar.menu.sub.button.label-activecolor.text.primaryvar(--sidebar-menu-sub-button-label-active)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Sub button disabled opacity disabled
when disabled
component.sidebar.menu.sub.button.disabled-opacity-disabledopacity.disabledvar(--sidebar-menu-sub-button-disabled-opacity-disabled)opacity.50:0.5
Sub button icon sizecomponent.sidebar.menu.sub.button.icon-sizesize.iconvar(--sidebar-menu-sub-button-icon-size)size.20:1.25rem
Sub button focus
on focus
component.sidebar.menu.sub.button.focusborder-width.focusvar(--sidebar-menu-sub-button-focus)border-width.3:3px
Sub button focus ring focus
Changes with theme
on focus
component.sidebar.menu.sub.button.focus-ring-focuscolor.border.focusvar(--sidebar-menu-sub-button-focus-ring-focus)Lightblue.light.600:#0B4FC0Darkblue.dark.600:#8AB4F8
Sub button focus ring offset focus
Changes with theme
on focus
component.sidebar.menu.sub.button.focus-ring-offset-focuscolor.surface.canvasvar(--sidebar-menu-sub-button-focus-ring-offset-focus)Lightgray.light.50:#F7F7F7Darkgray.dark.0:#0A0A0A
Default
Background hover
Changes with theme
component.sidebar.default.background-hovercolor.surface.sunkenvar(--sidebar-default-background-hover)Lightgray.light.100:#EDEDEDDarkgray.dark.100:#222222
Label hover
Changes with theme
on hover
component.sidebar.default.label-hovercolor.text.primaryvar(--sidebar-default-label-hover)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Heightcomponent.sidebar.default.heightsize.control.defaultvar(--sidebar-default-height)size.52:3.25rem
Text sizecomponent.sidebar.default.font-sizetype.body.font-sizevar(--sidebar-default-font-size)font.size.19:1.1875rem
Outline
Fill
Changes with theme
component.sidebar.outline.backgroundcolor.surface.canvasvar(--sidebar-outline-background)Lightgray.light.50:#F7F7F7Darkgray.dark.0:#0A0A0A
Background hover
Changes with theme
on hover
component.sidebar.outline.background-hovercolor.surface.sunkenvar(--sidebar-outline-background-hover)Lightgray.light.100:#EDEDEDDarkgray.dark.100:#222222
Label hover
Changes with theme
on hover
component.sidebar.outline.label-hovercolor.text.primaryvar(--sidebar-outline-label-hover)Lightgray.light.900:#141414Darkgray.dark.900:#F7F7F7
Sm
Text sizecomponent.sidebar.sm.font-sizetype.caption.font-sizevar(--sidebar-sm-font-size)font.size.16:1rem
Lg
Text sizecomponent.sidebar.lg.font-sizetype.body.font-sizevar(--sidebar-lg-font-size)font.size.19:1.1875rem
From the system
Edge
Changes with theme
color.border.default
straight from the system, through --border
Lightgray.light.200 · #D6D6D6Darkgray.dark.100 · #222222