Skip to content

As a keyboard-only user I want to navigate and select muscles on the body map so I can use the core feature without a mouse #69

@ChristopherRotnes

Description

@ChristopherRotnes

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

  • All muscle <g> elements in BodySVG, HeatmapBodySVG, and MusclePicker are focusable via Tab
  • Each muscle element announces its Norwegian name via aria-label
  • Enter and Space trigger the same action as a mouse click in MusclePicker
  • Focus ring is visible and meets Carbon focus style on all focusable muscle shapes
  • Decorative elements (body outline, neck, head) are marked aria-hidden=\"true\"
  • SVG wrapper groups are labelled (aria-label=\"Frontside muskler\" / \"Bakside muskler\")
  • Keyboard navigation tested end-to-end: full workout log flow completable without a mouse

Metadata

Metadata

Assignees

No one assigned

    Labels

    accessibilityScreen reader, keyboard navigation, ARIA, reduced motionpriority: high

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions