summaryrefslogtreecommitdiffhomepage
path: root/src/features/tabs/tabs.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-10 11:40:16 +0900
committerAdam Malczewski <[email protected]>2026-06-10 11:40:16 +0900
commit7b345f132763fa6405ae858b74e46229629c19d9 (patch)
tree4600200e5a92eccbe880f46b3760cf0b1217737d /src/features/tabs/tabs.ts
parent89ca80bac1e143a4ec5ba6e2e1d4998acce2553c (diff)
downloaddispatch-web-7b345f132763fa6405ae858b74e46229629c19d9.tar.gz
dispatch-web-7b345f132763fa6405ae858b74e46229629c19d9.zip
feat(tabs,app): tab id handles, fixed-width tabs-lift, slim shell + full-height sidebar
Tabs: - short-handle ID badge per tab (shortest unique conversationId prefix, min 4) - fixed-width (w-48) tabs with tabs-lift folder borders Shell (composition root): - drop the Dispatch title bar; tabs sit at the very top with a 5px gap - big faded "Dispatch" watermark centered on an empty chat - collapsible right sidebar (empty shell) spanning full window height: a permanently right-pinned hamburger in the tab row toggles it; in-flow push that shrinks the whole left column (tabs included) at >=lg, overlay + backdrop below lg; open-by-default on wide / closed on narrow - main is overflow-hidden with a min-w-0 shrink chain; app.css pins html/body/#app height + body overflow hidden so the page never overflows
Diffstat (limited to 'src/features/tabs/tabs.ts')
-rw-r--r--src/features/tabs/tabs.ts19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/features/tabs/tabs.ts b/src/features/tabs/tabs.ts
index a4db6f3..61ae58e 100644
--- a/src/features/tabs/tabs.ts
+++ b/src/features/tabs/tabs.ts
@@ -92,3 +92,22 @@ export function deriveTitle(message: string, max: number = DEFAULT_MAX_TITLE_LEN
if (trimmed.length <= max) return trimmed;
return `${trimmed.slice(0, max)}\u2026`;
}
+
+/** Minimum length of a tab handle (git-style short id). */
+export const MIN_HANDLE_LENGTH = 4;
+
+/**
+ * The short "handle" shown on a tab: the shortest prefix of `conversationId`
+ * (at least `MIN_HANDLE_LENGTH` chars) that is unique among all open tabs — a
+ * git-style short id. Grows by a char only when another open tab shares the
+ * prefix, and shrinks back when that sibling closes. Pure: the id + every open
+ * id in, the handle string out. (`allIds` may include `conversationId` itself.)
+ */
+export function shortHandle(conversationId: string, allIds: readonly string[]): string {
+ const others = allIds.filter((id) => id !== conversationId);
+ for (let len = MIN_HANDLE_LENGTH; len < conversationId.length; len++) {
+ const candidate = conversationId.slice(0, len);
+ if (!others.some((id) => id.startsWith(candidate))) return candidate;
+ }
+ return conversationId;
+}