Problem
While a session turn is executing, the sidebar row does animate today — the shared blue (accent) StatusDot pulses with isPulsing: true. But the pulse is too weak to read as "in progress":
- The animation is a plain opacity breathe — keyframes
opacity: 1 → 0.5 → 1, ease-in-out, animation-duration: 2s, infinite (@astryxdesign/core astryx.css).
- It runs on an 8px dot, so a 2-second 50%-opacity fade is easy to miss — especially in peripheral vision, which is where the sidebar is when the user is watching the conversation.
- The result is that "running" and "settled" look like the same blue dot, so the user cannot tell them apart at a glance.
Worse, when motion is reduced there is no cue at all: prefers-reduced-motion sets animation-name: none on the dot, leaving the running row visually identical to a finished one.
Where this lives:
packages/ui/src/session-history-list.tsx — sessionRowSignals() pushes { variant: dotForStatus('active'), isPulsing: true, ... } when the session is responding, and the row draws exactly one StatusDot.
packages/ui/src/status-vocabulary.ts — active → 'accent' (blue).
packages/ui/src/session-status-presentation.ts — running → 'active'.
Desired outcome
"Running" should be unmistakable at a glance — e.g. a spinner / clearly animated working mark on the running row, distinct from the resting accent dot that is shown once the turn has settled. And because the pulse is the only cue today, there should also be a non-motion fallback (an icon or label), so a running session is still recognisable with reduced motion enabled.
Alternatives or workarounds
Today the workaround is to hover the row or open the session to check whether it is still working. Making the existing pulse stronger/brighter is possible, but a spinner (or an icon + label) is the more conventional and unambiguous affordance, and it also covers the reduced-motion case. A Spinner component already exists and is used in packages/ui/src/chat-turn.tsx (compaction / "working" cues).
Additional context
@astryxdesign/core StatusDot is a fixed 8px dot, supports isPulsing but has no spinner variant, so the stronger "working" affordance has to come from the surface rather than the dot itself.
Problem
While a session turn is executing, the sidebar row does animate today — the shared blue (
accent)StatusDotpulses withisPulsing: true. But the pulse is too weak to read as "in progress":opacity: 1 → 0.5 → 1,ease-in-out,animation-duration: 2s,infinite(@astryxdesign/coreastryx.css).Worse, when motion is reduced there is no cue at all:
prefers-reduced-motionsetsanimation-name: noneon the dot, leaving the running row visually identical to a finished one.Where this lives:
packages/ui/src/session-history-list.tsx—sessionRowSignals()pushes{ variant: dotForStatus('active'), isPulsing: true, ... }when the session is responding, and the row draws exactly oneStatusDot.packages/ui/src/status-vocabulary.ts—active → 'accent'(blue).packages/ui/src/session-status-presentation.ts—running → 'active'.Desired outcome
"Running" should be unmistakable at a glance — e.g. a spinner / clearly animated working mark on the running row, distinct from the resting accent dot that is shown once the turn has settled. And because the pulse is the only cue today, there should also be a non-motion fallback (an icon or label), so a running session is still recognisable with reduced motion enabled.
Alternatives or workarounds
Today the workaround is to hover the row or open the session to check whether it is still working. Making the existing pulse stronger/brighter is possible, but a spinner (or an icon + label) is the more conventional and unambiguous affordance, and it also covers the reduced-motion case. A
Spinnercomponent already exists and is used inpackages/ui/src/chat-turn.tsx(compaction / "working" cues).Additional context
@astryxdesign/coreStatusDotis a fixed 8px dot, supportsisPulsingbut has no spinner variant, so the stronger "working" affordance has to come from the surface rather than the dot itself.