Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
56f31d9
feat(ui): show the active session title in the header
pascalandr Apr 18, 2026
2a62421
feat(ui): show the session title in the tab bar
pascalandr Apr 18, 2026
f748b42
Merge upstream dev into fix/show-session-title
pascalandr May 9, 2026
2758514
fix(ui): move session title into header
pascalandr May 9, 2026
1de1189
fix(ui): align header session title with floating sidebar
pascalandr May 9, 2026
f24a74b
fix(ui): soften header session title
pascalandr May 9, 2026
cdbe594
fix(ui): preserve toolbar offset for floating sidebar
pascalandr May 9, 2026
064cffd
fix(ui): keep header session title under floating sidebar
pascalandr May 9, 2026
e6a5929
Merge upstream/dev into fix/show-session-title for task 055
pascalandr May 16, 2026
541cd04
Merge branch 'dev' into fix/show-session-title
pascalandr May 16, 2026
e9e7e9d
Merge upstream/dev into fix/show-session-title for task 055 reopen
pascalandr May 16, 2026
b300e64
fix: task-069 remove compact header session title
pascalandr May 27, 2026
b100799
Merge branch 'dev' into fix/show-session-title
pascalandr May 27, 2026
935e39d
fix: task-078 restore UI typecheck on integrated batch
pascalandr Jun 5, 2026
c8f9aac
Merge branch 'dev' into fix/show-session-title
pascalandr Jun 5, 2026
452185f
fix: restore tablet preview toggle
pascalandr Jun 6, 2026
6be548c
chore: 085 remove PR 340 evidence artifacts
pascalandr Jun 6, 2026
a35d44c
Merge branch 'dev' into fix/show-session-title
pascalandr Jun 6, 2026
85737ef
Merge branch 'dev' into fix/show-session-title
pascalandr Jun 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ const App: Component = () => {
binaryPath: string
instanceId: string
} | null>(null)

const phoneQuery = useMediaQuery("(max-width: 767px)")
const isPhoneLayout = createMemo(() => phoneQuery())

Expand Down
219 changes: 120 additions & 99 deletions packages/ui/src/components/instance/instance-shell2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,23 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
</div>
)

const renderPreviewToggleButton = () => (
<Show when={!showingInfoView()}>
<IconButton
color="inherit"
onClick={handlePreviewButtonClick}
aria-label={previewToggleLabel()}
title={previewToggleLabel()}
size="small"
>
{(() => {
const Icon = PreviewToggleIcon()
return <Icon class="w-5 h-5" aria-hidden="true" />
})()}
</IconButton>
</Show>
)

const handleCommandPaletteClick = () => {
showCommandPalette(props.instance.id)
}
Expand Down Expand Up @@ -834,6 +851,50 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
}

const showingInfoView = createMemo(() => activeSessionIdForInstance() === "info")
const activeSessionTitle = createMemo(() => {
if (showingInfoView()) return null
const title = activeSessionForInstance()?.title?.trim()
return title || t("sessionList.session.untitled")
})
const showHeaderLeftSlot = createMemo(() => !leftPinned())
const showHeaderSessionTitle = createMemo(() => !compactHeaderLayout() && showHeaderLeftSlot() && Boolean(activeSessionTitle()))
const headerToolbarHorizontalInset = createMemo(() => (isPhoneLayout() ? 16 : 24))
const headerLeftSlotWidth = createMemo(() => Math.max(0, sessionSidebarWidth() - headerToolbarHorizontalInset()))
const headerLeftSlotStyle = createMemo(() =>
leftDrawerState() === "floating-open" || showHeaderSessionTitle() ? { width: `${headerLeftSlotWidth()}px` } : undefined,
)

const renderActiveSessionHeaderTitle = () => (
<Show when={showHeaderSessionTitle()}>
<div
class="session-header-active-title"
dir="auto"
title={activeSessionTitle() ?? undefined}
>
<span class="session-header-active-title-text">{activeSessionTitle()}</span>
</div>
</Show>
)

