feat: merged title bar — drag bands, owner's mark, title-width rename hit-box
The system title bar disappears (titleBarStyle hiddenInset +
trafficLightPosition {16,24}): the app's own 60px header bands become the
window's drag surface, and the traffic lights float over the sidebar's
mark band, vertically centered on the same line as the chat header's
phase pill (pixel-verified: circle centers y 24–36.5pt, pill box center
30pt).
- electron/main.cjs: hiddenInset chrome; dev shell (LH_DEV_URL) gets its
own userData (-dev suffix) so it never fights the packaged app's
single-instance lock — verified: the lock silently killed the dev
shell while the packaged app was open (that also proved the lock works
across separately-launched builds).
- app/globals.css: .lh-electron-gated utilities — drag/no-drag bands,
92px traffic-light gutter (.lh-lights-gutter / .lh-closed-toggle:
lights end ~75pt + the lights' own 16px edge inset as the gap),
home's floating strip becomes a drag surface only in the shell.
Everything is inert in the plain browser.
- sidebar.tsx: SidebarProvider sets <html class=lh-electron> post-mount
(UA detection; no hydration mismatch, absent in browser); LH wordmark
text replaced by the owner's mark (components/lh-mark.tsx, inlined
icon-no-padding.svg, 24px, home link kept); SidebarToggle gains the
92px margin when closed so it never slides under the static lights.
- chat.tsx: the rename hit-box shrinks to the title text itself —
flex-1 spanned the whole bar, so every click started a rename and the
window lost its grip. Shrink-to-fit + a flex-1 drag spacer (chips stay
right) + hover:bg-accent affordance (clear when hover renames vs
drags; -mx/px cancel for zero shift). The renaming input keeps flex-1
for edit room.
- home.tsx / new-session.tsx / phase-divider.tsx: drag bands + carve-outs.
Live-verified in the dev shell (pixel analysis) and headless browser:
lights/pill/mark centered, 17pt lights→mark gap, rename click→select-all
→Escape roundtrip, browser layout untouched.
Gates: typecheck, eslint, 500/500 tests, build.
This commit is contained in:
+10
-5
@@ -637,7 +637,7 @@ export function Chat({
|
||||
60px is an ALIGNMENT, not just a size: it equals the sidebar's
|
||||
LH wordmark band, so the header's border-b continues that
|
||||
band's bottom edge as one line across the app (owner, round 6). */}
|
||||
<header className="flex h-15 items-center gap-3 border-b border-border px-3">
|
||||
<header className="lh-drag flex h-15 items-center gap-3 border-b border-border px-3">
|
||||
<SidebarToggle />
|
||||
{renaming ? (
|
||||
<input
|
||||
@@ -651,9 +651,10 @@ export function Chat({
|
||||
onBlur={() => void commitRename(titleDraft)}
|
||||
spellCheck={false}
|
||||
aria-label="Session title"
|
||||
className="min-w-0 flex-1 bg-transparent font-title text-3xl tracking-tight caret-current outline-none"
|
||||
className="lh-no-drag min-w-0 flex-1 bg-transparent font-title text-3xl tracking-tight caret-current outline-none"
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
title="Rename session"
|
||||
@@ -661,10 +662,14 @@ export function Chat({
|
||||
setTitleDraft(titleText);
|
||||
setRenaming(true);
|
||||
}}
|
||||
className="min-w-0 flex-1 cursor-text truncate text-left font-title text-3xl tracking-tight"
|
||||
className="lh-no-drag -mx-1.5 min-w-4 shrink cursor-text truncate rounded-md px-1.5 text-left font-title text-3xl tracking-tight transition-colors hover:bg-accent"
|
||||
>
|
||||
{titleText}
|
||||
</button>
|
||||
</button>
|
||||
{/* flex-1 spacer: keeps the chips at the right edge AND stays a
|
||||
drag surface (no carve-out) — the freed bar is grippable. */}
|
||||
<div className="min-w-4 flex-1" aria-hidden="true" />
|
||||
</>
|
||||
)}
|
||||
{/* The plan chip (owner, plan-placement round): session-level
|
||||
structure beside the phase chip — access to the full-DAG popup
|
||||
@@ -675,7 +680,7 @@ export function Chat({
|
||||
data-testid="plan-chip"
|
||||
onClick={() => setPlanOpen(true)}
|
||||
title="Open the full plan"
|
||||
className="flex shrink-0 cursor-pointer items-center gap-1.5 rounded-full border border-border/80 px-2 py-0.5 text-xs font-medium uppercase tracking-wide text-muted-foreground transition-colors hover:border-border hover:text-foreground"
|
||||
className="lh-no-drag flex shrink-0 cursor-pointer items-center gap-1.5 rounded-full border border-border/80 px-2 py-0.5 text-xs font-medium uppercase tracking-wide text-muted-foreground transition-colors hover:border-border hover:text-foreground"
|
||||
>
|
||||
<WaypointsIcon className="size-3.5 text-primary" aria-hidden />
|
||||
Plan
|
||||
|
||||
Reference in New Issue
Block a user