summaryrefslogtreecommitdiffhomepage
path: root/src/features/tabs/ui/TabGroupBox.svelte
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-10-15 14:38:50 +0900
committerAdam Malczewski <[email protected]>2026-10-15 14:38:50 +0900
commitc4c1d76fec972e5d902a669f0cb1953eaa528f16 (patch)
treed5d85b8500157dd690e13954216a61a6aac64a8a /src/features/tabs/ui/TabGroupBox.svelte
parent3d3c28b10de06aae7e2ad474e8931a3fdd88b41c (diff)
downloaddispatch-web-c4c1d76fec972e5d902a669f0cb1953eaa528f16.tar.gz
dispatch-web-c4c1d76fec972e5d902a669f0cb1953eaa528f16.zip
feat(tabs): 2-column tab grid with nestable subagent groups + tab menu (add/remove from group)
Diffstat (limited to 'src/features/tabs/ui/TabGroupBox.svelte')
-rw-r--r--src/features/tabs/ui/TabGroupBox.svelte53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/features/tabs/ui/TabGroupBox.svelte b/src/features/tabs/ui/TabGroupBox.svelte
new file mode 100644
index 0000000..5cbfb27
--- /dev/null
+++ b/src/features/tabs/ui/TabGroupBox.svelte
@@ -0,0 +1,53 @@
+<script lang="ts">
+ import type { Snippet } from "svelte";
+ import type { TabGroupNode } from "../tab-groups";
+ import { groupBleedPx } from "../tab-groups";
+ import type { Tab } from "../tabs";
+ import TabGroupBox from "./TabGroupBox.svelte";
+
+ /**
+ * A subagent group: a darker box spanning both grid columns that wraps the
+ * group parent's (double-width) card + its subagents' cards. Recursive —
+ * a subagent with its own subagents renders a nested box. The box BLEEDS
+ * outward (negative margin + equal padding, `groupBleedPx`) so the cards
+ * inside stay on the same two columns as top-level cards: every card keeps
+ * identical dimensions at every depth. The translucent black background
+ * compounds, so each nesting level reads darker than the one around it.
+ */
+ let {
+ node,
+ level,
+ maxDepth,
+ card,
+ }: {
+ node: TabGroupNode;
+ /** Nesting level of THIS box (1 = outermost). */
+ level: number;
+ maxDepth: number;
+ /** Renders one card: (tab, wide, subagentCount). */
+ card: Snippet<[Tab, boolean, number]>;
+ } = $props();
+
+ const bleed = $derived(groupBleedPx(level, maxDepth));
+</script>
+
+<div
+ class="col-span-2 rounded-lg border border-black/50 bg-black/40 py-1.5 shadow-inner"
+ style:margin-inline="-{bleed}px"
+ style:padding-inline="{bleed}px"
+ role="group"
+ aria-label={`Subagents of ${node.tab.title}`}
+ data-tab-group={node.tab.conversationId}
+ data-level={level}
+>
+ <div class="grid grid-flow-row-dense grid-cols-2 gap-1.5">
+ {@render card(node.tab, true, node.children.length)}
+ {#each node.children as child (child.tab.conversationId)}
+ {#if child.children.length > 0}
+ <TabGroupBox node={child} level={level + 1} {maxDepth} {card} />
+ {:else}
+ {@render card(child.tab, false, 0)}
+ {/if}
+ {/each}
+ </div>
+</div>