# Search input has accessible label; autocomplete uses ARIA live region

- **Pattern:** `ab-001072` (`directory-search-discovery.pagination-url.search-a11y`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001072
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001072)

## Why it matters

A search input without an associated label fails WCAG 2.2 SC 4.1.2 (Name, Role, Value) — screen readers announce the field as "edit text" with no context, making it unusable for blind users. Autocomplete dropdowns that don't use `aria-live` or `role="listbox"` are invisible to assistive technology: suggestions appear visually but are never announced, so keyboard and screen reader users cannot benefit from them. WCAG 2.2 SC 4.1.3 (Status Messages) further requires that dynamic content changes like suggestion updates be communicated without requiring focus movement.

## Severity rationale

Medium because the failure eliminates search usability for screen reader users while stopping short of a critical data or security exposure.

## Remediation

Label the search input explicitly and annotate the suggestions container with ARIA roles. In `components/SearchInput.tsx`:

```tsx
<label htmlFor="search-input">Search listings</label>
<input
  id="search-input"
  type="text"
  role="combobox"
  aria-expanded={suggestions.length > 0}
  aria-autocomplete="list"
  aria-controls="suggestions-list"
/>
{suggestions.length > 0 && (
  <ul
    id="suggestions-list"
    role="listbox"
    aria-live="polite"
  >
    {suggestions.map((s, i) => (
      <li key={i} role="option">{s.name}</li>
    ))}
  </ul>
)}
```

`aria-live="polite"` causes screen readers to announce new suggestions without interrupting the user's current context. Test with VoiceOver (macOS) or NVDA (Windows) to verify announcements fire on each suggestion update.

## Detection

- **ID:** `search-a11y`
- **Severity:** `medium`
- **What to look for:** Enumerate all relevant files and Inspect the search input. Check for an associated `<label>` element or `aria-label`/`aria-labelledby` on the input. For autocomplete suggestions, check whether there's an `aria-live="polite"` or `role="listbox"` on the suggestions container so screen readers announce new suggestions.
- **Pass criteria:** At least 1 implementation must be present. Search input has a label (visible or via aria-label). Autocomplete suggestions container uses `aria-live="polite"` or `role="combobox"` + `aria-expanded`, allowing screen readers to announce new suggestions.
- **Fail criteria:** Search input has no label. Autocomplete suggestions are not announced to screen readers.
- **Skip (N/A) when:** Search is not implemented. Signal: no search input found.
- **Detail on fail:** `"Search input has no label or aria-label."` or `"Autocomplete dropdown has no aria-live. Screen readers won't announce suggestions."`
- **Remediation:** Add accessibility attributes to search and autocomplete:

  ```tsx
  // components/SearchInput.tsx
  export function SearchInput({ onSuggestionSelect }) {
    const [suggestions, setSuggestions] = useState([])

    return (
      <div className="relative">
        <label htmlFor="search-input">Search listings</label>
        <input
          id="search-input"
          type="text"
          onChange={e => handleSearchChange(e.target.value)}
          aria-describedby="suggestions-list"
          role="combobox"
          aria-expanded={suggestions.length > 0}
          aria-autocomplete="list"
        />
        {suggestions.length > 0 && (
          <ul
            id="suggestions-list"
            role="listbox"
            aria-live="polite"
            className="absolute top-full left-0 right-0 bg-white border"
          >
            {suggestions.map((s, i) => (
              <li key={i} role="option" onClick={() => onSuggestionSelect(s)}>
                {s.name}
              </li>
            ))}
          </ul>
        )}
      </div>
    )
  }
  ```

## External references

- wcag 1.3.1
- wcag 4.1.3
- wcag 4.1.2

Taxons: accessibility

HTML version: https://auditbuffet.com/patterns/ab-001072
