fix(mobile): PulseDot uses brand colour, not success — running ≠ completed

The agent "is working" pulse dot (shown both in the issue Stack header
ambient badge and in the in-card AgentActivityRow "Working" row) was
backgroundColor #22c55e — that's the success/completed token. Reading
green here meant "task complete", which is the opposite of what the
animation represents.

Switch to THEME[scheme].brand (hsl(225 71% 58%)), matching:
  - mobile RunRow status text: STATUS_CLASS.running = "text-brand"
  - web agent-live-card.tsx:327: <Loader2 text-info animate-spin />
  - Apple HIG / shadcn semantic colour convention:
      green = success, blue/brand = in-progress, red = destructive

One-line fix in pulse-dot.tsx; both call sites (AgentHeaderBadge top-right,
AgentActivityRow under the title) flip from green to brand blue
together. Docstring updated to spell out the rule for future readers:
DO NOT use success here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Naiyuan Qing
2026-05-19 16:12:41 +08:00
parent 9aaff146b5
commit e9b2e98d15

View File

@@ -1,15 +1,23 @@
/**
* Slow green pulse — opacity oscillation on the UI thread via Reanimated's
* `withRepeat`. 2-second cycle (1s in + 1s out). Same animation library as
* comment-card.tsx, no new primitive.
* Slow brand-coloured pulse — opacity oscillation on the UI thread via
* Reanimated's `withRepeat`. 2-second cycle (1s in + 1s out). Same
* animation library as comment-card.tsx, no new primitive.
*
* Used by:
* - apps/mobile/components/issue/agent-activity-row.tsx (in-card "Working" row)
* - apps/mobile/components/issue/agent-header-badge.tsx (Stack header ambient badge)
*
* Color is `#22c55e // success` (mobile tailwind.config.js:50). Inline hex
* is the project's convention for animated backgroundColor values that
* can't go through NativeWind className (see Reanimated style merging).
* Colour is the workspace `brand` token (mobile global.css:45 `--brand`),
* matching the "in-progress / live" semantic used everywhere else:
* `RunRow` paints dispatched/running state with `text-brand`, and web's
* `agent-live-card.tsx` uses `text-info` (also blue) for the same
* Loader2 spinner. **DO NOT** use the `success` token here — green means
* "completed", not "running" (Apple HIG / shadcn convention).
*
* Inline backgroundColor (rather than NativeWind className) is required
* because Reanimated's animated style merging doesn't compose cleanly
* with NativeWind class-derived styles; sibling `comment-card.tsx`
* follows the same pattern.
*/
import { useEffect } from "react";
import Animated, {
@@ -18,6 +26,8 @@ import Animated, {
withRepeat,
withTiming,
} from "react-native-reanimated";
import { useColorScheme } from "@/lib/use-color-scheme";
import { THEME } from "@/lib/theme";
interface Props {
/** Diameter in pt. Default 8 (matches the in-card row). */
@@ -25,6 +35,7 @@ interface Props {
}
export function PulseDot({ size = 8 }: Props) {
const { colorScheme } = useColorScheme();
const opacity = useSharedValue(0.3);
useEffect(() => {
opacity.value = withRepeat(
@@ -43,7 +54,7 @@ export function PulseDot({ size = 8 }: Props) {
width: size,
height: size,
borderRadius: size / 2,
backgroundColor: "#22c55e", // success
backgroundColor: THEME[colorScheme].brand,
},
style,
]}