Skip to content

Sidebar

Section navigation. Docked at desktop widths, a drawer below them.

Preview

Code

The three render the same class names, the same ARIA and the same data attributes. That is checked when this site builds: a class in any of these samples that neither the markup contract nor the shipped stylesheet defines fails the build.

<div class="wsu-drawer-backdrop" data-wsu-drawer-backdrop="app-sidebar" hidden></div>

<nav class="wsu-sidebar" id="app-sidebar" aria-label="Sections" hidden tabindex="-1">
  <div class="wsu-sidebar__inner">
    <button class="wsu-btn wsu-btn--icon wsu-btn--ghost wsu-sidebar__close" type="button" data-wsu-drawer-close>
      <span class="wsu-sr-only">Close navigation menu</span>
      <svg class="wsu-icon" aria-hidden="true"><use href="/assets/wayne-ui/icons.svg#wsu-x"/></svg>
    </button>

    <div class="wsu-sidebar__primary-nav">
      <ul class="wsu-sidebar__list" aria-label="Primary">
        <li><a class="wsu-sidebar__link" href="/term" aria-current="page">Term</a></li>
        <li><a class="wsu-sidebar__link" href="/catalog">Catalog</a></li>
      </ul>
    </div>

    <div>
      <p class="wsu-sidebar__heading" id="nav-registration">Registration</p>
      <ul class="wsu-sidebar__list" aria-labelledby="nav-registration">
        <li><a class="wsu-sidebar__link" href="/courses" aria-current="page">
          <svg class="wsu-icon" aria-hidden="true"><use href="/assets/wayne-ui/icons.svg#wsu-clipboard-list"/></svg>
          Select courses</a></li>
        <li><a class="wsu-sidebar__link" href="/schedule">
          <svg class="wsu-icon" aria-hidden="true"><use href="/assets/wayne-ui/icons.svg#wsu-calendar"/></svg>
          My schedule</a></li>
      </ul>
    </div>
  </div>
</nav>

Why it works this way

  • Label it for what it holds. "Sections" or "Filters", not "Navigation": a screen reader already announces the role, so aria-label="Navigation" produces "Navigation navigation".
  • The drawer is opened by the bar's menu button and closed by Escape, the backdrop or the close button. Focus moves into the drawer on open and back to the button on close, and the runtime that does this is the same wayne-ui-theme.js the static path uses.
  • The close button is hidden by the stylesheet where the sidebar is docked, because at that width there is nothing to close.
  • AppBar's own nav is display:none below 768px, and the drawer is the only place left to reach it at that width, so this repeats those same links under wsu-sidebar__primary-nav. The stylesheet hides the repeat again once the sidebar docks, where the bar's own copy is back.

Accessibility

  • hidden on the nav until opened, so a closed drawer is genuinely out of the tab order (2.4.3).
  • tabindex="-1" so focus can be moved to the drawer itself.
  • The list is labeled by its heading with aria-labelledby.

Success criteria in brackets refer to WCAG 2.2. Every one of them is checked by axe-core in both themes at three viewport widths before this page can be published. See Accessibility for what the gates are.

Props

Blade

AttributeDefaultWhat it does
id'app-sidebar'Must match the bar's drawer target.
labelconfig('wayne-ui.sidebar.label')Names the landmark.
itemsconfig('wayne-ui.sidebar.items')Flat items, or groups with a heading. One level of nesting.
backdroptrueRenders the drawer backdrop element. Set false where the page supplies its own.
navconfig('wayne-ui.nav')AppBar's own items, repeated here for the widths at which the bar hides them.
navLabel'Primary'Names the repeated list. There is no heading to point aria-labelledby at.

Vue

PropType and defaultWhat it does
idString, 'app-sidebar'Must match AppBar's drawer prop.
labelString, 'Sections'Names the landmark.
closeLabelString, 'Close navigation menu'Accessible name for the drawer close button.
primaryNavLabelString, 'Primary'Names the primary-nav slot's list.
SidebarNav itemsArray, [][{ label, href, icon, current, children }].
SidebarNav linkAsString, 'a'Inertia Link or RouterLink.

In the markup contract

contract/markup-contract.json is extracted from the two static templates and every package tests against it. This is what it records for .wsu-sidebar.

TemplateElementsAccessibility attributesUses
internal apps/examples/static-html/index.htmlnavaria-labelhiddentabindex1
public apps/examples/static-html/public-app.htmlnavaria-labelhiddentabindex1