From a4507a9cb0b738440fffa6dc066983b34452c515 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Thu, 12 Feb 2026 11:22:10 +0000 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=A4=96=20feat:=20add=20animated=20SVG?= =?UTF-8?q?=20thinking=20icon=20with=20synced=20shimmer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Render an animated SVG to the left of the streaming "Thinking..." shimmer label in ReasoningMessage. - Keep the icon and text shimmer in lockstep by sharing the same shimmer duration and sweep keyframes. - Add shimmer-surface overlay styles for non-text shimmer surfaces and keep existing non-streaming lightbulb behavior. --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `.04`_ --- .../assets/animations/thinking-dots.svg | 1 + .../components/Messages/ReasoningMessage.tsx | 31 +++++++++++++++++-- src/browser/styles/globals.css | 27 ++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/browser/assets/animations/thinking-dots.svg diff --git a/src/browser/assets/animations/thinking-dots.svg b/src/browser/assets/animations/thinking-dots.svg new file mode 100644 index 0000000000..e97ba3d7b2 --- /dev/null +++ b/src/browser/assets/animations/thinking-dots.svg @@ -0,0 +1 @@ + diff --git a/src/browser/components/Messages/ReasoningMessage.tsx b/src/browser/components/Messages/ReasoningMessage.tsx index 01eaa8b101..ac344e53fc 100644 --- a/src/browser/components/Messages/ReasoningMessage.tsx +++ b/src/browser/components/Messages/ReasoningMessage.tsx @@ -5,6 +5,7 @@ import { TypewriterMarkdown } from "./TypewriterMarkdown"; import { normalizeReasoningMarkdown } from "./MarkdownStyles"; import { cn } from "@/common/lib/utils"; import { Shimmer } from "../ai-elements/shimmer"; +import ThinkingDots from "@/browser/assets/animations/thinking-dots.svg?react"; import { Lightbulb } from "lucide-react"; interface ReasoningMessageProps { @@ -13,6 +14,13 @@ interface ReasoningMessageProps { } const REASONING_FONT_CLASSES = "font-primary text-[12px] leading-[18px]"; +const THINKING_SHIMMER_DURATION_SECONDS = 2; +type ThinkingShimmerStyle = React.CSSProperties & + Record<"--shimmer-duration" | "--shimmer-color", string>; +const THINKING_SHIMMER_STYLE: ThinkingShimmerStyle = { + "--shimmer-duration": `${THINKING_SHIMMER_DURATION_SECONDS}s`, + "--shimmer-color": "var(--color-thinking-mode)", +}; export const ReasoningMessage: React.FC = ({ message, className }) => { const [isExpanded, setIsExpanded] = useState(message.isStreaming); @@ -105,11 +113,30 @@ export const ReasoningMessage: React.FC = ({ message, cla )} > - + {isStreaming ? ( + + {/* Keep the icon shimmer in lockstep with the text shimmer while streaming. */} + + + ) : ( + + )}
{isStreaming ? ( - Thinking... + + Thinking... + ) : hasContent ? ( Date: Thu, 12 Feb 2026 15:10:54 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=A4=96=20fix:=20move=20streaming=20SV?= =?UTF-8?q?G=20indicator=20to=20streaming=20status=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Revert the animated SVG from reasoning message rows. - Add a reusable StreamingActivityIcon and use it at the start of streaming status labels. - Apply the icon + shimmer treatment to StreamingBarrier and WorkspaceStatusIndicator streaming states. - Keep the shared shimmer overlay utility for non-text surfaces. --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `.04`_ --- .../Messages/ChatBarrier/BaseBarrier.tsx | 7 +++- .../Messages/ChatBarrier/StreamingBarrier.tsx | 1 + .../ChatBarrier/StreamingBarrierView.tsx | 31 +++++++++++++++- .../components/Messages/ReasoningMessage.tsx | 31 +--------------- .../components/WorkspaceStatusIndicator.tsx | 37 +++++++++++++++++-- .../icons/StreamingActivityIcon.tsx | 32 ++++++++++++++++ src/browser/styles/globals.css | 2 +- 7 files changed, 104 insertions(+), 37 deletions(-) create mode 100644 src/browser/components/icons/StreamingActivityIcon.tsx diff --git a/src/browser/components/Messages/ChatBarrier/BaseBarrier.tsx b/src/browser/components/Messages/ChatBarrier/BaseBarrier.tsx index becde41fd5..318cc60c9a 100644 --- a/src/browser/components/Messages/ChatBarrier/BaseBarrier.tsx +++ b/src/browser/components/Messages/ChatBarrier/BaseBarrier.tsx @@ -2,10 +2,11 @@ import React from "react"; import { cn } from "@/common/lib/utils"; interface BaseBarrierProps { - text: string; + text: React.ReactNode; color: string; animate?: boolean; className?: string; + leadingElement?: React.ReactNode; } export const BaseBarrier: React.FC = ({ @@ -13,6 +14,7 @@ export const BaseBarrier: React.FC = ({ color, animate = false, className, + leadingElement, }) => { return (
= ({ }} />
+ {leadingElement} {text}
= ({ workspaceId, tps={tps} cancelText={cancelText} className={className} + isStreamingPhase={phase === "streaming"} hintElement={ showCompactionHint ? (