Skip to content

a11y(reputation): full keyboard operability#696

Merged
mikewheeleer merged 1 commit into
Talenttrust:mainfrom
Praiz089017:a11y/reputation-11-keyboard
Jul 25, 2026
Merged

a11y(reputation): full keyboard operability#696
mikewheeleer merged 1 commit into
Talenttrust:mainfrom
Praiz089017:a11y/reputation-11-keyboard

Conversation

@Praiz089017

Copy link
Copy Markdown
Contributor

Description

The Reputation Profile component's legend bands were static, non-interactive elements unreachable by keyboard. This PR makes every legend band fully keyboard-operable with a logical focus order, visible focus styles, and proper ARIA semantics.

Closes #623

Problem

  • Legend bands (Newcomer → Expert) had no tabIndex, no role, and no keyboard handlers
  • Keyboard users could not Tab into the legend at all
  • The <ul>/<li> structure prevented adding role="button" without axe violations

Solution

Converted the legend from <ul>/<li> to <div role="group"> with <div role="button"> bands. Each band now:

  1. Keyboard-focusable via tabIndex={0}
  2. Enter/Space activation via onKeyDown (Space also calls e.preventDefault())
  3. State communication via aria-pressed (true for active band)
  4. Accessible name via aria-label (e.g. "Trusted Partner level: 3.0 to 4.0")
  5. Visible focus styles via focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2

Type of Change

  • New feature

Pre-flight Checklist

  • npm run lint passes — 0 errors
  • npm test passes — 89/89 tests in ReputationProfile.test.tsx
  • npx tsc --noEmit passes — 0 type errors

Test Results

PASS src/components/ReputationProfile.test.tsx (89 tests)
  ✅ All 78 existing tests pass (no regressions)
  ✅ 11 new keyboard operability tests:
     - role="button" + tabIndex on all 5 bands
     - aria-pressed true on active band, false on inactive
     - aria-label describes level + range for each band
     - logical focus order: Newcomer → Contributor → Active Contributor → Trusted Partner → Expert
     - Enter key triggers click
     - Space key triggers click + prevents default scroll
     - Non-activation keys (ArrowRight) do not trigger click
     - No legend/buttons when score is undefined
     - axe audit passes (full history + keyboard legend)
     - axe audit passes (partial reputation + keyboard legend)

Cross-suite validation

  • a11y.test.tsx: 40/40 pass (all ReputationProfile a11y states)
  • reputation/page.test.tsx: 18/18 pass

Files Changed

src/components/ReputationProfile.tsx

  • Replaced <ul> with <div role="group" aria-labelledby="reputation-legend-title">
  • Replaced <li> with <div> carrying tabIndex={0}, role="button", aria-pressed, aria-label, onKeyDown, and focus-visible ring styles

src/components/ReputationProfile.test.tsx

  • Added fireEvent and getReputationBands imports
  • Updated 2 legend tests for new role="group" structure
  • Added 11 keyboard operability tests

Accessibility

  • ✅ 12 jest-axe audits pass with zero violations across all states
  • role="button" + aria-pressed pattern communicates state to screen readers
  • ✅ Focus order is logical and matches visual layout
  • ✅ Focus styles use the project's established focus-visible:ring-2 pattern

Edge Cases Covered

Edge Case Behavior
No score (undefined) No legend, no buttons in DOM
Score at boundary (0.0) Score 0 → Newcomer with aria-pressed=true
Score at max (5.0) Score 5 → Expert with aria-pressed=true
Non-Enter/Space keys Pass through without triggering
Space scroll suppression e.preventDefault() called
Custom maxScore Bands scale proportionally, keyboard operability preserved
Partial reputation Legend renders, keyboard-operable, no axe violations

Convert reputation level legend bands from static <ul>/<li> to keyboard-operable <div role="button"> elements with tabIndex, Enter/Space activation, visible focus styles, and aria-pressed for active state communication.

Closes Talenttrust#623
@drips-wave

drips-wave Bot commented Jul 25, 2026

Copy link
Copy Markdown

@Praiz089017 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@mikewheeleer

Copy link
Copy Markdown
Contributor

well done @Praiz089017, this reads well. merging in 🌟

@mikewheeleer
mikewheeleer merged commit 6888074 into Talenttrust:main Jul 25, 2026
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.

Make the reputation controls fully keyboard-operable

2 participants