[P3] Timeline range inputs give screen readers raw sample indices or fractional minutes instead of the formatted time #119
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Priority: P3
Type: bug
Source: full codebase review requested 2026-10-31 (independently reproduced against
2cac7cf)Location:
src/replay/DiveSummary.tsx:207-217,src/import/DiveImport.tsx:513-523,src/replay/DiveReplayComparison.tsx:606-622,src/planner/ProfilePlanner.tsx:830-843Problem and evidence
Each of the four timeline sliders sits inside a
<label>whose visible text holds the formatted time (for example "Timeline · 1:21"). Each also sets a staticaria-label. Under accessible-name computation,aria-labeltakes precedence over the native<label>, so the visible time never becomes part of the name. None of the four setsaria-valuetext, so assistive technology announces the rawvalue:max={samples.length-1},step="1").step="any", so values like 0.2176...).step="0.01").The codebase already uses
aria-valuetextin other places (App.tsx:2932 conservativeness slider, TankPressureGauge.tsx:37), which shows this is the intended pattern and these four are inconsistent with it.Read all four sites at HEAD
2cac7cf:<label>Timeline · {formatTime(...)}<input type="range" aria-label="Dive summary timeline" max={samples.length - 1} step="1" value={position}/>aria-label="Imported dive timeline"and the value as a sample index.aria-label="Comparison replay timeline",step="any", value = time in minutes.aria-label="Profile timeline",step="0.01".grep -rn aria-valuetext srcmatches only App.tsx and TankPressureGauge.tsx. None of the four inputs hasaria-describedby. The accessible name therefore comes fromaria-labelalone, and the announced value is the numericvalue. I did not rerun the reviewer's Playwright snapshot. The result follows from the markup and the accname precedence rules, and it matches the reviewer's ariaSnapshot (slider "Comparison replay timeline": "0.217620266666666").Suggested correction
Add
aria-valuetextto each slider:formatTime(sample.time - first.time)time(sample.seconds / 60)formatTime(time)formatTime(position)Optionally add context such as "of {formatTime(duration)}". Keep the existing aria-labels so test selectors stay stable, or drop them so the visible label supplies the name. For the replay slider, consider a finite step (for example 1/60 minute) so arrow keys move by whole seconds instead of arbitrary fractions.
Acceptance criteria
Each of the four sliders exposes an aria-valuetext with the same formatted m:ss time its visible label shows. A Playwright ariaSnapshot after arrowing a slider shows
slider "<name>": "m:ss"-style text, not a raw index or decimal. Regression test: a component or Playwright test per slider that changes the value and checks that thearia-valuetextattribute equals the formatted time text in the label. pnpm verify passes.Scope: maintenance of the educational simulator. Preserve historical R1 acceptance and operational-validation limits.