From 9106d09248f4527a58cc491e3be968300de529ff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 27 Sep 2026 08:57:30 +1000 Subject: [PATCH 1/2] feat(web): port thread details customization to responsive card --- apps/web/src/components/ChatView.tsx | 16 + .../chat/ThreadAutomationsPanel.tsx | 7 +- .../src/components/chat/ThreadDetailsCard.tsx | 26 +- .../chat/ThreadDetailsCustomize.tsx | 367 ++++++++++++++++++ .../chat/ThreadDetailsPanel.test.tsx | 211 ++++++++-- .../components/chat/ThreadDetailsPanel.tsx | 322 +++++++++++---- .../chat/ThreadRelationshipsControl.tsx | 6 +- .../chat/threadDetailsCustomization.test.ts | 146 +++++++ .../chat/threadDetailsCustomization.ts | 149 +++++++ apps/web/src/components/ui/popover.tsx | 2 +- packages/contracts/src/keybindings.ts | 1 + packages/contracts/src/settings.test.ts | 36 ++ packages/contracts/src/settings.ts | 30 ++ 13 files changed, 1195 insertions(+), 124 deletions(-) create mode 100644 apps/web/src/components/chat/ThreadDetailsCustomize.tsx create mode 100644 apps/web/src/components/chat/threadDetailsCustomization.test.ts create mode 100644 apps/web/src/components/chat/threadDetailsCustomization.ts diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 02563f3594bd5..ab5108a49fe8c 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -5539,6 +5539,11 @@ export default function ChatView(props: ChatViewProps) { } useRightPanelStore.getState().toggleVisibility(activeThreadRef); }, [activeThreadRef, closePreviewPanel, rightPanelOpen]); + const [threadPanelCustomizeRequested, setThreadPanelCustomizeRequested] = useState(false); + const handleThreadPanelCustomizeRequest = useCallback( + () => setThreadPanelCustomizeRequested(false), + [], + ); const toggleThreadPanel = useCallback(() => { if (!activeThreadRef) return; useRightPanelStore.getState().toggleThreadPanel(activeThreadRef, threadPanelPresentation); @@ -7357,6 +7362,14 @@ export default function ChatView(props: ChatViewProps) { return; } + if (command === "threadPanel.customize") { + event.preventDefault(); + event.stopPropagation(); + if (!threadPanelOpen) toggleThreadPanel(); + setThreadPanelCustomizeRequested(true); + return; + } + if (command === "threadPanel.toggle") { event.preventDefault(); event.stopPropagation(); @@ -7541,6 +7554,7 @@ export default function ChatView(props: ChatViewProps) { getShortcutContext, toggleRightPanel, toggleThreadPanel, + threadPanelOpen, toggleTerminalVisibility, composerRef, ]); @@ -10298,6 +10312,8 @@ export default function ChatView(props: ChatViewProps) { onAddProjectScript: saveProjectScript, onUpdateProjectScript: updateProjectScript, onDeleteProjectScript: deleteProjectScript, + customizeRequested: threadPanelCustomizeRequested, + onCustomizeRequestHandled: handleThreadPanelCustomizeRequest, }; const panelToggleControlProps = { terminalAvailable: activeProject !== null, diff --git a/apps/web/src/components/chat/ThreadAutomationsPanel.tsx b/apps/web/src/components/chat/ThreadAutomationsPanel.tsx index b53972f0116e4..2fab1be65e7f5 100644 --- a/apps/web/src/components/chat/ThreadAutomationsPanel.tsx +++ b/apps/web/src/components/chat/ThreadAutomationsPanel.tsx @@ -37,6 +37,7 @@ const STATUS_DOT_CLASS: Record = { * Renders nothing when the thread has no bound automations. */ export function ThreadAutomationsPanel(props: { + readonly alwaysVisible?: boolean; readonly environmentId: EnvironmentId; readonly threadId: ThreadId; }) { @@ -58,7 +59,7 @@ export function ThreadAutomationsPanel(props: { // A load error must not look like "no automations" — this thread may have // tasks whose controls would silently vanish. Only hide the section when we // positively know there is nothing bound to it. - if (tasksQuery.error === null && boundTasks.length === 0) return null; + if (tasksQuery.error === null && boundTasks.length === 0 && !props.alwaysVisible) return null; const reportFailure = (title: string, error: unknown) => { toastManager.add( @@ -131,6 +132,10 @@ export function ThreadAutomationsPanel(props: {

Could not load automations: {tasksQuery.error}

+ ) : boundTasks.length === 0 ? ( +

+ {tasksQuery.data === null ? "Loading automations…" : "No automations."} +

) : null}