From 148cb807713baf31e36c8c6d1d1c3864cfe2e938 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Thu, 30 Jul 2026 04:47:28 -0500 Subject: [PATCH 1/3] feat(desktop): one shell for the transcript's inline widgets Clarify and the artifact card were the only two tool results that render as a panel, and neither looked like the other: clarify sat on a 2px radius over the chat backdrop's own color, so the card was invisible except for its hairline; the artifact card used a hardcoded 10px radius and no fill at all. Both now wear WIDGET_SHELL_CLASS -- one radius a rung above the composer, one fill, no border. --ui-widget-surface-background is the card token in light mode and a touch below it in dark, where a raw card fill sits above the chrome and reads as a lit panel. It derives from --ui-bg-editor so a skin's own card seed carries through. --- .../components/assistant-ui/artifact-card.tsx | 6 +- .../components/assistant-ui/clarify-tool.tsx | 66 +++++++++++-------- .../src/components/chat/widget-shell.ts | 12 ++++ apps/desktop/src/styles.css | 11 +++- 4 files changed, 64 insertions(+), 31 deletions(-) create mode 100644 apps/desktop/src/components/chat/widget-shell.ts diff --git a/apps/desktop/src/components/assistant-ui/artifact-card.tsx b/apps/desktop/src/components/assistant-ui/artifact-card.tsx index feb9b06c951..e7fb043f6d5 100644 --- a/apps/desktop/src/components/assistant-ui/artifact-card.tsx +++ b/apps/desktop/src/components/assistant-ui/artifact-card.tsx @@ -5,6 +5,7 @@ import { useEffect, useMemo } from 'react' import { useSessionView } from '@/app/chat/session-view' import { CodeCardIcon } from '@/components/chat/code-card' +import { WIDGET_SHELL_CLASS } from '@/components/chat/widget-shell' import { useI18n } from '@/i18n' import type { ArtifactDetection } from '@/lib/artifact-detect' import { codiconForLanguage } from '@/lib/markdown-code' @@ -96,8 +97,9 @@ export function ArtifactCard({ code, detection, streaming = false }: ArtifactCar return ( - - - - +
+ + +
+ ) } diff --git a/apps/desktop/src/components/chat/widget-shell.ts b/apps/desktop/src/components/chat/widget-shell.ts new file mode 100644 index 00000000000..eea81bca583 --- /dev/null +++ b/apps/desktop/src/components/chat/widget-shell.ts @@ -0,0 +1,12 @@ +/** + * Inline transcript widgets — the few tool results that render as a panel the + * user reads or acts on (a clarify question, an artifact card) rather than as + * a scaffold line. + * + * They share one shell so they cannot drift apart. They used to each pick their + * own: clarify sat on a 2px radius over the chat backdrop's own color (a card + * you could only see by its hairline), the artifact card on a hardcoded 10px + * over nothing. One radius one rung above the composer, one mode-derived fill, + * no border — the surface reads as a surface on the fill alone. + */ +export const WIDGET_SHELL_CLASS = 'rounded-3xl bg-(--ui-widget-surface-background) px-3.5 py-3' diff --git a/apps/desktop/src/styles.css b/apps/desktop/src/styles.css index 4fea8ed294f..edea88a1713 100644 --- a/apps/desktop/src/styles.css +++ b/apps/desktop/src/styles.css @@ -327,6 +327,10 @@ --ui-sidebar-surface-background: var(--ui-bg-sidebar); --ui-chat-surface-background: var(--ui-bg-chrome); --ui-editor-surface-background: var(--ui-bg-chrome); + /* Inline chat widgets (clarify, artifact card) — the card fill in light + mode, nudged down in dark so a widget settles into the transcript + instead of glowing above it (see the `.dark` override). */ + --ui-widget-surface-background: var(--ui-bg-editor); --ui-chat-bubble-background: color-mix( in srgb, var(--theme-bubble-seed) var(--theme-mix-bubble), @@ -512,6 +516,11 @@ --ui-inline-code-background: color-mix(in srgb, #ffffff 7%, transparent); --ui-inline-code-foreground: color-mix(in srgb, #ffffff 88%, transparent); --ui-selection-background: color-mix(in srgb, #ffd24a 38%, transparent); + /* A dark card sits ABOVE the chrome (#161618 over #0d0d0e), so an inline + widget wearing the raw card fill reads as a lit panel. Take it down a + touch — still clearly a surface, no longer the brightest thing in the + transcript. Derived from the card so every skin follows its own seed. */ + --ui-widget-surface-background: color-mix(in srgb, var(--ui-bg-editor) 88%, #000); } * { @@ -1485,7 +1494,7 @@ text-* variant utilities. */ .btn-arc { } [data-slot='aui_assistant-message-content'] .aui-md .aui-md-table thead { - border-bottom-color: var(--dt-border) !important; + border-bottom-color: var(--ui-stroke-tertiary) !important; } /* Tool / thinking blocks are scaffolding around the model's reply, so we From 277a6f944a3143c28070326e0c920e9810556dd7 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Thu, 30 Jul 2026 04:47:39 -0500 Subject: [PATCH 2/3] fix(desktop): put the transcript's hairlines on one stroke token A markdown table's border came from border-border (--dt-border, the app-wide default) while the expanded tool block beside it used --ui-stroke-tertiary. In dark mode the default resolves fully opaque and the table glared next to everything around it. Every bordered surface in the thread -- tables, fences, blockquotes, callouts, media cards, attachments -- now uses --ui-stroke-tertiary, which DESIGN.md already names the in-panel hairline. That also retires the /45 /50 /55 /60 /70 opacity one-offs, five ad-hoc dilutions of one color, so retuning the hairline is a single edit. --dt-border keeps its 57 call sites outside the transcript. --- .../src/components/assistant-ui/directive-text.tsx | 4 ++-- .../src/components/assistant-ui/embeds/alert.tsx | 2 +- .../src/components/assistant-ui/markdown-text.tsx | 12 ++++++------ .../assistant-ui/thread/user-message-text.tsx | 2 +- .../desktop/src/components/chat/compact-markdown.tsx | 10 +++++----- .../src/components/chat/preview-attachment.tsx | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/desktop/src/components/assistant-ui/directive-text.tsx b/apps/desktop/src/components/assistant-ui/directive-text.tsx index 418f59eda71..3c6e4df2760 100644 --- a/apps/desktop/src/components/assistant-ui/directive-text.tsx +++ b/apps/desktop/src/components/assistant-ui/directive-text.tsx @@ -418,7 +418,7 @@ export function DirectiveContent({ text }: { text: string }) { {images.map((src, index) => ( = ({ id, label }) => { return (
diff --git a/apps/desktop/src/components/assistant-ui/markdown-text.tsx b/apps/desktop/src/components/assistant-ui/markdown-text.tsx index f6a35b57647..cad8f0d7407 100644 --- a/apps/desktop/src/components/assistant-ui/markdown-text.tsx +++ b/apps/desktop/src/components/assistant-ui/markdown-text.tsx @@ -197,7 +197,7 @@ function MediaAttachment({ path }: { path: string }) { if (kind === 'audio' && src) { return ( - + {name}