Top bar — accessibility

Keyboard

  • Everything in the bar is a real <button>: workspace switch, search, utilities, account. Tab reaches them left to right.
  • Global search answers to ⌘K / Ctrl+K through a window listener, and the button advertises it with aria-keyshortcuts="Meta+K" as well as the visible ⌘K chip.
  • The assistant answers to ⌘J and says so with aria-keyshortcuts="Meta+J"; it has no visible chip because the trigger already carries a name.
  • Menus opened from the bar are canonical popovers: Escape closes them, and the same keyboard limits apply as for Popover (no arrow-key movement inside the menu).
  • The mobile hamburger toggles the off-canvas sidebar and is the first tab stop on small screens.

ARIA

  • The workspace switch is aria-haspopup="menu" + aria-expanded; the account button carries the user's name as aria-label and title.
  • The hamburger has aria-expanded and aria-controls="as-side-nav", so the sidebar it opens is named.
  • The assistant trigger sets aria-busy while a run is going — the pulse is not the only signal.
  • The .dot indicator is decorative; what is waiting must also be readable in the panel that opens. Nothing announces its appearance (no live region).
  • The bar is a <header>; the sidebar is <aside id="as-side-nav">, so both are landmarks.

Focus

  • No focus rule in app-shell.css and no outline: none: all controls are buttons, so the foundation ring from ds.css applies (outline: 2px solid var(--accent); outline-offset: 1px).
  • Opening the search palette moves focus into it; closing returns focus to the search button.
  • The bar is not a focus trap and never steals focus on load.

Contrast

Computed from packages/ui/src/tokens/tokens.css:

  • Workspace name and account initials sit on --surface-100 in ink tones — above 12:1 in both themes.
  • Search placeholder .ph uses --fg-muted = 2.85:1 light, 3.63:1 dark — below AA for text; it is a placeholder, and the button's accessible name carries the meaning.
  • The ⌘K chip is .acrm-kbd — the canonical shortcut chip, muted by design.
  • The waiting dot is accent on the button surface; it is a non-text indicator above the 3:1 minimum, but it is small — the panel behind it is the real carrier.
  • Focus ring --accent = 4.44:1 light, 3.83:1 dark.

Known limits

  • The search placeholder and the utility icons sit at --fg-muted (2.85:1 in light theme).
  • Nothing is announced when the dot appears — a screen-reader user learns about a new notification only by opening the bell.
  • The assistant's busy pulse is visual; aria-busy covers assistive technology, but there is no text status.
  • The bar has no skeleton state: while the workspace list loads it renders the current workspace only.

Source: docs/app-shell/top-bar.a11y.md · GitLab