suo
Widget reference

Accessibility

The roles, labels and live regions that make the widget usable with a screen reader, and what to check.

The widget implements the ARIA combobox pattern end to end, inside its shadow root.

Roles and attributes

ElementRole / attribute
The inputrole="combobox", aria-expanded, aria-controls pointing at the results list, aria-activedescendant pointing at the highlighted result's id
The results containerrole="listbox"
Each resultrole="option", aria-selected on the highlighted one
The result countA visually hidden live region (aria-live="polite") announcing "12 results" as results change
The modalrole="dialog", aria-modal="true", labeled by the visible heading or input placeholder

Focus management

Opening the modal moves focus to the input. Closing it returns focus to whatever triggered the open — the hotkey, or the element that was clicked. Focus never silently lands on <body>.

Announcements

  • A results update announces the new count, not every individual result — so typing does not flood a screen reader with a result-by-result readout.
  • The zero-result state announces the same "no results" text a sighted user sees, plus its suggestions.
  • A typo correction announcement follows the visible "Showing results for X" text (see Typo tolerance).

Color and motion

Nothing in the widget relies on color alone — see Status below for the indexing indicator's non-color fallback. The "indexing" pulsing ring (used in the dashboard, not the widget itself) switches to a static ring under prefers-reduced-motion: reduce.

Status indicators

Any live status shown alongside search results (for example, a degraded-mode notice) pairs a dot or icon with text — never a color shift alone — so the state reads correctly without color vision or a screen.

What to test

  • Keyboard-only: open, type, arrow through results, open one, and close, without ever touching a pointer.
  • A screen reader pass (VoiceOver or NVDA) confirms the announcements above.
  • axe runs clean against every widget state as part of CI — a widget change that introduces a new state should add an axe check for it.

On this page