Sort options available via accessible select or listbox
Why it matters
A sort control built from unsemantic divs or buttons fails WCAG 2.2 SC 4.1.2 (Name, Role, Value) and SC 2.1.1 (Keyboard) — keyboard users cannot tab to the control, screen readers cannot identify it as an interactive dropdown, and arrow-key navigation expected of a listbox never fires. Sorting is a primary navigation mechanism in any results page; locking it behind mouse-only interaction excludes a non-trivial portion of users and makes the directory non-compliant in any context where WCAG conformance is required (government contracts, enterprise procurement, ADA-adjacent legal exposure).
Severity rationale
Low because the failure blocks keyboard and screen reader access to sorting without exposing data or creating a security risk.
Remediation
Use a native <select> element for the sort control — it ships with full keyboard navigation, screen reader support, and no ARIA configuration required. In components/SortControl.tsx:
<label htmlFor="sort-select">Sort by</label>
<select
id="sort-select"
value={currentSort}
onChange={e => onChange(e.target.value)}
>
<option value="relevance">Relevance</option>
<option value="rating">Highest rating</option>
<option value="distance">Nearest distance</option>
</select>
If a custom styled dropdown is required for design reasons, use Radix UI's <Select> or shadcn/ui's Select component — both implement the ARIA listbox pattern with correct keyboard navigation. Do not build a custom dropdown from <div> or <button> elements without the full ARIA combobox/listbox implementation.
Detection
-
ID:
sort-a11y -
Severity:
low -
What to look for: Enumerate all relevant files and Examine the sort control. Check whether it uses an accessible
<select>element, or a custom dropdown with proper ARIA roles (role="listbox",role="option",aria-expanded, etc.). Verify it can be navigated via keyboard (arrow keys, Enter to select). -
Pass criteria: No more than 0 violations are acceptable. Sort control uses
<select>or a custom component with proper ARIA roles and keyboard navigation support. -
Fail criteria: Sort control is a non-semantic button or styled div with no ARIA attributes, preventing screen reader and keyboard access.
-
Skip (N/A) when: Results are not sortable or sort control doesn't exist. Signal: no sort control found.
-
Detail on fail:
"Sort control is a styled button with no <select> or ARIA roles. Screen readers cannot identify it as a dropdown. Keyboard navigation doesn't work." -
Remediation: Use semantic
<select>for sort:// components/SortControl.tsx export function SortControl({ currentSort, onChange }) { return ( <div> <label htmlFor="sort-select">Sort by</label> <select id="sort-select" value={currentSort} onChange={e => onChange(e.target.value)} aria-label="Sort results by" > <option value="relevance">Relevance</option> <option value="rating">Highest rating</option> <option value="distance">Nearest distance</option> </select> </div> ) }For custom dropdowns, use Radix UI's
<Select>component or similar, which includes full ARIA support.
External references
- wcag:2.2 · 4.1.2 — Name, Role, Value
- wcag:2.2 · 2.1.1 — Keyboard
Taxons
History
- 2026-04-18·v1.0.0·Initial import from directory-search-discovery·automated