# Interactive elements have accessible names

- **Pattern:** `ab-000050` (`accessibility-basics.semantic-structure-aria.accessible-names`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000050
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000050)

## Why it matters

Icon-only buttons — a close X, a hamburger menu, a heart for favorites — read as 'button' or are skipped entirely by screen readers when they carry no accessible name. WCAG 2.2 SC 4.1.2 (Name, Role, Value) requires every UI component to expose a name to assistive technology. SC 2.4.6 (Headings and Labels) requires labels to be descriptive. Section 508 2018 Refresh 502.3.1 mandates that all object information be programmatically determinable. A screen reader user navigating a list of 'View Details' links on a product listing page encounters identical announcements with no way to distinguish which product each link targets — this is a known and documented navigation failure mode. The business consequence is that entire interaction patterns are unusable by an estimated 7.5 million screen reader users in the US alone.

## Severity rationale

High because nameless interactive elements render entire interaction flows inaccessible to screen reader users, blocking navigation and task completion.

## Remediation

Every interactive element must expose a name through one of: visible text content, `aria-label`, `aria-labelledby`, or (rarely) `title`. In your button and link components:

```tsx
// Visible text — always preferred
<button>Save Changes</button>

// Icon-only: use aria-label
<button aria-label="Close dialog">
  <XIcon aria-hidden="true" size={20} />
</button>

// Disambiguate duplicate link text with aria-label
{products.map(product => (
  <a
    key={product.id}
    href={`/products/${product.slug}`}
    aria-label={`View details for ${product.name}`}
  >
    View Details
  </a>
))}

// aria-labelledby for names computed from sibling elements
<button aria-labelledby="doc-title-42">
  <DownloadIcon aria-hidden="true" />
</button>
<span id="doc-title-42">Q1 2024 Report</span>
```

Set `aria-hidden="true"` on decorative icons inside labeled buttons to prevent double-reading.

## Detection

- **ID:** `accessible-names`
- **Severity:** `high`
- **What to look for:** Enumerate every relevant item. Check all interactive elements (buttons, links, custom controls). Each must have an accessible name visible to screen readers, either from visible text, `aria-label`, `aria-labelledby`, or in rare cases, `title` attribute. Icon-only buttons are particularly common offenders.
- **Pass criteria:** At least 1 of the following conditions is met. Every interactive element (button, link, input, custom control) has an accessible name perceivable to screen readers.
- **Fail criteria:** Any interactive element lacks an accessible name, or has only a `title` attribute with no text content or ARIA label.
- **Skip (N/A) when:** Never — all interactive elements need accessible names.
- **Cross-reference:** For user-facing accessibility and compliance, the Accessibility Basics audit covers foundational requirements.
- **Detail on fail:** Specify which elements lack names. Example: `"Menu toggle button has no text or aria-label. Close button uses × icon with no aria-label. Search results 'View Details' links have duplicate text not distinguishable by screen reader."`
- **Remediation:** Provide accessible names for all interactive elements:

  ```tsx
  {/* Visible text */}
  <button>Save Changes</button>

  {/* Icon-only button with aria-label */}
  <button aria-label="Close menu">
    <X size={20} />
  </button>

  {/* Icon-only button with aria-labelledby */}
  <button aria-labelledby="save-icon-label">
    <SaveIcon id="save-icon-label" />
  </button>
  ```

## External references

- wcag 4.1.2
- wcag 2.4.6
- section-508 502.3.1

Taxons: accessibility

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