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 {");