Sidebar nav

The nested navigation list inside the app sidebar, carrying its own active and expanded states.

In the libraryVue source: WildSidebarNav.vueStorybook story: Navigation/Sidebar Nav

Try it

Pick a row, open Integrations, then collapse the list and use the flyouts.

Settings / Monitoring / Alarms
Recipient lists

Who hears about an alarm, by email or SMS, and when.

Variant
Collapsed
Icons
Counts
Headings
<WildSidebarNav
  v-model="page"
  v-model:expanded="openBranches"
  v-model:collapsed="collapsed"
  :items="settingsNav"
  collapsible
  aria-label="Settings"
/>

<script setup>
const settingsNav = [
  { id: 'monitoring', label: 'Monitoring', isHeader: true },
  { id: 'alarms', label: 'Alarms', icon: 'bell', children: [
    { id: 'rules', label: 'Rules', badge: 18 },
    { id: 'recipients', label: 'Recipient lists' },
  ] },
  { id: 'system-alerts', label: 'System alerts', icon: 'exclamation-triangle',
    badge: 3, badgeTone: 'alert', badgeLabel: '3 need attention' },
]
</script>

When to use

  • Use it for the pages of one area, such as settings.
  • Group a long list under short headings.
  • Gather a few related pages under one branch.
Don’t use it
  • For the product’s main navigation. Use App sidebar.
  • To switch views of one subject. Use Tabs.
  • For actions. Use a Button or Menu.

Anatomy

  1. 1Heading. Names the rows below.
  2. 2Row. Glyph and label, 36px tall.
  3. 3Branch. Opens and closes its rows.
  4. 4Count. A plain number.
  5. 5Current row. Grey ground and the cyan strip.
  6. 6Nested rows. Hang off a hairline.
  7. 7Alert. A red badge for counts that need action.
  8. 8Closed branch. Totals the alerts inside it.

Variants

Match the variant to the ground it sits on.

light
dark

Rail

Collapsed, the list is a 64px rail of glyphs. Hover or focus one for its name, and press a branch for a flyout.

Monitoring / Alarms
Recipient lists
light
Monitoring / Alarms
Recipient lists
dark
Headings become short rules, and alert counts a red dot.

Nesting

Nest one level only. A parent isn’t a page itself.

branches open
branches closed
A closed branch takes the strip when it holds the current page.

States

rest
hover
pressed
keyboard focus
current
disabled
rest
hover
pressed
keyboard focus
current
disabled
Pressed and current share a grey, and only current has the strip. Disabled dims to 40%.

In context

Account settings in the web app.

Account settingsEmu Park Orchard
Alarm recipient lists

A list can be attached to any number of alarms. Editing it changes every alarm that uses it.

Irrigation team4 people · email and SMSUsed by 12 alarms
After-hours on call2 people · SMSUsed by 5 alarms
Reseller support1 person · emailUsed by 2 alarms

Content

  • Name each row after the page it opens, in sentence case.
  • Keep labels short, because long ones are truncated.
  • Hide a page someone can’t open. Keyboard and touch users never see a disabled row’s reason.
  • Say what an alert count means, for screen readers: “3 need attention”.

Accessibility

Headings name their lists, and the current row is announced as the current page. A closed branch holding it says so.

KeyWhat it does
TabRows, then the collapse button. Skips disabled rows.
↓ / ↑Next or previous row.
Home / EndFirst or last row.
EnterOpens the page, or opens and closes a branch.
SpaceSame as Enter, on rows without an href.
→Opens a branch, or enters an open one. On the rail, opens its flyout.
←Closes a branch. On a nested row, goes to the parent.
EscapeCloses a flyout and returns focus to its parent.

Props

PropTypeDefaultDescription
v-modelstring—The current row’s id.
items{ id, label, icon?, href?, badge?, badgeTone?, badgeLabel?, disabled?, disabledReason?, isHeader?, children? }[]—Rows and headings, in order.
badgeTone'count' | 'alert' | 'new''count'Per item: a plain number, or a red or cyan badge.
v-model:expandedstring[]the current branchIds of the open branches.
v-model:collapsedbooleanfalseShows the 64px rail.
collapsiblebooleanfalseAdds a collapse button.
variant'light' | 'dark''light'See Variants.
widthnumber240Expanded width in px.
borderedbooleantrueThe 1px right edge.
aria-labelstring'Sidebar'Names the navigation landmark.
@change(id, item) => void—Emitted whenever a row is chosen.

Tokens

TokenValueWhere it lands
--color-grey-50#FDFDFDLight surface.
--color-grey-100#F5F5F5Hover ground.
--color-grey-300#ECECEDCurrent and pressed ground.
--color-primary#00AEEFCurrent-row strip.
--color-grey-900#4F4D55Row labels, 8.2:1.
--color-grey-1200#0A090BHeadings, current label.
(no token)#4F4D55Counts on light.
--color-grey-800#7F7D83Glyphs and chevrons, 4:1.
--color-border-default#E6E6E6Right edge and branch hairline.
--color-error#E12121Alert badges, rail dot.
--color-grey-1100#1D1C20Dark surface.
--color-grey-600#C9C9CCLabels and counts on dark.
--color-primary-active#1877F2Focus ring.