From 6bd8f4718b44d06d116d02d9538214c8450b1c8d Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Sat, 27 Jun 2026 16:08:10 +0900 Subject: feat(sidebar-tabs): add active tab title to top bar (New Tab for unstarted chats) --- src/app/App.svelte | 27 ++++++++++++++++++++++++--- src/app/App.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/app/App.svelte b/src/app/App.svelte index 9a17999..1bb5689 100644 --- a/src/app/App.svelte +++ b/src/app/App.svelte @@ -216,6 +216,18 @@ return parseTodoPayload(field.payload); }); + // Top-bar title: the active tab's title, or "New Tab" when no tab is active + // (a fresh, unstarted draft — the conversation hasn't been sent yet, so no + // tab exists). Pure-derived from the (workspace-filtered) tab set + the + // active id; reflects whichever tab is selected in the sidebar's Tabs view. + const NEW_TAB_TITLE = "New Tab"; + const topBarTitle = $derived.by(() => { + const id = store.activeConversationId; + if (id === null) return NEW_TAB_TITLE; + const tab = store.tabs.find((t) => t.conversationId === id); + return tab?.title ?? NEW_TAB_TITLE; + }); + // Conversation/tab switch → snap to the bottom of the new transcript. $effect(() => { void store.activeConversationId; @@ -421,9 +433,18 @@ (below), so opening it shrinks this ENTIRE column. -->
-
+ the top row now shows the active tab's title on the left (or "New Tab" + for an unstarted draft), with the build version + sidebar toggle on + the right. --> +
+ + {topBarTitle} + { store.dispose(); }); + it("shows 'New Tab' in the top bar for an unstarted draft (no active tab)", () => { + const ws = fakeSocket(); + const store = createAppStore({ + socketFactory: () => ws, + fetchImpl: fakeFetchImpl(), + localStorage: createFakeStorage(), + }); + ws.resolveOpen(); + + render(App, { props: { store } }); + + expect(store.activeConversationId).toBeNull(); + expect(screen.getByTestId("top-bar-title")).toHaveTextContent("New Tab"); + + store.dispose(); + }); + + it("shows the active tab's title in the top bar once a tab is started", async () => { + const ws = fakeSocket(); + const store = createAppStore({ + socketFactory: () => ws, + fetchImpl: fakeFetchImpl(), + localStorage: createFakeStorage(), + }); + ws.resolveOpen(); + + render(App, { props: { store } }); + + // Promote draft → tab: the tab's title is derived from the first message. + store.send("Refactor the auth module"); + expect(store.activeConversationId).not.toBeNull(); + + // The top-bar title updates reactively; findByTestId awaits the flush. + expect(await screen.findByTestId("top-bar-title")).toHaveTextContent( + "Refactor the auth module", + ); + + store.dispose(); + }); + it("auto-subscribes to every catalog entry on render (no buttons to click)", () => { const ws = fakeSocket(); const store = createAppStore({ -- cgit v1.2.3