6d665d0113962bf27e66aecb5e1fc2f0e6b86a44
Previously the app used a binary matchMedia split at 1023.98px, so iPad portrait + half-screen-on-13"-Mac both fell into the mobile shell — neither is really mobile. The tablet tier fills that gap. - `use-is-mobile.ts` gains `useViewportTier()` returning 'mobile' | 'tablet' | 'desktop' (mobile < 768, tablet 768-1023, desktop ≥ 1024). Backed by useSyncExternalStore so render reads stay pure. `useIsMobile()` retained as a back-compat alias = `tier !== 'desktop'` so existing call sites don't have to change in lockstep. - `app-shell.tsx` now renders three branches. Mobile + desktop unchanged. Tablet renders the desktop shell, but the Sidebar lives inside a left-side `<Sheet>` opened by a new leading logo button in the Topbar. SheetContent width matches `--width-sidebar` so the open state reads consistent. Children subtree position stays invariant across tier flips so inline-edit drafts survive a resize. - `topbar.tsx` accepts an optional `leadingSlot` rendered before the back button + breadcrumbs in the LEFT column. AppShell mounts a port-logo button in that slot on tablet (or a three-bar menu icon when the port has no logo yet) that triggers the sheet. - `page-header.tsx` was the dashboard "title card looks bad on tablet" surface — the actions row was forced no-wrap at sm (640px) which crushed the title on iPad-portrait. Stack point moved from sm to lg, so tablet stacks vertically (title above, actions below); desktop returns to side-by-side. tsc clean, 1454/1454 vitest pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Description
No description provided
Languages
TypeScript
98.7%
HTML
1%
CSS
0.1%
Shell
0.1%