From c4dfa6f3e4e507e4210ed04016c567bb3443fa11 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Thu, 29 Oct 2026 17:53:45 +0100 Subject: [PATCH] fix: draw the focus outline on plugin kit buttons, fields and switches --- app/(sandbox)/plugin-kit.css | 18 ++++++++++++++++++ lib/__tests__/plugin-ui-kit.test.tsx | 9 +++++++++ lib/plugin-sandbox/ui-kit/components.tsx | 24 ++++++++++++------------ 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/app/(sandbox)/plugin-kit.css b/app/(sandbox)/plugin-kit.css index ff06f66b4..0459e062a 100644 --- a/app/(sandbox)/plugin-kit.css +++ b/app/(sandbox)/plugin-kit.css @@ -74,3 +74,21 @@ color-scheme: dark; } } + +/* The app's focus outline (app/accessibility.css) for the kit's own + elements: a real outline instead of a box-shadow ring, so it also shows in + forced colours. Kit components carry no focus ring of their own. Only + containers focused from script (tabindex="-1" without a control role) skip + it. */ +:is(.bk, .bk *):focus-visible:not([tabindex="-1"]:not(a[href], button, input, select, textarea, [role="button"], [role="menuitem"], [role="option"], [role="tab"], [role="row"], [role="gridcell"], [role="checkbox"], [role="switch"], [role="radio"])) { + outline: 2px solid var(--color-ring) !important; + outline-offset: 2px !important; +} +:is(.bk [role="option"], .bk [role="row"], .bk [role="tab"], .bk .focus-inset, .bk.focus-inset):focus-visible { + outline-offset: -2px !important; +} +@media (forced-colors: active) { + :is(.bk, .bk *):focus-visible { + outline-color: Highlight !important; + } +} diff --git a/lib/__tests__/plugin-ui-kit.test.tsx b/lib/__tests__/plugin-ui-kit.test.tsx index 320878301..aa4b57a02 100644 --- a/lib/__tests__/plugin-ui-kit.test.tsx +++ b/lib/__tests__/plugin-ui-kit.test.tsx @@ -442,4 +442,13 @@ describe('plugin-kit.css', () => { expect(reset).toMatch(/button\.bk/); expect(reset).toMatch(/\.bk button/); }, 60_000); + + it('draws the focus outline on kit controls, since the kit has no focus rings', () => { + const css = readFileSync(path.join(ROOT, 'app/(sandbox)/plugin-kit.css'), 'utf8'); + const rule = css.split('}').find((r) => r.includes(':focus-visible') && /outline:\s*2px solid var\(--color-ring\)/.test(r)); + expect(rule).toBeDefined(); + expect(rule).toMatch(/\.bk \*/); + expect(source('lib/plugin-sandbox/ui-kit/components.tsx')).not.toMatch(/focus(-visible)?:ring/); + expect(source('components/ui/button.tsx')).not.toMatch(/focus(-visible)?:ring/); + }); }); diff --git a/lib/plugin-sandbox/ui-kit/components.tsx b/lib/plugin-sandbox/ui-kit/components.tsx index 18b4cbf5a..c6b76415b 100644 --- a/lib/plugin-sandbox/ui-kit/components.tsx +++ b/lib/plugin-sandbox/ui-kit/components.tsx @@ -134,7 +134,7 @@ export const Textarea = React.forwardRef ); @@ -153,7 +153,7 @@ export function Select({ options, children, onChange, disabled, block = false, c return (