09 — Fix Accessibility Issues
Fix accessibility issues found in a module or component via axe-core, Lighthouse, or manual audit.
Examples: Missing ARIA attributes, keyboard navigation broken, focus not visible, color contrast failing.
Context Loading
Section titled “Context Loading”Read these files before executing the prompt:
docs/PRD/14_Accessibility_and_Compliance.mddocs/dev-frontend-guides/03_MODULE_DEVELOPMENT_LIFECYCLE.md # a11y checklist sectionpackages/modules/src/{MODULE_PATH}/ # all files in the affected modulepackages/ui/src/ # if the issue is in a shared UI componentPrompt Template
Section titled “Prompt Template”Read the following context files first:- docs/PRD/14_Accessibility_and_Compliance.md- docs/dev-frontend-guides/03_MODULE_DEVELOPMENT_LIFECYCLE.md- {COMPONENT_FILES — list each file in the module directory}
Now fix the following accessibility issue:
**Component Path:** packages/{PACKAGE}/src/{COMPONENT_PATH}/**Component Name:** {COMPONENT_NAME}**Module ID:** {MODULE_ID}
**Issue Source:** {axe-core | Lighthouse | manual audit | screen reader testing}**WCAG Criterion Violated:** {WCAG_CRITERION — e.g., 2.1.1 Keyboard, 4.1.2 Name/Role/Value, 1.4.3 Contrast}**WCAG Level:** {A | AA}
**Issue Description:**{DESCRIBE_THE_SPECIFIC_ACCESSIBILITY_PROBLEM}
**Current Behavior:**{WHAT_HAPPENS_NOW — e.g., "Pressing Enter on accordion header does nothing", "Icon button has no accessible name"}
**Expected Behavior:**{WHAT_SHOULD_HAPPEN — e.g., "Pressing Enter or Space toggles the accordion panel", "Icon button announces 'Close menu' to screen readers"}
**Steps to Reproduce:**{HOW_TO_TRIGGER_THE_ISSUE — e.g., "Tab to the accordion header, press Enter — nothing happens"}
**Additional Context:**{ANY_EXTRA_INFO — e.g., "This also affects M14 FAQ which uses the same accordion pattern"}
Fix the issue following these requirements:- WCAG 2.1 AA compliance is mandatory for all components- axe-core must report zero violations after the fix- Keyboard navigation must work fully (Tab, Shift+Tab, Enter, Space, Escape, Arrow keys where applicable)- Screen readers (VoiceOver, NVDA) must announce the correct state and role- Focus must be visible at all times with a clear focus indicator- Color contrast must meet 4.5:1 for normal text, 3:1 for large text- ARIA attributes must follow WAI-ARIA 1.2 authoring practices- No information may be conveyed only through color — use text, icons, or patterns as well- Update the component's test file to include a11y regression tests- Update Storybook stories if the fix changes the component's rendered outputAcceptance Criteria
Section titled “Acceptance Criteria”- The specific WCAG criterion violation is resolved
- axe-core reports zero violations on the component (test with
@axe-core/reactor Storybook a11y addon) - Full keyboard navigation works: Tab, Shift+Tab, Enter, Space, Escape, and Arrow keys where applicable
- Screen reader announces correct role, name, and state (test with VoiceOver on macOS)
- Focus indicator is visible on all interactive elements (meets WCAG 2.4.7)
- Color contrast meets minimum ratios: 4.5:1 for normal text, 3:1 for large text (WCAG 1.4.3)
- ARIA attributes are correct and follow WAI-ARIA 1.2 authoring practices
- No content is conveyed only through color (WCAG 1.4.1)
- Component test file updated with a11y regression test covering the fixed issue
- Storybook stories updated if the rendered output changed
- Fix works correctly in all 8 hotel themes (different color palettes may affect contrast)
- Fix does not break any existing functionality or visual design
-
pnpm testpasses with the updated test file - No new TypeScript errors introduced
Common Pitfalls
Section titled “Common Pitfalls”- Missing
aria-labelon icon-only buttons — Buttons with only an icon (close, menu, arrow) must havearia-labeldescribing the action:<button aria-label="Close menu">. - Missing
alttext on images — Every<img>needsalt. Decorative images usealt=""withrole="presentation". Content images need descriptivealttext. - Focus indicator not visible — The default browser outline is often overridden by
outline: none. Always provide a visible custom focus style using CSS custom properties for theme compatibility. - Skip-to-content link missing — The page layout must include a skip link as the first focusable element that jumps to
#main-content. aria-expandednot toggled — Accordion headers, dropdown triggers, and menu buttons must togglearia-expanded="true"/aria-expanded="false"on state change.- Focus not trapped in modals — When a modal or dialog is open, focus must be trapped inside it. Tab from the last element should cycle to the first. Escape must close the modal.
- Missing landmark roles — Page sections should use semantic HTML5 landmarks (
<nav>,<main>,<aside>,<footer>) or explicitroleattributes. - Interactive elements not reachable by keyboard — Click handlers on
<div>or<span>are not keyboard accessible. Use<button>or<a>or addrole,tabindex="0", and key event handlers. - Heading level hierarchy skipped — Heading levels must not skip (e.g.,
<h2>followed by<h4>). Maintain sequential order within each section. - Form inputs without labels — Every
<input>,<select>, and<textarea>must have an associated<label>viahtmlFor, or usearia-label/aria-labelledby.
Example
Section titled “Example”Filled-in prompt for M13 Accordion — Keyboard and ARIA issues:
Read the following context files first:- docs/PRD/14_Accessibility_and_Compliance.md- docs/dev-frontend-guides/03_MODULE_DEVELOPMENT_LIFECYCLE.md- packages/modules/src/m13-accordion/index.tsx- packages/modules/src/m13-accordion/m13-accordion.module.scss- packages/modules/src/m13-accordion/m13-accordion.types.ts- packages/modules/src/m13-accordion/m13-accordion.test.tsx- packages/modules/src/m13-accordion/m13-accordion.stories.tsx
Now fix the following accessibility issue:
**Component Path:** packages/modules/src/m13-accordion/**Component Name:** Accordion**Module ID:** M13
**Issue Source:** axe-core + manual keyboard audit**WCAG Criterion Violated:** 2.1.1 Keyboard (Level A), 4.1.2 Name/Role/Value (Level A)**WCAG Level:** A
**Issue Description:**The accordion component has three accessibility violations:1. Pressing Enter or Space on an accordion header does not toggle the panel open/closed2. The `aria-expanded` attribute is missing from accordion header buttons3. The focus indicator is not visible on accordion panels when navigating with Tab
**Current Behavior:**- Accordion headers respond to mouse click only — keyboard Enter and Space do nothing- No `aria-expanded` attribute exists, so screen readers cannot announce whether a panel is open or closed- When tabbing through accordion items, the focus ring is invisible due to `outline: none` in the SCSS with no replacement style
**Expected Behavior:**- Pressing Enter or Space on a focused accordion header toggles the associated panel open/closed- Each header has `aria-expanded="true"` when open and `aria-expanded="false"` when closed- Each header has `aria-controls` pointing to the panel's `id`- Focus ring is clearly visible on all accordion headers using the theme's focus token `var(--focus-ring-color)`- Arrow Up/Down moves focus between accordion headers
**Steps to Reproduce:**1. Open Storybook, navigate to M13 Accordion > Default story2. Press Tab to focus the first accordion header3. Press Enter — nothing happens (panel does not toggle)4. Inspect the header element — no `aria-expanded` attribute present5. Observe no visible focus indicator on the header
**Additional Context:**This same accordion pattern is used by M14 FAQ. The fix here should also apply there.
Fix the issue following these requirements:- WCAG 2.1 AA compliance is mandatory for all components- axe-core must report zero violations after the fix- Keyboard navigation must work fully (Tab, Shift+Tab, Enter, Space, Escape, Arrow keys where applicable)- Screen readers (VoiceOver, NVDA) must announce the correct state and role- Focus must be visible at all times with a clear focus indicator- Color contrast must meet 4.5:1 for normal text, 3:1 for large text- ARIA attributes must follow WAI-ARIA 1.2 authoring practices- No information may be conveyed only through color — use text, icons, or patterns as well- Update the component's test file to include a11y regression tests- Update Storybook stories if the fix changes the component's rendered output