From f5a57de56027333415142f03bb84b3b51ce1f20a Mon Sep 17 00:00:00 2001 From: Zach Marley Date: Thu, 8 Oct 2026 09:58:26 -0400 Subject: [PATCH] fix(styles): flatten `*`-led nested focus-visible rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tailwind v4.3.3 drops the whole parent selector when a selector that starts with the universal selector (e.g. `*:not(body):not(.focus-override)`) uses `&` nesting. The three nested focus-visible rules in globals.css all collapsed into a single bare `:focus-visible { ... }` block, so every focused element got the last rule's 2px `.link` ring — including `.focus-override` opt-outs like composer inputs (a stray grey ring) and the menu surfaces whose ring was meant to be suppressed. Flatten the three rules to equivalent single selectors (same specificity and cascade order) and add a test that keeps CSS nesting out of globals.css while the upstream bug stands. --- src/shared/styles/globals.css | 18 ++++++------------ src/shared/styles/globals.test.ts | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/shared/styles/globals.css b/src/shared/styles/globals.css index 78739b45d..35b461942 100644 --- a/src/shared/styles/globals.css +++ b/src/shared/styles/globals.css @@ -1953,10 +1953,8 @@ html[data-window-kind="voice-buddy"] #root { outline: none !important; } - *:not(body):not(.focus-override) { - &:focus-visible { - @apply ring-ring ring-offset-background ring-2 ring-offset-1 outline-hidden; - } + *:not(body):not(.focus-override):focus-visible { + @apply ring-ring ring-offset-background ring-2 ring-offset-1 outline-hidden; } /* Menu surfaces and items paint their own focus highlight (focus:bg-*), @@ -1977,20 +1975,16 @@ html[data-window-kind="voice-buddy"] #root { [data-slot="menubar-checkbox-item"], [data-slot="menubar-radio-item"], [data-slot="menubar-sub-trigger"] - ) { - &:focus-visible { - @apply ring-0 ring-offset-0; - } + ):focus-visible { + @apply ring-0 ring-offset-0; } .link { @apply hover:text-foreground/80 inline-flex items-center gap-1 rounded-xs font-medium underline underline-offset-4; } - *:not(body):not(.focus-override).link { - &:focus-visible { - @apply ring-ring ring-offset-background ring-2 ring-offset-2 outline-hidden; - } + *:not(body):not(.focus-override).link:focus-visible { + @apply ring-ring ring-offset-background ring-2 ring-offset-2 outline-hidden; } } diff --git a/src/shared/styles/globals.test.ts b/src/shared/styles/globals.test.ts index 20dc6bc04..a593a5f72 100644 --- a/src/shared/styles/globals.test.ts +++ b/src/shared/styles/globals.test.ts @@ -35,6 +35,30 @@ describe("text shimmer motion", () => { }); }); +describe("global focus ring", () => { + // Tailwind v4.3.3 drops the whole parent selector when a `*`-led selector + // like `*:not(body):not(.focus-override)` uses `&` nesting, compiling it to a + // bare `:focus-visible` that matches every element. Keep these rules + // flattened until the upstream Tailwind bug is fixed. + it("keeps focus-visible selectors flattened", () => { + const cssWithoutVariantDefinitions = globalsCss + .split("\n") + .filter((line) => !line.trimStart().startsWith("@custom-variant")) + .join("\n"); + + expect(cssWithoutVariantDefinitions).not.toMatch(/^\s*&/m); + expect(globalsCss).toContain( + "*:not(body):not(.focus-override):focus-visible {", + ); + expect(globalsCss).toContain( + '[data-slot="menubar-sub-trigger"]\n ):focus-visible {', + ); + expect(globalsCss).toContain( + "*:not(body):not(.focus-override).link:focus-visible {", + ); + }); +}); + describe("card-glass surface", () => { it("derives the glass panel fill from the card token in both themes", () => { const lightTheme = declarationsFor(":root {");