You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Explorer: modal focus management and non-duplicated drag redraw
The two follow-ups worth taking from the review of the previous change.
Both were listed in that commit as deliberately deferred.
Modal focus management (WCAG 2.4.3, 4.1.2)
The overlays had no dialog semantics and no focus handling: opening one
left focus behind on the page, closing it dropped the user at the top
of the document, and Tab walked straight out into the page behind the
dialog. Added role="dialog" + aria-modal + an accessible name, focus
into the dialog on open, restore to the trigger on close, and a Tab
trap in both directions.
aria-modal hides the background from assistive tech but does nothing
about the tab order, which is why the trap is also needed.
One non-obvious interaction: the previous change hid the closed
overlays with `transition: opacity, visibility 0.25s`. Transitioning
visibility symmetrically keeps the overlay non-visible for the whole
250 ms after opening, and a visibility:hidden element cannot take
focus -- the focus() call was silently rejected, with focus() invoked
but no focusin event. Visibility now flips immediately on open and is
delayed only on close, so the fade-out still reads correctly.
Drag redraw no longer runs twice per frame
onSliderChange both schedules a coalesced redraw and keeps the
animation loop alive, and the loop already redraws both canvases every
frame -- so update() from the coalesced callback drew them again.
Measured over a sustained drag: 1.68 canvas redraws per animation
frame, i.e. ~40% wasted work on the one interaction path that the
worker, mean-only and crossfade work never touched.
The loop owns the canvases while it is running; the coalesced callback
still performs the non-canvas work, since dropping it would freeze the
readouts and the screen-reader summary mid-drag.
1.68 -> 1.08 redraws per frame, and 47 -> 65 frames completed in the
same 2 s window.
Not taken, with reasons, so this does not get re-litigated:
- #scatter-canvas still has no text equivalent. It is the primary
surface, but a 149-row table helps nobody; exposing it well means
deciding what to surface (Pareto frontier summary? keyboard navigation
between points?) and is a design task, not a small fix.
- _reduceMotion is still sampled once at module load. Live-updating it
is ~5 lines, but the only way to hit the gap is flipping the OS
setting mid-session.
Verification: lint 0, test-js 13/13, e2e 105 on macOS and 109 on Linux
in the matching Playwright image, both Lighthouse profiles green with
zero failing accessibility audits. The new modal-focus and drag-redraw
tests were each confirmed to fail against the defect they pin.
<h2id="about-modal-title">About This Explorer</h2>
132
132
<p>This tool predicts concrete compressive strength using a Gaussian Process model trained on laboratory mortar and concrete specimens. Predictions reflect controlled lab conditions and <strong>may differ from field performance</strong> due to batching variability, curing environment, and aggregate properties.</p>
0 commit comments