From a4aa86e66dad93f40bce640545d8903f7e6bcb64 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Fri, 16 Oct 2026 15:25:40 +0900 Subject: feat(tabs): confirm dialog that cascades a tab close to its subagents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closing a tab whose visible subagent group is non-empty now asks ONE daisyUI modal (CloseSubagentsConfirm): 'Yes, close all N' closes the tab plus every transitive descendant tab (sub-sub-agents included, no further prompts), 'No, keep them open' closes only the tab, and Cancel/Escape/ backdrop closes nothing. Plain tabs close directly as before. - cascadeCloseIds (pure, tab-groups.ts): the tab + its transitive visible group descendants in tab order — one decision covers the whole subtree - TabList intercepts tab-close and opens the dialog only when the subtree has >1 tab; ids are snapshotted at open time - each closed conversation goes through the existing onClose port, so every close still POSTs /conversations/:id/close (backend doesn't cascade; it is idempotent) --- src/features/tabs/ui/CloseSubagentsConfirm.svelte | 57 +++++++++++++++++++++++ src/features/tabs/ui/TabList.svelte | 43 ++++++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/features/tabs/ui/CloseSubagentsConfirm.svelte (limited to 'src/features/tabs/ui') diff --git a/src/features/tabs/ui/CloseSubagentsConfirm.svelte b/src/features/tabs/ui/CloseSubagentsConfirm.svelte new file mode 100644 index 0000000..cbbec79 --- /dev/null +++ b/src/features/tabs/ui/CloseSubagentsConfirm.svelte @@ -0,0 +1,57 @@ + + + e.key === "Escape" && onDismiss()} /> + + diff --git a/src/features/tabs/ui/TabList.svelte b/src/features/tabs/ui/TabList.svelte index 06d5aa6..4b96e08 100644 --- a/src/features/tabs/ui/TabList.svelte +++ b/src/features/tabs/ui/TabList.svelte @@ -1,6 +1,7 @@ {#snippet card(tab: Tab, wide: boolean, subagentCount: number)} @@ -83,7 +105,7 @@ {wide} {subagentCount} {onSelect} - {onClose} + onClose={requestClose} {onRename} onMenu={openMenu} /> @@ -147,3 +169,22 @@ onDismiss={() => (menu = null)} /> {/if} + +{#if closeConfirm !== null} + {@const target = closeConfirm.tab} + {@const cascadeIds = [...closeConfirm.cascadeIds]} + {@const closeOwner = onClose} + { + closeOwner(target.conversationId); + closeConfirm = null; + }} + onCloseAll={() => { + for (const id of cascadeIds) closeOwner(id); + closeConfirm = null; + }} + onDismiss={() => (closeConfirm = null)} + /> +{/if} -- cgit v1.2.3