Skip to content

feat: add accessibility support (ARIA labels, semantic HTML, keyboard nav)#8

Merged
intel352 merged 1 commit intomainfrom
feat/issue-4-accessibility
Feb 24, 2026
Merged

feat: add accessibility support (ARIA labels, semantic HTML, keyboard nav)#8
intel352 merged 1 commit intomainfrom
feat/issue-4-accessibility

Conversation

@intel352
Copy link
Contributor

Summary

  • Replace outer <div> with <main> landmark in LoginPage for proper page structure
  • Connect <label> elements to inputs via htmlFor/id pairs using useId() for stable unique IDs
  • Add aria-required="true" to required fields (reinforces native required attribute)
  • Add aria-label="Login form" to <form> for a named form landmark
  • Add aria-busy on the form and aria-disabled on the button during async login
  • Wrap error area in aria-live="polite" + aria-atomic="true" region for screen-reader announcements
  • Add role="alert" to error message div for immediate announcement on error
  • Add aria-describedby on inputs pointing to the error element when an error is shown
  • Add outlineColor on inputs and button for visible keyboard focus indicator (WCAG 2.1 AA)
  • Install vitest-axe and register toHaveNoViolations matcher in test setup
  • Add src/test/a11y.ts helper with checkA11y() utility
  • Add 18 new accessibility tests: axe violations, semantic HTML landmarks, ARIA attributes, live region error announcements, keyboard tab navigation
  • Fix pre-existing ErrorBoundary test (broken TDZ reference in Wrapper component)
  • Fix pre-existing LoadingSpinner test (wrong CSS selector for ring element)

Closes #4

Test plan

  • All 95 tests pass including 2 new axe violation tests
  • Build succeeds
  • Lint passes
  • Tab order: username → password → submit button
  • Enter key on submit button submits the form
  • Error messages announced via aria-live region
  • Form labeled with aria-label for screen readers

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings February 23, 2026 11:20
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive accessibility support to the workflow-ui library, including ARIA labels, semantic HTML, keyboard navigation, and automated a11y testing. The PR introduces 6 new reusable UI components (StatusBadge, DataTable, Modal, LoadingSpinner, ErrorBoundary, Sidebar) and enhances the existing LoginPage with proper accessibility attributes. However, there's a critical issue with keyboard focus indicators that prevents the accessibility improvements from being fully effective.

Changes:

  • Added vitest-axe for automated accessibility testing with configurable test helpers
  • Enhanced LoginPage with semantic HTML (<main> landmark), connected labels, ARIA attributes (aria-live, aria-busy, aria-required, aria-describedby), and keyboard focus indicators (though these have implementation issues)
  • Created 6 new UI components with comprehensive test coverage (except Sidebar which lacks tests)

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
package.json Added vitest-axe dependency, updated eslint-plugin-react-refresh to ^0.5.1, added ./components export
package-lock.json Lock file updates for new dependencies
vite.config.ts Added components/index entry point for library build
src/test/setup.ts Registered vitest-axe matchers globally
src/test/a11y.ts Created checkA11y() helper for accessibility testing
src/index.ts Exported all new components and their types from components module
src/components/index.ts Created barrel export for all UI components
src/components/StatusBadge.tsx New badge component with status indicators and pulsing animation
src/components/StatusBadge.test.tsx Comprehensive tests for StatusBadge component
src/components/Sidebar.tsx New navigation sidebar with collapse/expand, ARIA labels, and keyboard support
src/components/Modal.tsx New modal dialog with proper ARIA attributes, focus trap, and keyboard support
src/components/Modal.test.tsx Comprehensive tests for Modal including accessibility checks
src/components/LoadingSpinner.tsx New loading spinner with aria-live status announcements
src/components/LoadingSpinner.test.tsx Tests for LoadingSpinner including ARIA attributes
src/components/ErrorBoundary.tsx New error boundary component with role="alert"
src/components/ErrorBoundary.test.tsx Comprehensive tests for ErrorBoundary error handling
src/components/DataTable.tsx New data table with sorting, pagination, and ARIA attributes
src/components/DataTable.test.tsx Comprehensive tests for DataTable functionality
src/auth/LoginPage.tsx Enhanced with semantic HTML, ARIA attributes, live regions, and keyboard focus indicators (with implementation issues)
src/auth/LoginPage.test.tsx Added 18 new accessibility tests covering axe violations, ARIA attributes, and keyboard navigation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

width: '100%',
padding: '10px',
fontSize: '15px',
opacity: loading ? 0.7 : 1,
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting outlineColor alone will not produce a visible keyboard focus indicator on the submit button. The button needs an explicit outline style such as outline: '2px solid' in addition to outlineColor to ensure keyboard users can see focus indication (WCAG 2.1 AA compliance).

Suggested change
opacity: loading ? 0.7 : 1,
opacity: loading ? 0.7 : 1,
outline: '2px solid',

Copilot uses AI. Check for mistakes.
Comment on lines +144 to +147
style={{
...baseStyles.input,
outlineColor: colors.blue,
}}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting outlineColor will not produce a visible keyboard focus indicator because baseStyles.input has outline: 'none'. To achieve WCAG 2.1 AA compliant keyboard focus indicators, you need to either remove the outline: 'none' from baseStyles.input or override it with a valid outline style (e.g., outline: '2px solid', outlineColor: colors.blue) instead of just setting outlineColor.

Copilot uses AI. Check for mistakes.
Comment on lines +173 to +176
style={{
...baseStyles.input,
outlineColor: colors.blue,
}}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting outlineColor will not produce a visible keyboard focus indicator because baseStyles.input has outline: 'none'. To achieve WCAG 2.1 AA compliant keyboard focus indicators, you need to either remove the outline: 'none' from baseStyles.input or override it with a valid outline style (e.g., outline: '2px solid', outlineColor: colors.blue) instead of just setting outlineColor.

Copilot uses AI. Check for mistakes.
- Add ARIA labels, roles, and semantic HTML to LoginPage component
- Add aria-busy, aria-disabled, and aria-live for loading states
- Add useId() for stable form element ID associations
- Add vitest-axe for automated accessibility testing
- Add checkA11y() test helper with axe-core integration
- Add 18 new accessibility-focused tests for LoginPage

Closes #4

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@intel352 intel352 force-pushed the feat/issue-4-accessibility branch from b15914e to e1335bc Compare February 23, 2026 11:26
@intel352 intel352 merged commit 28f197a into main Feb 24, 2026
3 checks passed
@intel352 intel352 deleted the feat/issue-4-accessibility branch February 24, 2026 01:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add accessibility support (ARIA labels, semantic HTML, keyboard nav)

2 participants