There are two aria-*/role attributes in the entire component tree. The boards are data tables rendered as divs, the meters convey state through colour and width alone, and focus states are mostly browser defaults.
What to do
Pick one board and do it properly — this does not need to land in one PR:
- Semantic table markup, or
role="table" / role="row" / role="cell" where the layout requires divs
aria-label on the meters, with the numeric value exposed as text for screen readers
- Visible focus rings that meet contrast requirements
aria-live="polite" on the signal feed so new rows are announced without stealing focus
- Check that no state is communicated by colour alone
Acceptance
Notes
The palette is already colour-vision-deficiency separated — see tailwind.config.ts. Use the theme tokens, never raw hex.
There are two
aria-*/roleattributes in the entire component tree. The boards are data tables rendered as divs, the meters convey state through colour and width alone, and focus states are mostly browser defaults.What to do
Pick one board and do it properly — this does not need to land in one PR:
role="table"/role="row"/role="cell"where the layout requires divsaria-labelon the meters, with the numeric value exposed as text for screen readersaria-live="polite"on the signal feed so new rows are announced without stealing focusAcceptance
npx tsc --noEmitandnpm run buildcleanNotes
The palette is already colour-vision-deficiency separated — see
tailwind.config.ts. Use the theme tokens, never raw hex.