refactor(web): replace RunningBorder SVG arc with CSS body-shimmer - #2274
refactor(web): replace RunningBorder SVG arc with CSS body-shimmer#2274lsm wants to merge 2 commits into
Conversation
Replace the heavy SVG 'chasing glow' running indicator (inline SVG + animateMotion + ResizeObserver) with a lightweight pure-CSS shimmer sweep across the card body — the 'option 4' mockup the user approved. - Add .running-shimmer overlay + @Keyframes runningShimmer to styles.css: faint white left->right gradient, background-size 200%, ~1.8s loop, position:absolute inset-0 pointer-events:none, honors prefers-reduced-motion. - ThinkingBlock / SubagentBlock / ToolResultCard: drop the <RunningBorder> wrapper; render the overlay as a child while isRunning and add 'relative' to the card when running. Existing isRunning gating is unchanged. - Delete packages/web/src/components/sdk/RunningBorder.tsx. - Update doc/comment references to describe the shimmer instead of the SVG arc. - Add ThinkingBlock test that .running-shimmer is present while running and absent when not.
lsm
left a comment
There was a problem hiding this comment.
🤖 Review by glm-5.1 (GLM)
Model: glm-5.1 | Client: NeoKai | Provider: GLM
Recommendation: REQUEST_CHANGES — 1 P2 finding (one missed stale comment). The refactor itself is correct and well-scoped; all verification passed.
Verified ✅
bun run check(root: oxlint +tsc --build --noEmit+ knip + session-guards + space-task-handler-tests + db-schema-parity + test-quality) — clean, exit 0.- Block tests green: ThinkingBlock (incl. 2 new shimmer tests), SubagentBlock, SDKAssistantMessage — 130 passed.
- No remaining
RunningBorderreferences anywhere in the repo;RunningBorder.tsxfully deleted; no test imported or asserted on it. - Shimmer loop math verified: with
background-size:200%, the band center sits atW·(1 − P/100); at P=130% → −0.30W (fully off-left) and at P=−30% → +1.30W (fully off-right). Off-screen clearance (0.30W) exceeds the band half-width (0.10W), so the infinite-loop seam is invisible. Sweep is left→right, 1.8s linear. Correct. prefers-reduced-motionfully disables it (animation:none+display:none).pointer-events:none+aria-hidden="true"on all three usages.- Containment: all three card roots are always
overflow-hiddenand gainrelativeexactly whenisRunning. ConfirmModal(ToolResultCard) renders viaModal→<Portal into="body">+fixed inset-0 z-50, so the in-card shimmer cannot occlude it.isRunningplumbing is byte-for-byte identical to before (doc-comment changes only); parent containers don't depend on the old wrapper structure.
Finding
P2 — packages/web/src/components/sdk/SDKAssistantMessage.tsx:261-264 (stale comment, in task scope)
The inline comment still describes the deleted mechanism verbatim:
// When isRunning, ALL blocks in this message receive the animated arc so every block type is visible for debugging/verification. Each component applies the arc via a wrapper div (not directly on its overflow:hidden root) so the inset:-2px extension isn't clipped.
This is now wrong on three counts: there is no "animated arc" (it's a body shimmer), no "wrapper div" (the shimmer is a direct child of the overflow-hidden root), and no "inset:-2px extension". The task explicitly scoped updating arc/RunningBorder doc references in this file — lines 62-66 and 359-366 were updated, but this paragraph was missed. Suggest rewriting it to describe the in-card .running-shimmer overlay (contained by the card's overflow-hidden). Doc-only; no behavioral impact.
Non-blocking notes
- New
@keyframes runningShimmerrather than reusing the existingshimmer(skeleton) keyframe: the existing one is px-locked to dark skeleton colors and isn't reusable for a white percentage sweep, so a separate keyframe is the right call. - Task text said the shimmer should sit "below interactive children"; it's rendered as the last child (paints above content) but
pointer-events:nonefully preserves interaction, satisfying the intent. No change needed.
The inline comment at SDKAssistantMessage.tsx:261-264 still described the deleted SVG-arc mechanism (animated arc, wrapper div, inset:-2px extension). Rewrite it to describe the in-card .running-shimmer overlay, matching the updates already made elsewhere in the file.
lsm
left a comment
There was a problem hiding this comment.
🤖 Review by glm-5.1 (GLM)
Model: glm-5.1 | Client: NeoKai | Provider: GLM
Recommendation: APPROVE — zero findings. The P2 doc-comment from the prior round is fixed; all checks and tests pass.
Round-2 verification (fresh, not relying on prior conclusions):
- Fix commit
8bb46f3feis surgical: onlySDKAssistantMessage.tsx(3+/3−). The stale inline comment now correctly describes the in-card.running-shimmeroverlay contained by the card'soverflow-hidden. - Independent residual-vocabulary grep across
packages/web/src(animated arc / border-light / animateMotion / mpath / radial-gradient mask / inset:-2px / wrapper-div arc / RunningBorder) → only false positives (router*FromPathhelpers, unrelated "wrapper div" comments). No real leftovers. bun run check(root: oxlint +tsc --build --noEmit+ knip + session-guards + space-task-handler-tests + db-schema-parity + test-quality) — exit 0.- ThinkingBlock / SubagentBlock / SDKAssistantMessage tests — 130 passed.
- PR OPEN, MERGEABLE, head == fix commit (
8bb46f3fe), zero unresolved review threads.
The refactor itself (verified in round 1): correct CSS loop-seam math, prefers-reduced-motion, pointer-events:none + aria-hidden, overflow-hidden/relative containment on all three blocks, and ConfirmModal portal isolation. No blocking issues.
(Self-review fallback: GitHub rejects self-APPROVE, so posted as COMMENT with an explicit APPROVE recommendation.)
Replaces the heavy SVG "chasing glow" running indicator with a lightweight pure-CSS shimmer sweep across the card body (the "option 4" mockup the user approved). No border arc, no SVG, no ResizeObserver.
Changes
Visual — while a block is running, a faint white left→right gradient sweeps across the card surface (~1.8s loop). Motion-only signal per the user's decision (no static accent pairing).
New CSS (
packages/web/src/styles.css):@keyframes runningShimmer+.running-shimmeroverlay —position:absolute; inset:0; pointer-events:none, white gradient,background-size:200%, left→right sweep.background-size:200%, animatingbackground-position130% → -30%sweeps the band fully off the left edge, across the card, and fully off the right edge.prefers-reduced-motionhides it entirely.Blocks (keep existing
isRunninggating intact, only swap the visual):ThinkingBlock,SubagentBlock,ToolResultCard— drop the<RunningBorder>wrapper; render the overlay as a card child while running and addrelativeto the card when running (overflow-hiddenclips it to the rounded surface).Cleanup:
packages/web/src/components/sdk/RunningBorder.tsxand its 3 imports.RunningBorderto describe the shimmer (SDKMessageRenderer,SDKAssistantMessage,SubagentBlock,ThinkingBlock,ToolResultCard,tool-types,styles.css).Tests:
svgqueries were for icons).ThinkingBlocktest:.running-shimmeris present while running, absent when not.Verification