polish(v0.6): make "New session" a grid tile instead of a heavy header button

The big solid-amber "+ New session" button clashed with the refined segmented
control. Replace it with a dashed "+" tile that leads the session grid (same
size as the session cards, re-prepended each refresh), so it reads as a natural
"create" cell. Header is now just the title + Sessions/Projects toggle; the
redundant empty-state message is gone (the tile is the CTA).

Frontend-only (launcher.ts + style.css). Verified: web typecheck + build clean,
preview-grid tests green, in-browser the grid leads with the New-session tile
followed by the session cards (Open/Kill).
This commit is contained in:
Yaojia Wang
2026-06-30 14:25:56 +02:00
parent bf5241e87b
commit 59de784c8a
3 changed files with 47 additions and 19 deletions

View File

@@ -42,16 +42,20 @@ export function mountLauncher(host: HTMLElement, hooks: LauncherHooks): Launcher
const head = el('div', 'launcher-head')
head.append(el('div', 'launcher-title', 'Your sessions'))
const sub = el('div', 'launcher-sub', '')
const actions = el('div', 'launcher-actions')
const newBtn = el('button', 'launcher-new', ' New session')
newBtn.addEventListener('click', () => hooks.onNew())
actions.append(newBtn)
head.append(sub, actions)
head.append(sub)
root.append(head)
const grid = el('div', 'mg-grid')
root.append(grid)
// "New session" is a tile that leads the grid (matches the session cards),
// instead of a heavy header button. Re-prepended on every refresh.
const newTile = el('button', 'mg-new-card')
newTile.title = 'Start a new session'
newTile.setAttribute('aria-label', 'New session')
newTile.append(el('div', 'mg-new-plus', ''), el('div', 'mg-new-label', 'New session'))
newTile.addEventListener('click', () => hooks.onNew())
const cards = new Map<string, PreviewCard>()
let timer: ReturnType<typeof setInterval> | null = null
@@ -78,6 +82,9 @@ export function mountLauncher(host: HTMLElement, hooks: LauncherHooks): Launcher
? `${sessions.length} running on this host — pick one to open`
: 'No sessions running yet'
// Keep the New-session tile as the first grid cell.
if (grid.firstChild !== newTile) grid.prepend(newTile)
const seen = new Set<string>()
for (const s of sessions) {
seen.add(s.id)
@@ -99,10 +106,6 @@ export function mountLauncher(host: HTMLElement, hooks: LauncherHooks): Launcher
}
}
grid.querySelector('.mg-empty')?.remove()
if (sessions.length === 0) {
grid.append(el('div', 'mg-empty', 'No running sessions. Click “New session” to start one.'))
}
}
return {