File: crates/web/src/components/lifecycle.rs:64
Severity: robustness — availability (UI hangs under reduced-motion)
Obvious? yes — sibling-of-closed (#496 8d89f18)
is_zero_duration only treats "", "0s", "0ms" as zero (line 79). But crates/web/style.css:4481-4485 defines a global @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: 0.01ms !important; } } rule.
Under reduced-motion the computed transition-duration is "0.01ms", which the helper rejects → snap shortcut skipped → mobile_shell, confirm_dialog, action sheet all sit waiting for a transitionend that may either never fire (no transitionable property changed) or fire so fast the test/UI races.
Commit 8d89f18's claim "confirm_dialog uses animation, no transition; lifecycle relies on the snap shortcut" only holds if the snap actually fires — under reduced-motion it doesn't, because 0.01ms flunks the equality test.
Fix: also treat sub-1ms durations (or anything ≤ small epsilon) as zero — global override is the authoritative reduced-motion contract.
Filed by /general-audit @ b901575 (2026-05-02). master: #513.
File:
crates/web/src/components/lifecycle.rs:64Severity: robustness — availability (UI hangs under reduced-motion)
Obvious? yes — sibling-of-closed (#496 8d89f18)
is_zero_durationonly treats"","0s","0ms"as zero (line 79). Butcrates/web/style.css:4481-4485defines a global@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: 0.01ms !important; } }rule.Under reduced-motion the computed
transition-durationis"0.01ms", which the helper rejects → snap shortcut skipped → mobile_shell, confirm_dialog, action sheet all sit waiting for a transitionend that may either never fire (no transitionable property changed) or fire so fast the test/UI races.Commit 8d89f18's claim "confirm_dialog uses animation, no transition; lifecycle relies on the snap shortcut" only holds if the snap actually fires — under reduced-motion it doesn't, because
0.01msflunks the equality test.Fix: also treat sub-1ms durations (or anything ≤ small epsilon) as zero — global override is the authoritative reduced-motion contract.
Filed by
/general-audit@b901575(2026-05-02). master: #513.