From 3f196514f86017fbd569b0f65df3d461ad0576f2 Mon Sep 17 00:00:00 2001 From: Michael Yong Date: Fri, 7 Aug 2026 21:56:50 -0700 Subject: [PATCH] Fix selected sticky sidebar row transparency --- .../components/sidebar/sidebarRowClasses.test.ts | 6 ++++++ .../app/src/components/sidebar/sidebarRowClasses.ts | 2 +- apps/app/src/components/ui/theme.css | 10 ++++++++++ apps/app/src/components/ui/theme.test.ts | 13 +++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/apps/app/src/components/sidebar/sidebarRowClasses.test.ts b/apps/app/src/components/sidebar/sidebarRowClasses.test.ts index 05d56ca231..6a00c80c0d 100644 --- a/apps/app/src/components/sidebar/sidebarRowClasses.test.ts +++ b/apps/app/src/components/sidebar/sidebarRowClasses.test.ts @@ -9,4 +9,10 @@ describe("sidebar selected thread styling", () => { ); expect(CONTEXT_SELECTION_SURFACE_CLASS).toBe("bg-state-active"); }); + + it("marks the row for an opaque backing surface when it becomes sticky", () => { + expect(SIDEBAR_ROW_SELECTED_STATE_CLASS).toContain( + "bb-sidebar-selected-row", + ); + }); }); diff --git a/apps/app/src/components/sidebar/sidebarRowClasses.ts b/apps/app/src/components/sidebar/sidebarRowClasses.ts index 0cd1841f32..ea6dd66b46 100644 --- a/apps/app/src/components/sidebar/sidebarRowClasses.ts +++ b/apps/app/src/components/sidebar/sidebarRowClasses.ts @@ -70,7 +70,7 @@ export const SIDEBAR_ROW_STATIC_STATE_CLASS = "text-sidebar-foreground/85 dark:text-sidebar-foreground"; export const SIDEBAR_ROW_SELECTED_STATE_CLASS = - `${CONTEXT_SELECTION_SURFACE_CLASS} text-sidebar-foreground`; + `${CONTEXT_SELECTION_SURFACE_CLASS} bb-sidebar-selected-row text-sidebar-foreground`; export const SIDEBAR_MORE_ACTION_TRIGGER_CLASS = "relative m-1 h-5 w-5 after:absolute after:left-1/2 after:top-1/2 after:h-7 after:w-7 after:-translate-x-1/2 after:-translate-y-1/2 after:content-[''] max-md:pointer-coarse:m-0 max-md:pointer-coarse:h-9 max-md:pointer-coarse:w-9 max-md:pointer-coarse:after:hidden"; diff --git a/apps/app/src/components/ui/theme.css b/apps/app/src/components/ui/theme.css index 67261c42ce..974415b900 100644 --- a/apps/app/src/components/ui/theme.css +++ b/apps/app/src/components/ui/theme.css @@ -202,6 +202,16 @@ height: var(--bb-sidebar-sticky-tier-shield-bottom-height, 0); } + /* The shared active-context surface is translucent so it can tint tabs and + other content surfaces. A sticky sidebar row needs an opaque sidebar layer + beneath that tint, or scrolled descendant text paints through the row. */ + [data-sidebar-sticky-stack] + [data-sidebar-sticky-tier].bb-sidebar-selected-row { + background-image: + linear-gradient(var(--state-active), var(--state-active)), + linear-gradient(var(--sidebar), var(--sidebar)); + } + .bb-sidebar-hover-actions { pointer-events: none; opacity: 0; diff --git a/apps/app/src/components/ui/theme.test.ts b/apps/app/src/components/ui/theme.test.ts index 3d69180c14..a60add4d59 100644 --- a/apps/app/src/components/ui/theme.test.ts +++ b/apps/app/src/components/ui/theme.test.ts @@ -133,6 +133,19 @@ function contrastRatio(foreground: OklchColor, background: OklchColor): number { } describe("theme.css neutral ramp", () => { + it("backs selected sticky sidebar rows with an opaque sidebar layer", () => { + const rule = css.match( + /\[data-sidebar-sticky-tier\]\.bb-sidebar-selected-row\s*\{([^}]*)\}/s, + )?.[1]; + + expect(rule).toContain( + "linear-gradient(var(--state-active), var(--state-active))", + ); + expect(rule).toContain( + "linear-gradient(var(--sidebar), var(--sidebar))", + ); + }); + for (const mode of MODES) { describe(mode, () => { const block = modeBlock(mode);