fix(layout): topbar grid auto-expanded center column hid right buttons at 780-1280
Some checks failed
Build & Push Docker Images / lint (push) Successful in 2m37s
Build & Push Docker Images / build-and-push (push) Has been cancelled

User reported the search bar dropping to a second row + the top-right
buttons (+ New / Inbox / Avatar) going missing as they resized the
browser. Playwright probe confirmed: at every width 780-1280 the
search bar's intrinsic `max-w-2xl` (672px) forced the topbar's
center grid column to expand to that width, leaving the right
column too narrow to hold "+ New + Inbox + Avatar" without
overlapping the search OR going off-screen.

Two coordinated fixes:

1. Grid template `auto_1fr_auto` instead of `1fr_minmax(280,800)_1fr`.
   Side columns now size to their actual content (logo + breadcrumbs
   on the left; New + Inbox + Avatar on the right); the center
   column takes whatever's left. No more "intrinsic content forces
   the column to grow" behaviour.

2. Search wrapper max-width scales by tier: max-w-md (448px) at
   base, lg:max-w-xl (576px), xl:max-w-2xl (672px). Generous enough
   on wide screens, restrained enough on narrow ones so the side
   columns always get the space they need.

Verified via Playwright probe at 780/900/1023/1024/1100/1280 —
"+ New" button now lands inside the header at every width.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-22 14:22:29 +02:00
parent 9ae7940a04
commit 355f242b8f

View File

@@ -60,12 +60,16 @@ export function Topbar({ ports, user, leadingSlot }: TopbarProps) {
// The brand logo lives in the sidebar header (per design feedback) so the
// topbar center is dedicated to the global search bar.
//
// Center column min-width: 280 at tablet, 420 at lg+. The earlier
// single 420 min starved the left column to ~100px at 768 viewport
// width (when the sidebar is hidden under a Sheet on tablet) — that
// was hiding the new logo-trigger leadingSlot AppShell mounts. Two
// breakpoints split the difference cleanly.
<header className="grid h-14 grid-cols-[minmax(0,1fr)_minmax(280px,800px)_minmax(0,1fr)] items-center border-b border-border bg-background gap-3 px-4 shrink-0 lg:grid-cols-[minmax(0,1fr)_minmax(420px,800px)_minmax(0,1fr)]">
// Grid is `auto auto 1fr` instead of three fr-tracks: the left + right
// columns size to their actual content (logo trigger + breadcrumbs on
// the left; New / Inbox / Avatar on the right), and the search column
// soaks up the rest. The earlier `minmax(280px,800px)` center column
// auto-grew to the search bar's intrinsic `max-w-2xl` (672px), which
// squeezed the right column below the width of "+ New + Inbox +
// Avatar" and pushed the New button off-screen at every tablet +
// narrow-desktop width. With the center as a single fr-track, the
// right column always gets the space it needs.
<header className="grid h-14 grid-cols-[auto_1fr_auto] items-center border-b border-border bg-background gap-3 px-4 shrink-0">
{/* LEFT: optional sidebar trigger (tablet) + optional back button + breadcrumbs */}
<div className="min-w-0 flex items-center gap-1.5">
{leadingSlot}
@@ -86,18 +90,18 @@ export function Topbar({ ports, user, leadingSlot }: TopbarProps) {
<Breadcrumbs />
</div>
{/* CENTER: global search - capped width and visually centered
against the FULL viewport (not the post-sidebar area) via a
translate-X that shifts left by half the sidebar width.
Without the translate the topbar's grid centers inside the
area-after-the-sidebar, so the search visually drifts right
by half the sidebar width.
The translate is gated to `lg:` because at tablet (768-1023)
the sidebar is HIDDEN behind a Sheet — translating left there
shifts the search into the leading-slot column, hiding the
AppShell-mounted logo trigger. */}
{/* CENTER: global search. Caps scale by viewport tier so the search
bar doesn't crowd the side columns at narrow widths:
base: max-w-md (28rem / 448px) — fits tablet 768-1023 with
~150-200px left for the right column.
lg: max-w-xl (36rem / 576px) — narrow desktop with sidebar.
xl: max-w-2xl (42rem / 672px) — full desktop, plenty of room.
The lg: translate-X visually centers the search against the FULL
viewport (compensating for the sidebar's 256px on the left). It
stays gated to lg+ so tablet (sidebar hidden behind Sheet)
doesn't get an unnecessary shift. */}
<div className="flex items-center justify-center min-w-0">
<div className="w-full max-w-2xl mx-auto min-w-0 lg:-translate-x-[calc(var(--width-sidebar)/2)]">
<div className="w-full max-w-md mx-auto min-w-0 lg:max-w-xl xl:max-w-2xl lg:-translate-x-[calc(var(--width-sidebar)/2)]">
<CommandSearch />
</div>
</div>