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).
Low because the failure blocks keyboard and screen reader access to sorting without exposing data or creating a security risk.
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.
ID: directory-search-discovery.pagination-url.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.