Summary
The SVG body map (app/src/lib/bodymap.jsx) and MusclePicker component (app/src/components/MusclePicker.jsx) are the core interaction of the app, but they are entirely mouse-dependent. The SVG <g> muscle elements have onClick handlers but no tabIndex, no role, no keyboard event handlers, and no aria-label. A keyboard-only user or screen reader user cannot select, deselect, or identify any muscle group.
Priority
High
UI spec (Carbon g100)
- Each muscle
<g> element must receive tabIndex={0}, role=\"button\", and aria-label with the Norwegian muscle name (from MUSCLES[id].label)
- On keyboard focus, the muscle shape must show the same 2px
#0f62fe focus ring used across the rest of the app (consistent with Carbon focus style)
onKeyDown handler must respond to Enter and Space to trigger the click/toggle action
- In
MusclePicker, arrow keys should cycle focus between muscle groups within the same view (front/back)
- The SVG wrapper should have
role=\"group\" and an aria-label such as \"Frontside muskler\" / \"Bakside muskler\"
- Decorative body outline elements (head, torso path) must have
aria-hidden=\"true\" so screen readers only announce the interactive muscle shapes
HeatmapBodySVG (read-only): muscle shapes should have role=\"img\" and aria-label describing their activation state (e.g. \"Biceps – primær\")
- The internal tooltip must continue to be suppressed when
onHover prop is provided (existing behaviour preserved)
Acceptance criteria
Summary
The SVG body map (
app/src/lib/bodymap.jsx) andMusclePickercomponent (app/src/components/MusclePicker.jsx) are the core interaction of the app, but they are entirely mouse-dependent. The SVG<g>muscle elements haveonClickhandlers but notabIndex, norole, no keyboard event handlers, and noaria-label. A keyboard-only user or screen reader user cannot select, deselect, or identify any muscle group.Priority
High
UI spec (Carbon g100)
<g>element must receivetabIndex={0},role=\"button\", andaria-labelwith the Norwegian muscle name (fromMUSCLES[id].label)#0f62fefocus ring used across the rest of the app (consistent with Carbon focus style)onKeyDownhandler must respond toEnterandSpaceto trigger the click/toggle actionMusclePicker, arrow keys should cycle focus between muscle groups within the same view (front/back)role=\"group\"and anaria-labelsuch as\"Frontside muskler\"/\"Bakside muskler\"aria-hidden=\"true\"so screen readers only announce the interactive muscle shapesHeatmapBodySVG(read-only): muscle shapes should haverole=\"img\"andaria-labeldescribing their activation state (e.g.\"Biceps – primær\")onHoverprop is provided (existing behaviour preserved)Acceptance criteria
<g>elements inBodySVG,HeatmapBodySVG, andMusclePickerare focusable via Tabaria-labelEnterandSpacetrigger the same action as a mouse click inMusclePickeraria-hidden=\"true\"aria-label=\"Frontside muskler\"/\"Bakside muskler\")