From e8eba34d59b4ffd349de1165c06b80b2f8c3d574 Mon Sep 17 00:00:00 2001 From: varutasu <104105839+varutasu@users.noreply.github.com> Date: Thu, 4 Jun 2026 16:25:14 -0500 Subject: [PATCH] refactor(layout): migrate 3 floating popovers to .glass-panel-strong (#124) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Brief 3 of unify-glass-panel-surfaces convoy. Migrates three floating surfaces from inline var(--glass-surface-*) + backdropFilter to the canonical .glass-panel-strong className, preserving their existing box-shadow chains (ember rim for the dropdown panels; pronounced elevation for the drawer + TopSearchBar UserMenu) via inline override. Three popovers migrated: 1. components/Layout.js UserProfileDropdown panel (sidebar) - boxShadow chain preserved: var(--rim-light-inner), var(--ember-rim-subtle), var(--elevation-ambient). 2. components/Layout.js mobile drawer - boxShadow chain preserved: var(--rim-light-inner), var(--rim-light-outer), var(--elevation-pronounced). 3. components/ui/TopSearchBar.js UserMenu dropdown - boxShadow chain preserved: var(--rim-light-inner), var(--ember-rim-subtle), var(--elevation-pronounced) (note: -pronounced, not -ambient — caught by architect boot-the-brief recheck and documented in convoy's risk note). The sidebar nav-chip / main content chrome block (Layout.js ~L853-863) intentionally remains handrolled with full-intensity corner lights — allowlisted by Brief 7's CI gate (D4 of the architect plan). Tests (test/components/Layout.test.js, +2 new assertions): - mobile drawer container queryable via .glass-panel-strong selector and is wired with width/positioning classes (.w-64, .fixed, etc). - mobile drawer inline style contains no var(--glass-surface-*) and no backdrop-filter (both now provided by the class); does contain var(--elevation-pronounced) (preserved override). Verification: - npm run lint passes (1 pre-existing unrelated warning). - npm run test:run: 118/118 tests pass (was 116; +2 new). Acceptance criteria from .convoys/unify-glass-panel-surfaces/brief-3-floating-popovers.md all met. No edits outside the 3 files in scope. Co-authored-by: Cursor --- components/Layout.js | 16 +++++------- components/ui/TopSearchBar.js | 5 +--- test/components/Layout.test.js | 46 ++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/components/Layout.js b/components/Layout.js index 47df0e8..d07f8e9 100644 --- a/components/Layout.js +++ b/components/Layout.js @@ -87,12 +87,10 @@ function UserProfileDropdown({ user, onMobileMenuClose }) { {/* Menu — Liquid Glass popover, high-tint w/ ember-subtle rim. */}
@@ -693,14 +691,12 @@ export default function Layout({ children, user = null, showSearch = false }) { {/* Mobile Menu Drawer - Slides in from left when "More" is tapped */}
diff --git a/components/ui/TopSearchBar.js b/components/ui/TopSearchBar.js index ce2ca06..1e3b409 100644 --- a/components/ui/TopSearchBar.js +++ b/components/ui/TopSearchBar.js @@ -211,11 +211,8 @@ function UserMenu({ user }) {
{ expect(container.textContent).not.toContain('Guest'); }); }); + +describe('Layout — floating popovers use .glass-panel-strong (regression: Brief 3 of unify-glass-panel-surfaces)', () => { + afterEach(() => cleanup()); + + // The sidebar UserProfileDropdown and the mobile drawer are floating + // glass surfaces. Brief 3 migrated them from inline + // `background: var(--glass-surface-*)` + `backdropFilter` to the + // canonical `.glass-panel-strong` className. If a future PR reverts + // either to the inline pattern, the bespoke-glass-surface CI gate + // (Brief 7) will catch the regression — these unit tests catch the + // SAME regression at the component-render level, before the gate + // would fire. + + it('mobile drawer panel carries .glass-panel-strong when isMobileMenuOpen', () => { + const { container } = render( + page body + ); + // The drawer is rendered (translated off-screen via `-translate-x-full`) + // even when closed, so we can assert on it from a default mount. + const drawer = container.querySelector( + '.glass-panel-strong.md\\:hidden.fixed.inset-y-0.left-0' + ); + expect(drawer).not.toBeNull(); + expect(drawer.className).toContain('glass-panel-strong'); + expect(drawer.className).toContain('w-64'); + }); + + it('mobile drawer panel does NOT carry an inline `background: var(--glass-surface-*)` style after Brief 3', () => { + // Regression lock against reverting Brief 3 to handrolled inline + // glass styles on the mobile drawer specifically. The drawer is + // always in the DOM (translated off-screen when closed), so we can + // query it from a default mount. + const { container } = render( + page body + ); + const drawer = container.querySelector( + '.glass-panel-strong.md\\:hidden.fixed.inset-y-0.left-0' + ); + expect(drawer).not.toBeNull(); + const inlineStyle = drawer.getAttribute('style') ?? ''; + expect(inlineStyle).not.toMatch(/var\(--glass-surface-/); + expect(inlineStyle).not.toMatch(/backdrop-filter/i); + expect(inlineStyle).toContain('box-shadow'); + expect(inlineStyle).toContain('--elevation-pronounced'); + }); +});