From bf80473d35c8b14db7145af79f25aed69cd90a0f Mon Sep 17 00:00:00 2001 From: Guilhem Lemouel Date: Mon, 5 Oct 2026 11:32:54 -0700 Subject: [PATCH] feat: a session in full screen keeps its tabs in the band Full screen used to drop the session's name from the breadcrumb and leave the tab strip inside the panel. The band now carries both: the session's name where "Sessions" stood, and from the breadcrumb to the right edge one filled surface holding the tabs and the preview's controls, the bar's full height. The switch between the two layouts is the panel expanding to the left. The chat column is resized to nothing rather than unmounted, so it can be seen taking its place -- and so a toggle no longer tears down every mounted chat and rebuilds it on the way back. Panes transition their width only while that switch is in flight, since a splitter drag sets the same inline width and would trail the pointer. The band floats over the content in full screen as it already did beside a panel, so only its right edge moves and the page below never shifts by the bar's height. Leaving full screen, the panel travels back across ground the band has already claimed, so it passes one layer above it for the length of the move: pinned to the width the panel will end at, the bar would otherwise show through as a white patch over the panel's left edge. The breadcrumb also gains the acting fork, the way every other page shows it, which replaces the "Acting on" control the session header carried. Co-Authored-By: Claude Opus 5 (1M context) --- .../src/lib/components/NavBreadcrumb.svelte | 20 +- .../src/lib/components/PageHeaderBar.svelte | 17 +- .../lib/components/PageHeaderContent.svelte | 2 + .../common/tabs/DraggableTabs.svelte | 7 +- .../components/pageHeaderRegistry.svelte.ts | 6 + .../components/sessions/SessionWrapper.svelte | 22 +- .../(root)/(logged)/sessions/+page.svelte | 461 +++++++++++------- 7 files changed, 333 insertions(+), 202 deletions(-) diff --git a/frontend/src/lib/components/NavBreadcrumb.svelte b/frontend/src/lib/components/NavBreadcrumb.svelte index 5bcfd4db24..bffb4b7c43 100644 --- a/frontend/src/lib/components/NavBreadcrumb.svelte +++ b/frontend/src/lib/components/NavBreadcrumb.svelte @@ -53,9 +53,6 @@ same weight, size and icon size, so the line reads as one control rather than fo } = $props() const scopeId = $derived(actingWorkspaceId ?? $workspaceStore ?? undefined) - // In session mode the workspace is the session's scope, not a place to navigate to: the name - // says which workspace the chat acts on, and going home from it would leave the session. - const sessionMode = $derived(page.url.pathname.startsWith(`${base}/sessions`)) const homeHref = $derived( actingWorkspaceId ? `${base}/?workspace=${encodeURIComponent(actingWorkspaceId)}` : `${base}/` ) @@ -103,9 +100,7 @@ same weight, size and icon size, so the line reads as one control rather than fo const forkableWorkspaces = $derived(forkable.current) const currentWs = $derived(forkableWorkspaces.find((w) => w.id === scopeId)) const inFork = $derived(!!currentWs?.parent_workspace_id) - // A session names the workspace it acts on beside its own title, so here the family name alone - // says where the user is browsing — the fork in this spot would read as a workspace switch. - const showFork = $derived(inFork && !actingWorkspaceId) + const showFork = $derived(inFork) const familyName = $derived(family?.name ?? scopeId ?? '') // The workspace the user actually stands in, which is the fork's own name inside a fork. const scopeName = $derived(currentWs?.name ?? familyName) @@ -116,7 +111,6 @@ same weight, size and icon size, so the line reads as one control rather than fo // A dev workspace wears its environment; the root wears "prod", so which environment the user // is standing in is answered the same way whichever one it is. const envBadge = $derived.by(() => { - if (actingWorkspaceId) return undefined if (!inFork) return { text: 'prod', dev: false } if (currentWs?.is_dev_workspace) return { text: devBadgeText(currentWs.dev_workspace_label), dev: true } @@ -182,8 +176,10 @@ same weight, size and icon size, so the line reads as one control rather than fo {/if} {/snippet} -{#snippet slash()} - +{#snippet slash(extra = '')} + + {/snippet}