Turn React Component Findings into Accessibility Tickets
React accessibility bugs become easier to fix when the ticket names the component, the affected props or states, and the product routes where users hit the problem.
Use this guide for component-level findings in React, Next.js, Remix, Gatsby, or other single-page app flows: custom buttons, dialogs, menus, tabs, route changes, async updates, validation summaries, and reused design-system components.
Draft the React ticket
Open a prefilled component finding in the generator. The structured fields include the component path, failing interaction state, affected routes, and acceptance criteria.
What to capture from the finding
- Component name: React component, package, Storybook story, or design-system primitive where the defect lives.
- Affected states: open, closed, loading, invalid, disabled, selected, expanded, error, empty, success, or route-transition state.
- Affected routes: list every product flow that reuses the component, especially checkout, login, account, search, or admin views.
- User path: keyboard steps, screen reader announcements, pointer-independent operation, or route-change behavior.
- Ownership split: component fix, product integration fix, test fixture, documentation update, or migration note.
Ticket structure
Title: [Severity] Component name: React state does not expose expected accessible behavior User impact: Explain the task that becomes blocked, confusing, or high effort when the component state is not exposed or managed correctly. Evidence: - Component: - Package or app area: - Affected route(s): - Affected prop/state: - Trigger or user action: - Expected keyboard or screen reader result: - Actual result: - Browser and assistive technology: Likely WCAG references to verify: - 2.1.1 Keyboard, when the component cannot be operated without a pointer. - 2.4.3 Focus Order, when focus moves unpredictably after state changes or route changes. - 2.4.7 Focus Visible, when focus styling disappears inside the component. - 4.1.2 Name, Role, Value, when role, accessible name, expanded state, selected state, or dialog naming is missing. - 4.1.3 Status Messages, when async updates, saved states, result counts, or validation messages are not announced. Acceptance criteria: - The affected component exposes the expected name, role, value, and state in each listed state. - Keyboard focus moves predictably when the state changes and returns to a useful place after dismissal. - The fix passes on every listed route that uses the component. - Component tests, Storybook stories, or product-level regression checks cover the failing state. - Documentation or usage notes are updated when the component API changes.
Paste your React component note into the generator when you want this structure drafted from raw audit text.
Example conversion: route change focus
Raw note: After submitting the React search form, the route changes from /search to /search?query=boots, but focus stays on the submit button. NVDA does not announce the new results heading or result count. Developer ticket: [High] Search route: React route change does not move focus or announce new results User impact: Screen reader and keyboard users may not realize the page content changed after submitting search. They must manually explore the page to find the new results and count. Evidence: - Component: SearchPage route shell - Route: /search to /search?query=boots - State: results loaded - Trigger: Submit search form - Actual result: focus remains on submit button and the result count is silent - Expected result: focus moves to the results heading or an equivalent status message announces the loaded result count Likely WCAG references to verify: - 2.4.3 Focus Order - 4.1.3 Status Messages Acceptance criteria: - After a successful search route update, focus moves to the results heading or another agreed target. - Result count changes are announced without moving focus when users refine filters. - The implementation does not create duplicate announcements during typing or loading. - Keyboard and NVDA retests pass for initial search and later filter changes.
Example conversion: custom select state
Raw note: React ProductSortSelect uses a div-based menu. VoiceOver announces "Sort by" but not button, expanded, selected option, or the current sort value. Developer ticket: [Medium] ProductSortSelect: custom sort control does not expose role, expanded state, or selected value User impact: Screen reader users cannot tell that the control opens a menu, whether it is expanded, or which sort option is currently selected. Evidence: - Component: ProductSortSelect - Routes: category listing and search results - State: closed and open - Expected result: trigger exposes a control role, useful accessible name, expanded state, and current selected value - Actual result: VoiceOver announces only "Sort by" Likely WCAG references to verify: - 4.1.2 Name, Role, Value - 2.1.1 Keyboard Acceptance criteria: - The sort trigger exposes a correct role, accessible name, expanded state, and current value. - Menu options are keyboard reachable and expose selected state. - The visual selected state and programmatic selected state remain synchronized. - Category listing and search results both pass the retest.
Common fix directions
- Prefer native controls: use button, input, select, fieldset, dialog patterns, and semantic headings before adding ARIA to generic elements.
- Ticket the shared component when reuse is broad: fixing one product screen may leave the same bug in every route that imports the component.
- Include state coverage: collapsed, expanded, loading, invalid, selected, and disabled states often need separate assertions.
- Keep route focus deliberate: single-page navigation should not leave keyboard focus stranded on stale controls.
- Retest the integration: a Storybook fix still needs at least one product route check when surrounding headings, labels, portals, or layout affect the result.
Paste-ready input for the generator
React component finding: Component: Package or app area: Affected route(s): Affected prop/state: Trigger or user action: Expected keyboard or screen reader behavior: Actual keyboard or screen reader behavior: Assistive technology and browser: Shared usage / rollout note: Retest notes:
Open the accessibility ticket generator and paste this structure with the component finding.