const renderHeaderLeftSlot = () => (
<Show when={showHeaderLeftSlot()}>
<div class="session-header-left-slot" style={headerLeftSlotStyle()}>
<Show when={leftDrawerState() === "floating-closed"}>
<IconButton
ref={setLeftToggleButtonEl}
color="inherit"
onClick={handleLeftAppBarButtonClick}
aria-label={leftAppBarButtonLabel()}
size="small"
aria-expanded={leftDrawerState() !== "floating-closed"}
>
{leftAppBarButtonIcon()}
</IconButton>
</Show>
{renderActiveSessionHeaderTitle()}
</div>
</Show>
)

const isLaunching = createMemo(() => props.instance.status === "starting")

Expand Down Expand Up @@ -933,94 +994,76 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
fallback={
<div class="flex flex-col w-full gap-1.5">
<div class="flex flex-wrap items-center justify-between gap-2 w-full">
<Show when={leftDrawerState() === "floating-closed"}>
<IconButton
ref={setLeftToggleButtonEl}
color="inherit"
onClick={handleLeftAppBarButtonClick}
aria-label={leftAppBarButtonLabel()}
size="small"
aria-expanded={leftDrawerState() !== "floating-closed"}
>
{leftAppBarButtonIcon()}
</IconButton>
</Show>
{renderHeaderLeftSlot()}

<div class="flex-1 flex items-center justify-center min-w-0">
{renderSessionHeaderIndicators()}
</div>
<div class="flex-1 flex items-center justify-center min-w-0">
{renderSessionHeaderIndicators()}
</div>

<div class="flex flex-wrap items-center justify-center gap-1">
<Show when={!showingInfoView()}>
<div class="flex flex-wrap items-center justify-center gap-1">
<Show when={!showingInfoView()}>
<IconButton
color="inherit"
onClick={handleChatSearchClick}
aria-label={t("instanceShell.chatSearch.openAriaLabel")}
title={t("instanceShell.chatSearch.openAriaLabel")}
size="small"
>
<Search class="w-5 h-5" aria-hidden="true" />
</IconButton>
</Show>
<button
type="button"
class="connection-status-button command-palette-button"
onClick={handleCommandPaletteClick}
aria-label={t("instanceShell.commandPalette.openAriaLabel")}
style={{ flex: "0 0 auto", width: "auto" }}
>
{t("instanceShell.commandPalette.button")}
</button>
<span class="connection-status-shortcut-hint kbd-hint">
<Kbd shortcut="cmd+shift+p" />
</span>
</div>

<div class="flex-1 flex items-center justify-center min-w-0">
<span
class={`status-indicator ${connectionStatusClass()}`}
aria-label={t("instanceShell.connection.ariaLabel", { status: connectionStatusLabel() })}
>
<span class="status-dot" />
</span>
</div>

<Show when={!isPhoneLayout()}>
{renderPreviewToggleButton()}
</Show>

<Show when={isPhoneLayout() && !props.mobileFullscreenMode}>
<IconButton
color="inherit"
onClick={handleChatSearchClick}
aria-label={t("instanceShell.chatSearch.openAriaLabel")}
title={t("instanceShell.chatSearch.openAriaLabel")}
onClick={props.onEnterMobileFullscreen}
aria-label={t("instanceShell.fullscreen.enter")}
title={t("instanceShell.fullscreen.enter")}
size="small"
>
<Search class="w-5 h-5" aria-hidden="true" />
<Maximize2 class="w-5 h-5" aria-hidden="true" />
</IconButton>
{renderPreviewToggleButton()}
</Show>

<Show when={rightDrawerState() === "floating-closed"}>
<IconButton
ref={setRightToggleButtonEl}
color="inherit"
onClick={handlePreviewButtonClick}
aria-label={previewToggleLabel()}
title={previewToggleLabel()}
onClick={handleRightAppBarButtonClick}
aria-label={rightAppBarButtonLabel()}
size="small"
aria-expanded={rightDrawerState() !== "floating-closed"}
>
{(() => {
const Icon = PreviewToggleIcon()
return <Icon class="w-5 h-5" aria-hidden="true" />
})()}
{rightAppBarButtonIcon()}
</IconButton>
</Show>
<button
type="button"
class="connection-status-button command-palette-button"
onClick={handleCommandPaletteClick}
aria-label={t("instanceShell.commandPalette.openAriaLabel")}
style={{ flex: "0 0 auto", width: "auto" }}
>
{t("instanceShell.commandPalette.button")}
</button>
<span class="connection-status-shortcut-hint kbd-hint">
<Kbd shortcut="cmd+shift+p" />
</span>
</div>

<div class="flex-1 flex items-center justify-center min-w-0">
<span
class={`status-indicator ${connectionStatusClass()}`}
aria-label={t("instanceShell.connection.ariaLabel", { status: connectionStatusLabel() })}
>
<span class="status-dot" />
</span>
</div>

<Show when={isPhoneLayout() && !props.mobileFullscreenMode}>
<IconButton
color="inherit"
onClick={props.onEnterMobileFullscreen}
aria-label={t("instanceShell.fullscreen.enter")}
title={t("instanceShell.fullscreen.enter")}
size="small"
>
<Maximize2 class="w-5 h-5" aria-hidden="true" />
</IconButton>
</Show>

<Show when={rightDrawerState() === "floating-closed"}>
<IconButton
ref={setRightToggleButtonEl}
color="inherit"
onClick={handleRightAppBarButtonClick}
aria-label={rightAppBarButtonLabel()}
size="small"
aria-expanded={rightDrawerState() !== "floating-closed"}
>
{rightAppBarButtonIcon()}
</IconButton>
</Show>
</div>

<div class="flex flex-wrap items-center justify-center gap-2 pb-1">
Expand All @@ -1038,18 +1081,7 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
}
>
<div class="session-toolbar-left flex-1 flex items-center gap-3 min-w-0">
<Show when={leftDrawerState() === "floating-closed"}>
<IconButton
ref={setLeftToggleButtonEl}
color="inherit"
onClick={handleLeftAppBarButtonClick}
aria-label={leftAppBarButtonLabel()}
size="small"
aria-expanded={leftDrawerState() !== "floating-closed"}
>
{leftAppBarButtonIcon()}
</IconButton>
</Show>
{renderHeaderLeftSlot()}

