From 474c4138ac751f48b5be354f6ec0b2b42a89fe4d Mon Sep 17 00:00:00 2001 From: scotttong Date: Wed, 29 Jul 2026 11:49:14 -0700 Subject: [PATCH] =?UTF-8?q?feat(ui):=20task-chat=20redesign=20phase=202=20?= =?UTF-8?q?=E2=80=94=20v5=E2=80=93v7=20reconciliation=20+=20live-thread=20?= =?UTF-8?q?completeness?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reconcile the baseline with the accepted v5–v7 prototype decisions and finish the live-thread work items (, plan §5), all behind enableTaskChatRedesign: - Composer: v7 comp-bar (attach + far left, rectangle status-chip mode trigger via --tc-mode-* hues incl. ask-blue #3b82f6, assignee combobox left of send, all controls 32px, no shortcut hints), per-message mode with ⇧⇥ cycling, attachments via button/paste/drag-drop, reassign-on-send with implicit reopen. - Scroll pill: stock shadcn MessageScrollerButton (32px round, arrow-only) with tokenized entry/exit motion and easing-aware re-follow (smooth glide cannot unpin the follow state; wheel/touch cancels). - Turn fold: run activity grouped into TaskChatTurn — live turns stream expanded, settling folds to a one-line '✓ Worked · 38s · 3 tools · +34 −3' summary (--motion-turn-fold 380ms, instant for settled history, reduced-motion honored), settled turns interleave before their run's reply comment. - Bubbles: agent header gains the textless brand-gradient capsule avatar + name · mode chip (deterministic agent→gradient hash). - Properties pane: tab label Plans→Plan; drag-resizable (clamp ≥260px, dbl-click reset 322px, width remembered) + maximizable (320ms glide, spacer holds flex slot, 840px content cap) — flag-off DOM untouched. - Motion: new tokens (turn-fold, scroll-pill enter/exit + easings, pane-glide) in index.css :root + reduced-motion zeroing + tweak-panel catalog entries. Verified: workspace tsc clean; check-task-chat-motion + token gates clean; 53 task-chat/PropertiesPanel/gate tests, 29 experimental-settings tests and 21 server instance-settings tests pass. Co-Authored-By: Claude Fable 5 --- scripts/check-task-chat-motion.mjs | 1 + ui/src/components/PropertiesPanel.tsx | 28 +- ui/src/components/TaskChatThread.tsx | 170 +++++- .../issue-properties/IssueProperties.tsx | 8 +- .../components/task-chat/TaskChatBubble.tsx | 24 +- .../task-chat/TaskChatComposer.test.tsx | 498 ++---------------- .../components/task-chat/TaskChatComposer.tsx | 377 +++++++++++-- .../task-chat/TaskChatThreadView.tsx | 24 +- .../task-chat/TaskChatTurn.test.tsx | 164 +----- ui/src/components/task-chat/TaskChatTurn.tsx | 134 ++--- .../task-chat/TaskMessageScroller.tsx | 117 +++- ui/src/components/task-chat/motion-tokens.ts | 6 + .../components/task-chat/task-chat-adapter.ts | 13 + .../task-chat/task-chat-fixtures.ts | 17 +- .../components/task-chat/task-chat-model.ts | 46 +- .../task-chat/transcript-adapter.ts | 55 ++ ui/src/index.css | 53 ++ 17 files changed, 889 insertions(+), 846 deletions(-) diff --git a/scripts/check-task-chat-motion.mjs b/scripts/check-task-chat-motion.mjs index a885de07c10..4cc7898b211 100644 --- a/scripts/check-task-chat-motion.mjs +++ b/scripts/check-task-chat-motion.mjs @@ -27,6 +27,7 @@ const repoRoot = join(dirname(fileURLToPath(import.meta.url)), ".."); const SCAN_DIRS = ["ui/src/components/task-chat"]; const SCAN_FILES = [ "ui/src/components/TaskChatThread.tsx", + "ui/src/components/PropertiesPanel.tsx", "ui/src/components/TaskChatRedesignGate.tsx", "ui/src/pages/TaskChatLab.tsx", "ui/src/components/issue-properties/IssuePropertiesPlansTab.tsx", diff --git a/ui/src/components/PropertiesPanel.tsx b/ui/src/components/PropertiesPanel.tsx index 6cad68da0ef..bccfa40691a 100644 --- a/ui/src/components/PropertiesPanel.tsx +++ b/ui/src/components/PropertiesPanel.tsx @@ -47,19 +47,6 @@ export function PropertiesPanel() { * variant. Everything below renders only when the flag is ON. * ------------------------------------------------------------------------- */ -/** - * Portal target in the redesigned pane's header bar: hosted content (the - * Properties | Plan | Artifacts tab strip) renders here, left of the window - * controls. See IssueProperties' flag-ON shell. - */ -export const PROPERTIES_PANE_HEADER_SLOT_ID = "properties-pane-header-slot"; -/** - * Portal target pinned below the pane's scroll area: hosted content (the plan - * confirmation action bar) renders here so it stays visible while the pane - * body scrolls. - */ -export const PROPERTIES_PANE_FOOTER_SLOT_ID = "properties-pane-footer-slot"; - const WIDTH_STORAGE_KEY = "taskChatRedesign.propertiesPaneWidth"; const DEFAULT_PANE_WIDTH = 322; const MIN_PANE_WIDTH = 260; @@ -353,17 +340,9 @@ function ResizablePropertiesPanel({ className={cn("flex-1 flex flex-col min-h-0", isFixed && "w-full")} style={isFixed ? undefined : { width, minWidth: width }} > - {/* The slot hosts whatever IssueProperties portals in — the tab strip - when Plan/Artifacts have content, else a plain "Properties" title; - window controls sit right. Vertical padding lives on the controls - cluster, not the bar, so the tab strip can stretch to the border - and its active underline hugs the header's bottom line. */} -
-
-
+
+ Properties +