From e703f7af2adc181eacb3fecedacada5eb71d2872 Mon Sep 17 00:00:00 2001 From: Haley Park Date: Wed, 12 Aug 2026 14:38:50 -0700 Subject: [PATCH] style(desktop): refine session chat layout (#13205) * style(ui): refine chat message surfaces and actions * feat(desktop): refine session transcript layout * style(desktop): refine conversation composer * style(ui): format chat theme changes --- .../webview/components/ui/combobox.tsx | 4 +- .../webview/components/ui/dropdown-menu.tsx | 14 +- .../components/views/chat/chat-input-bar.tsx | 63 ++-- .../views/chat/chat-messages.test.tsx | 22 +- .../components/views/chat/chat-messages.tsx | 324 +++++++++--------- .../views/chat/messages/message-bubble.tsx | 17 +- .../components/views/chat/session-content.tsx | 21 ++ .../components/views/chat/welcome-chat.tsx | 5 +- .../ui/components/agent-chat/agent-chat.css | 71 ++-- .../ui/components/agent-chat/index.tsx | 13 +- .../ui/stories/agent-chat.stories.tsx | 109 +++++- sdk/packages/ui/theme/scoped-tokens.css | 2 + sdk/packages/ui/theme/tokens.css | 2 + 13 files changed, 417 insertions(+), 250 deletions(-) create mode 100644 apps/examples/desktop-app/webview/components/views/chat/session-content.tsx diff --git a/apps/examples/desktop-app/webview/components/ui/combobox.tsx b/apps/examples/desktop-app/webview/components/ui/combobox.tsx index adfa7fa8d3..8254958ce1 100644 --- a/apps/examples/desktop-app/webview/components/ui/combobox.tsx +++ b/apps/examples/desktop-app/webview/components/ui/combobox.tsx @@ -113,7 +113,7 @@ function ComboboxContent({ > (null); const promptInputRef = useRef(null); + const [promptInputFocused, setPromptInputFocused] = useState(false); const [cursorIndex, setCursorIndex] = useState(() => promptInput.length); // Mention/slash detection is derived synchronously from the input + // cursor. Deriving (rather than syncing through effects) keeps a keystroke @@ -429,7 +429,10 @@ function ChatInputBarImpl({ : !hasExplicitReasoningSelection && modelSupportsReasoning === false ? "None" : (EFFORT_LEVELS[effortIndex]?.label ?? "Reasoning"); - const promptInputRows = PROMPT_INPUT_ROWS; + const promptInputRows = + variant === "welcome" || promptInputFocused + ? PROMPT_INPUT_EXPANDED_ROWS + : PROMPT_INPUT_COLLAPSED_ROWS; const handleEffortChange = useCallback( (value: string) => { if (modelSupportsReasoning !== true) { @@ -656,12 +659,17 @@ function ChatInputBarImpl({ className={cn( "bg-card", variant === "welcome" - ? "overflow-visible rounded-xl border border-border/90 bg-card/90 shadow-[0_24px_80px_-56px_color-mix(in_oklab,var(--primary)_72%,transparent)] backdrop-blur-md" - : "border-t border-border bg-card/95 backdrop-blur-sm", + ? "overflow-visible rounded-xl border border-border/90 bg-surface-1/40 shadow-[0_24px_80px_-56px_color-mix(in_oklab,var(--primary)_72%,transparent)] backdrop-blur-md" + : "overflow-visible rounded-xl border border-border bg-surface-2 backdrop-blur-sm focus-within:border-primary/50 focus-within:ring-1 focus-within:ring-primary/20", )} > {/* Input area */} -
+
)} + {/* biome-ignore lint/a11y/noStaticElementInteractions: Empty composer space forwards pointer focus to the nested textarea; keyboard users focus the textarea directly. */}
{ + const target = event.target; + if ( + target instanceof HTMLElement && + target.closest("button, input, textarea") + ) { + return; + } + event.preventDefault(); + promptInputRef.current?.focus(); + }} >