refactor(layout): floating sidebar + floating top header #113

Merged
varutasu merged 1 commit from redesign-v2-floating-chrome into main 2026-06-04 13:07:17 -04:00
2 changed files with 44 additions and 13 deletions

View file

@ -664,7 +664,18 @@ export default function Layout({ children, user = null, showSearch = false }) {
}, []);
return (
<div className="flex h-screen">
// Outer shell — `md:p-4 md:gap-4` pulls both the sidebar and the
// main column in from the viewport edges so the sidebar and the
// top header read as floating chrome chips (operator feedback
// 2026-06-04: "pull out the left nav to make it look like it is
// its own floating section versus attached to the top-left"). The
// `md:gap-4` on this row also creates the visible page-body
// background between the sidebar's right edge and the main
// column, which replaces the previous hard divider — "all feels
// like one large page" is achieved by the hearth gradient
// showing through the gap. Mobile (< 768px) keeps the current
// flush layout because the sidebar is `hidden md:flex` anyway.
<div className="flex h-screen md:p-4 md:gap-4">
{/* Mobile Navigation - Bottom bar for mobile */}
<MobileNavigation
onMenuOpen={() => setIsMobileMenuOpen(true)}
@ -815,14 +826,21 @@ export default function Layout({ children, user = null, showSearch = false }) {
{/* Desktop Sidebar - Hidden on mobile. Liquid Glass mid-tint, ambient
elevation + rim-light edges; the page background visibly cools
through the rail. */}
through the rail. 2026-06-04 floating-chrome pass: rounded-3xl
+ overflow-hidden so the rail reads as its own floating chip;
`var(--rim-light-outer)` dropped from the box-shadow stack
because that 1px outer ring was the "vertical divider between
the sidebar and the right side" the operator wanted gone. The
chip's edge is now defined solely by `var(--elevation-ambient)`
(drop shadow) + the glass-surface-mid tint against the body
gradient that shows through `md:gap-4` on the outer flex. */}
<div
className="hidden md:flex md:static inset-y-0 left-0 w-64"
className="hidden md:flex md:static inset-y-0 left-0 w-64 md:rounded-3xl md:overflow-hidden"
style={{
background: 'var(--glass-surface-mid)',
backdropFilter: 'blur(var(--glass-blur-mid)) saturate(var(--glass-saturate))',
WebkitBackdropFilter: 'blur(var(--glass-blur-mid)) saturate(var(--glass-saturate))',
boxShadow: 'var(--rim-light-inner), var(--rim-light-outer), var(--elevation-ambient)',
boxShadow: 'var(--rim-light-inner), var(--elevation-ambient)',
}}
>
<div className="p-4 h-full flex flex-col w-full">
@ -933,8 +951,14 @@ export default function Layout({ children, user = null, showSearch = false }) {
</div>
</div>
{/* Main Content */}
<div className="flex-1 flex flex-col pb-16 md:pb-0">
{/* Main Content. `md:gap-4` adds vertical breathing room between
the floating TopSearchBar header and the page content so they
read as two distinct floating chrome elements over the body
gradient (rather than the header sitting flush against the
content). `min-w-0` prevents flex children from blowing past
the column width when long card titles or table cells refuse
to wrap. */}
<div className="flex-1 flex flex-col pb-16 md:pb-0 md:gap-4 min-w-0">
{/* Global top bar redesign-v2 sub-convoy #3 (2026-06-04).
Rendered for ALL authenticated pages so the search +
notifications + user-menu chrome is consistent everywhere

View file

@ -62,17 +62,24 @@ export default function TopSearchBar({
return (
<header
className="px-4 sm:px-6 py-3 flex items-center gap-3 sm:gap-4"
// Floating-chrome pass 2026-06-04: `md:rounded-2xl` so the bar
// reads as its own floating chip on desktop (Layout's
// `md:p-4 md:gap-4` puts visible body gradient on all four sides
// of it). Mobile keeps square corners since the header runs
// edge-to-edge there. The shadow stack pairs `rim-light-inner`
// (subtle top inset highlight kept from the prior pass) with
// `elevation-ambient` (drop shadow) so it floats over the body
// gradient. We deliberately did NOT add `rim-light-outer` here:
// the operator's "remove the divider" feedback from the prior
// pass applies to any visible 1px edge, and a hairline outer
// ring would re-introduce one on mobile where the bar abuts
// content directly.
className="px-4 sm:px-6 py-3 flex items-center gap-3 sm:gap-4 md:rounded-2xl"
style={{
background: 'var(--glass-surface-mid)',
backdropFilter: 'blur(12px) saturate(180%)',
WebkitBackdropFilter: 'blur(12px) saturate(180%)',
// The hairline border-bottom (`0 1px 0 var(--border)`) was
// removed 2026-06-04 per operator feedback ("almost looks
// seamless between that header and the rest of that page
// content"). The rim-light-inner highlight stays so the bar
// still reads as elevated chrome against the gradient body.
boxShadow: 'var(--rim-light-inner)',
boxShadow: 'var(--rim-light-inner), var(--elevation-ambient)',
}}
>
{/* Search affordance read-only-ish input that opens the