feat(ui): swap the in-turn loader for a brain-wave sweep left of the send button
Phase 117 (owner request, live-mockup-confirmed): the phase-109 3-dot cue becomes a compact ECG trace (49px, P/QRS/T) with a brand sweep traveling the path (bwdraw, 42/140 dash segment, 0.9s loop), the loader repositioned left of the button so its appearance never shifts it. setUiState stays the sole owner of the loader's hidden attribute; the reduced-motion variant stills the sweep. Unit + lifecycle-E2E pins updated for the new contract.
This commit is contained in:
@@ -54,8 +54,9 @@ context, ``_reset_db`` reseeds the KB deterministically):
|
||||
``SEND_STATUS`` idle shape (empty — not stuck on a mid-turn label);
|
||||
then, in a context with ``reducedMotion: "reduce"`` (the Playwright
|
||||
context option), a second turn shows the loader STILL visible
|
||||
mid-turn — the reduced-motion variant stills the dots (computed
|
||||
``animation-name: none``), it does not HIDE the cue: visibility is
|
||||
mid-turn — the reduced-motion variant stills the sweep (the phase-
|
||||
117 brain wave: computed ``animation-name: none`` on the ``.bw-pulse``
|
||||
path), it does not HIDE the cue: visibility is
|
||||
owned by the JS ``hidden`` attribute in ``setUiState`` (D16), not by
|
||||
CSS.
|
||||
"""
|
||||
@@ -281,13 +282,20 @@ def test_loader_a11y_and_reduced_motion(
|
||||
status = page.locator("#send-status")
|
||||
expect(status).to_have_attribute("aria-live", "polite")
|
||||
expect(status).to_have_text("")
|
||||
# Control (default-motion context): the loader's dots run the
|
||||
# typing animation — the reduced-motion check below stills it.
|
||||
# Control (default-motion context): the CONTAINER carries no
|
||||
# animation — the SWEEP path runs the phase-117 bwdraw travel —
|
||||
# the reduced-motion check below stills it.
|
||||
assert (
|
||||
page.evaluate(
|
||||
"getComputedStyle(document.querySelector('#turn-loader')).animationName"
|
||||
)
|
||||
== "typing"
|
||||
== "none"
|
||||
)
|
||||
assert (
|
||||
page.evaluate(
|
||||
"getComputedStyle(document.querySelector('#turn-loader .bw-pulse')).animationName"
|
||||
)
|
||||
== "bwdraw"
|
||||
)
|
||||
|
||||
# Reduced motion: a FRESH context with ``reducedMotion: "reduce"``
|
||||
@@ -308,12 +316,13 @@ def test_loader_a11y_and_reduced_motion(
|
||||
# loader is still the visible cue ...
|
||||
expect(rm_page.locator(".tool-call")).to_be_visible(timeout=30_000)
|
||||
expect(rm_page.locator("#turn-loader")).to_be_visible()
|
||||
# ... and the reduced-motion CSS variant IS applied: static
|
||||
# dots, no pulse (the animation is gone from the computed
|
||||
# style — the element itself is unchanged).
|
||||
# ... and the reduced-motion CSS variant IS applied: the full
|
||||
# trace shows static, no travel (the animation is gone from
|
||||
# the sweep path's computed style — the loader itself is
|
||||
# unchanged).
|
||||
assert (
|
||||
rm_page.evaluate(
|
||||
"getComputedStyle(document.querySelector('#turn-loader')).animationName"
|
||||
"getComputedStyle(document.querySelector('#turn-loader .bw-pulse')).animationName"
|
||||
)
|
||||
== "none"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user