<Show when={!showingInfoView()}>
<ContextMeter
Expand Down Expand Up @@ -1095,18 +1127,7 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
>
<Search class="w-5 h-5" aria-hidden="true" />
</IconButton>
<IconButton
color="inherit"
onClick={handlePreviewButtonClick}
aria-label={previewToggleLabel()}
title={previewToggleLabel()}
size="small"
>
{(() => {
const Icon = PreviewToggleIcon()
return <Icon class="w-5 h-5" aria-hidden="true" />
})()}
</IconButton>
{renderPreviewToggleButton()}
</Show>
<Show when={connectionStatus() === "connected"}>
<span class="status-indicator connected">
Expand Down
26 changes: 26 additions & 0 deletions packages/ui/src/styles/panels/session-layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,32 @@
color: var(--text-primary);
}

.session-header-left-slot {
@apply flex items-center gap-2 min-w-0;
flex: 0 0 auto;
}

.session-header-active-title {
display: flex;
align-items: center;
flex: 1 1 auto;
min-width: 0;
align-self: stretch;
padding-inline: 0.75rem;
border-inline: 1px solid color-mix(in oklab, var(--border-base) 72%, transparent);
color: var(--text-secondary);
}

.session-header-active-title-text {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
font-size: 0.8125rem;
font-weight: 500;
line-height: 1.15;
}

.session-sidebar-shortcuts {
@apply flex flex-col gap-1;
}
Expand Down
Loading