From c8aca8d3a0d18b86416ca1a8bf3e5f42fcd67bef Mon Sep 17 00:00:00 2001 From: Danny White <3104761+dnywh@users.noreply.github.com> Date: Wed, 22 Jul 2026 12:10:07 -0400 Subject: [PATCH] chore(design-system): standardise keyboard focus rings (#41575) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? UI / design-system consistency (accessibility). ## What is the current behavior? Keyboard focus rings are inconsistent across Studio and `packages/ui`: - Custom Button uses thick `outline` with per-variant colours (brand / grey / destructive / warning) - Form controls use muted grey rings (`ring-background-control`) - Tabs / NavMenu / Radio use soft brand `ring-ring` - Studio `.inset-focus` uses dark green `outline-brand-600` Related: [DEPR-354](https://linear.app/supabase/issue/DEPR-354). ## What is the new behavior? One shared focus recipe, exposed as Tailwind `@utility` classes in `packages/config/css/utilities.css`: | Utility | Use when | | --- | --- | | `focus-ring` | Buttons, inputs, most controls (offset ring) | | `focus-inset` | Dense/flush surfaces such as interactive table rows (renamed from `inset-focus`) | ```txt # focus-ring outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background ``` Applied on Button, shadcn form controls, Menu/NavMenu, Command palette trigger, Studio table rows, and related call sites. Documented in the design-system accessibility docs. Variants do not change focus ring colour. When the ring must appear on a different element than the focused one (e.g. Menu + ProductMenu `Link` via `group-focus-visible`, or InputGroup via `:has()`), keep an explicit ring stack. The utilities bake in `:focus-visible` on the same element. ## Additional context **Out of scope** - Full `packages/ui` / Studio / www sweep - Legacy Studio form-group green box-shadow cleanup - ESLint rule for bare `outline-none` ## Test plan Prefer Safari (“hard mode” for `tabIndex`). Expect one soft brand ring everywhere: not grey, not solid green outline. ### Design system - [ ] [Accessibility](https://design-system-git-dnywh-choreimprove-tab-focus-styles-supabase.vercel.app/design-system/docs/accessibility): recipe docs match what you see - [ ] [Button](https://design-system-git-dnywh-choreimprove-tab-focus-styles-supabase.vercel.app/design-system/docs/components/button): Tab primary / default / danger; same ring colour - [ ] [Table → Row-level navigation](https://design-system-git-dnywh-choreimprove-tab-focus-styles-supabase.vercel.app/design-system/docs/components/table#row-level-navigation): Tab an interactive row; inset outline (`focus-inset`) sits inside the row ### Studio - [ ] **Org home → table view** (`/organizations/_` or org projects): switch to the table layout, Tab onto a project row; inset outline sits inside the row (list/card view uses CardButton, not `focus-inset`) - [ ] **Project sidebar** (Database, Auth, Storage, …): Tab the main product nav links; ring follows the focused item (not the nested section menus like Tables / Roles) - [ ] **Storage → Files**: Tab a bucket row; same inset outline as org table rows - [ ] **Project Settings → General** (or Compute and Disk): Tab through inputs, checkboxes, switches, selects; same offset ring, no ring on mouse click - [ ] **Header ⌘K** (desktop width): Tab to the search control after Feedback; same soft brand `focus-ring` (was a thicker `ring-border-strong` before) - [ ] **Table Editor or SQL Editor tabs**: focus a tab, Tab to × if active; close shows a ring - [ ] **Light + dark**: ring stays visible against both backgrounds --- .../content/docs/accessibility.mdx | 60 ++++++++++++++++++- .../content/docs/components/button.mdx | 1 + .../content/docs/components/table.mdx | 2 +- .../example/table-row-link-actions.tsx | 2 +- .../default/example/table-row-link.tsx | 2 +- .../Functions/EdgeFunctionsListItem.tsx | 2 +- .../Home/ProjectList/ProjectTableRow.tsx | 2 +- .../PlatformWebhooksEndpointDetails.tsx | 2 +- .../Webhooks/PlatformWebhooksEndpointList.tsx | 2 +- .../JitDbAccessRulesTable.tsx | 2 +- .../Storage/AnalyticsBuckets/index.tsx | 2 +- .../BucketsPickerDialog/BucketTableRow.tsx | 2 +- .../Storage/FilesBuckets/BucketTable.tsx | 2 +- .../Storage/VectorBuckets/index.tsx | 2 +- .../ProjectNeedsSecuringView.tsx | 2 +- .../components/layouts/Tabs/SortableTab.tsx | 2 +- apps/studio/components/layouts/Tabs/Tabs.tsx | 2 +- .../DataTableFilterCheckbox.tsx | 2 +- .../DataTableFilterCheckboxAsync.tsx | 2 +- .../ui/DataTable/DataTableSheetRowAction.tsx | 7 +-- .../ui/DataTable/primitives/Slider.tsx | 2 +- .../ui/ProductMenu/ProductMenuItem.tsx | 2 +- apps/studio/pages/_app.tsx | 1 - apps/studio/routes/__root.tsx | 1 - apps/studio/styles/focus.css | 6 -- packages/config/css/utilities.css | 26 ++++++++ .../src/CommandMenu/api/CommandMenu.tsx | 7 ++- .../src/multi-select/multi-select.tsx | 2 +- packages/ui/src/components/Button/Button.tsx | 27 +-------- packages/ui/src/components/Menu/Menu.tsx | 8 ++- packages/ui/src/components/NavMenu/index.tsx | 2 +- .../ui/src/components/radio-group-card.tsx | 4 +- .../ui/src/components/shadcn/ui/button.tsx | 2 +- .../ui/src/components/shadcn/ui/checkbox.tsx | 2 +- .../src/components/shadcn/ui/input-group.tsx | 5 +- .../ui/src/components/shadcn/ui/input.tsx | 2 +- .../src/components/shadcn/ui/radio-group.tsx | 2 +- .../ui/src/components/shadcn/ui/select.tsx | 2 +- .../ui/src/components/shadcn/ui/slider.tsx | 2 +- .../ui/src/components/shadcn/ui/switch.tsx | 2 +- packages/ui/src/components/shadcn/ui/tabs.tsx | 11 +--- .../ui/src/components/shadcn/ui/text-area.tsx | 2 +- .../ui/src/components/shadcn/ui/textarea.tsx | 2 +- .../ui/src/components/shadcn/ui/toggle.tsx | 2 +- packages/ui/src/lib/commonCva.ts | 11 ---- 45 files changed, 136 insertions(+), 101 deletions(-) delete mode 100644 apps/studio/styles/focus.css diff --git a/apps/design-system/content/docs/accessibility.mdx b/apps/design-system/content/docs/accessibility.mdx index a549d1eb7b6..0d71788abac 100644 --- a/apps/design-system/content/docs/accessibility.mdx +++ b/apps/design-system/content/docs/accessibility.mdx @@ -25,14 +25,68 @@ All interactive page elements should be reachable by keyboard. Given the below i Chromium-based browsers and Firefox handle this automatically via the Tab key. Safari, by default, requires the Option key to also be held down. Enabling _Keyboard navigation_ on macOS Settings [removes this requirement](https://mayank.co/blog/safari-focus/#keyboard-navigation) but makes links non-tabbable as a result. -Interactive page elements should also provide visual feedback upon selection via a `focus-visible` state. We use consistent focus styles such as `inset-focus` so users recognize this state instantly. +Interactive page elements should also provide visual feedback upon selection via a `focus-visible` state. We use one shared focus ring so users recognize this state instantly. -[Button](components/button) has all of the above built-in. The same explicit `tabIndex` default is also baked into Checkbox, Switch, Select Trigger, Toggle, Accordion Trigger, Collapsible Trigger, Dropdown Menu Trigger, Popover Trigger, Dialog Trigger, Sheet Trigger, Alert Dialog Trigger, and the Sidebar Menu and action buttons. Bespoke interactive elements however, such as the below interactive [Table Row](components/table#examples), require these props to be added manually: +### Focus ring recipe + +Prefer the shared utilities over inventing local styles: + +| Utility | Use when | +| ------------- | -------------------------------------------------------------------------- | +| `focus-ring` | Buttons, inputs, and most controls (offset **ring**) | +| `focus-inset` | Dense or flush surfaces such as interactive table rows (inset **outline**) | + +```tsx +className = 'focus-ring' +// or +className = 'relative cursor-pointer focus-inset' +``` + +These expand to: + +**`focus-ring`** + +```txt +outline-hidden +focus-visible:ring-2 +focus-visible:ring-ring +focus-visible:ring-offset-2 +focus-visible:ring-offset-background +``` + +**`focus-inset`** + +Uses `outline` (not `ring`) so it paints reliably on interactive ``s. Tailwind `ring` is `box-shadow`, which browsers often skip on `display: table-row` (notably Safari). Do not put `focus-ring` or raw `ring-*` on a ``, and do not add `outline-hidden` alongside `focus-inset`. `outline-hidden` sets `outline-style: none` and will hide the indicator. + +```txt +&:focus-visible { + outline-style: solid + outline-width: 2px + outline-offset: -2px + outline-color: var(--ring) + border-radius: var(--radius-md) +} +``` + +`outline-hidden` is always on (not `focus-visible:`-prefixed) so mouse click does not show the browser’s default outline; the focus indicator replaces it for keyboard focus only. + +Rules: + +- Prefer `:focus-visible` over `:focus` so click/tap does not show a focus indicator +- Never use `outline-none` / `outline-hidden` without a ring or outline replacement +- Always use the shared color (`ring-ring` / `outline-ring`). Variants (primary, danger, warning) do not change focus colour +- Do not animate the focus indicator; avoid `transition-all` / `transition` on controls that show one (prefer `transition-colors`) +- Prefer `focus-ring` / `focus-inset` over copy-pasting the class stack +- On interactive ``s, use `focus-inset` only. `focus-ring` will look fine in some browsers and invisible in others + +When the focused element is not the thing that should show the ring (e.g. a wrapping `Link` with `group`, or an `InputGroup` parent using `:has()`), keep the explicit `group-focus-visible:ring-*` / `has-[…]:focus-visible:ring-*` stack. The utilities bake in `:focus-visible` on the same element and do not compose as `group-focus-visible:focus-ring`. + +[Button](components/button) has focus, `tabIndex`, and the shared ring built-in. The same explicit `tabIndex` default is also baked into Checkbox, Switch, Select Trigger, Toggle, Accordion Trigger, Collapsible Trigger, Dropdown Menu Trigger, Popover Trigger, Dialog Trigger, Sheet Trigger, Alert Dialog Trigger, and the Sidebar Menu and action buttons. Bespoke interactive elements however, such as the below interactive [Table Row](components/table#examples), require these props to be added manually: ```tsx showLineNumbers {4-14} { if (event.currentTarget !== event.target) return handleBucketNavigation(bucket.id, event) diff --git a/apps/design-system/content/docs/components/button.mdx b/apps/design-system/content/docs/components/button.mdx index 43afbfad43f..ffa96da53df 100644 --- a/apps/design-system/content/docs/components/button.mdx +++ b/apps/design-system/content/docs/components/button.mdx @@ -144,5 +144,6 @@ Inside [Admonition](../fragments/admonition#split-button-with-dropdown) actions, - Enabled buttons default to `tabIndex={0}` (keyboard accessible) - Disabled buttons default to `tabIndex={-1}` (removed from tab order) - You can still override with an explicit `tabIndex` prop when needed +- Keyboard focus uses the shared `focus-ring` utility; variants do not change ring colour You therefore don't need to manually set `tabIndex`, as Button handles it automatically based on its `disabled` state. diff --git a/apps/design-system/content/docs/components/table.mdx b/apps/design-system/content/docs/components/table.mdx index f25a80fe12f..d0ab5ccb536 100644 --- a/apps/design-system/content/docs/components/table.mdx +++ b/apps/design-system/content/docs/components/table.mdx @@ -221,7 +221,7 @@ Avoid adding other actions when using row-level navigation, as multiple interact When implementing row-level navigation, pay close attention to [Accessibility](/accessibility#focus-management) requirements. The row must be keyboard accessible with proper focus management. Also consider these affordances: - Handle `Enter` and `Space` key presses for activation -- Provide visual focus indicators using classes like `inset-focus` +- Provide visual focus indicators using classes like `focus-inset` - Support modifier keys (`Ctrl`/`Cmd`, middle-click) for opening links in new tabs - Consider using the shared `createNavigationHandler` function to handle modifier keys - Avoid bubbling up action events from _within_ the row diff --git a/apps/design-system/registry/default/example/table-row-link-actions.tsx b/apps/design-system/registry/default/example/table-row-link-actions.tsx index 7e744df1b89..5e366aec446 100644 --- a/apps/design-system/registry/default/example/table-row-link-actions.tsx +++ b/apps/design-system/registry/default/example/table-row-link-actions.tsx @@ -70,7 +70,7 @@ export default function TableRowLinkActions() { {policies.map((policy) => ( { if (event.currentTarget !== event.target) return handlePolicyNavigation(policy.id, event) diff --git a/apps/design-system/registry/default/example/table-row-link.tsx b/apps/design-system/registry/default/example/table-row-link.tsx index be4716eff24..25850a88203 100644 --- a/apps/design-system/registry/default/example/table-row-link.tsx +++ b/apps/design-system/registry/default/example/table-row-link.tsx @@ -54,7 +54,7 @@ export default function TableRowLink() { {buckets.map((bucket) => ( { if (event.currentTarget !== event.target) return handleBucketNavigation(bucket.id, event) diff --git a/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx b/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx index 470e5620f97..db84ba3159e 100644 --- a/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx +++ b/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx @@ -62,7 +62,7 @@ export const EdgeFunctionsListItem = ({ function: item }: EdgeFunctionsListItemP onAuxClick={handleNavigation} onKeyDown={handleNavigation} tabIndex={0} - className="cursor-pointer inset-focus" + className="cursor-pointer focus-inset" >

{item.name}

diff --git a/apps/studio/components/interfaces/Home/ProjectList/ProjectTableRow.tsx b/apps/studio/components/interfaces/Home/ProjectList/ProjectTableRow.tsx index a8e20c56d36..967a4a252fb 100644 --- a/apps/studio/components/interfaces/Home/ProjectList/ProjectTableRow.tsx +++ b/apps/studio/components/interfaces/Home/ProjectList/ProjectTableRow.tsx @@ -75,7 +75,7 @@ export const ProjectTableRow = ({ return ( <> ( onOpenDelivery(row.original.id)} onKeyDown={(event) => { if (event.key === 'Enter' || event.key === ' ') { diff --git a/apps/studio/components/interfaces/Platform/Webhooks/PlatformWebhooksEndpointList.tsx b/apps/studio/components/interfaces/Platform/Webhooks/PlatformWebhooksEndpointList.tsx index 766c1997268..732202461f9 100644 --- a/apps/studio/components/interfaces/Platform/Webhooks/PlatformWebhooksEndpointList.tsx +++ b/apps/studio/components/interfaces/Platform/Webhooks/PlatformWebhooksEndpointList.tsx @@ -170,7 +170,7 @@ export const PlatformWebhooksEndpointList = ({ return ( { diff --git a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/index.tsx b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/index.tsx index ef3505c7b2e..92c594863c3 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticsBuckets/index.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticsBuckets/index.tsx @@ -154,7 +154,7 @@ export const AnalyticsBuckets = () => { return ( td]:hover:bg-transparent cursor-not-allowed' )} onClick={handleRowActivate} diff --git a/apps/studio/components/interfaces/Storage/FilesBuckets/BucketTable.tsx b/apps/studio/components/interfaces/Storage/FilesBuckets/BucketTable.tsx index 8fc7e89519e..5ce3d537792 100644 --- a/apps/studio/components/interfaces/Storage/FilesBuckets/BucketTable.tsx +++ b/apps/studio/components/interfaces/Storage/FilesBuckets/BucketTable.tsx @@ -107,7 +107,7 @@ export const BucketTableRow = ({ { return ( { trackViewPolicies() handleNavigation(event) diff --git a/apps/studio/components/layouts/Tabs/SortableTab.tsx b/apps/studio/components/layouts/Tabs/SortableTab.tsx index 23240722b91..c66a3a003a1 100644 --- a/apps/studio/components/layouts/Tabs/SortableTab.tsx +++ b/apps/studio/components/layouts/Tabs/SortableTab.tsx @@ -158,7 +158,7 @@ export const SortableTab = ({ 'absolute top-1/2 right-2.5 z-10 -translate-y-1/2', 'flex size-5 items-center justify-center rounded-xs', 'opacity-0 group-hover/tab:opacity-100 group-focus-within/tab:opacity-100 focus-visible:opacity-100', - 'hover:bg-200 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background', + 'hover:bg-200 focus-ring', 'cursor-pointer' )} > diff --git a/apps/studio/components/layouts/Tabs/Tabs.tsx b/apps/studio/components/layouts/Tabs/Tabs.tsx index 72b06e913ac..9ee549892b3 100644 --- a/apps/studio/components/layouts/Tabs/Tabs.tsx +++ b/apps/studio/components/layouts/Tabs/Tabs.tsx @@ -259,7 +259,7 @@ export const EditorTabs = () => { className={cn( 'absolute top-1/2 right-3 z-10 flex -translate-y-1/2 items-center justify-center rounded-xs', 'opacity-0 group-hover/new-tab:opacity-100 group-focus-within/new-tab:opacity-100 focus-visible:opacity-100', - 'hover:bg-200 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background', + 'hover:bg-200 focus-ring', 'cursor-pointer' )} > diff --git a/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterCheckbox.tsx b/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterCheckbox.tsx index 01d5f1d1967..2ce56bf564b 100644 --- a/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterCheckbox.tsx +++ b/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterCheckbox.tsx @@ -153,7 +153,7 @@ export function DataTableFilterCheckbox({ className={cn( 'text-xs text-muted-foreground hover:text-foreground', 'absolute inset-y-0 right-0 hidden bg-surface-100 group-hover:flex group-focus-within:flex items-center cursor-pointer', - 'ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2' + 'focus-ring' )} > Only diff --git a/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterCheckboxAsync.tsx b/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterCheckboxAsync.tsx index a8ba1cea405..6b44f955cdf 100644 --- a/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterCheckboxAsync.tsx +++ b/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterCheckboxAsync.tsx @@ -123,7 +123,7 @@ export function DataTableFilterCheckboxAsync({ className={cn( 'text-xs text-muted-foreground hover:text-foreground', 'absolute inset-y-0 right-0 hidden bg-surface-100 group-hover:flex group-focus-within:flex items-center cursor-pointer', - 'ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2' + 'focus-ring' )} > Only diff --git a/apps/studio/components/ui/DataTable/DataTableSheetRowAction.tsx b/apps/studio/components/ui/DataTable/DataTableSheetRowAction.tsx index d832a349511..207f4dc9687 100644 --- a/apps/studio/components/ui/DataTable/DataTableSheetRowAction.tsx +++ b/apps/studio/components/ui/DataTable/DataTableSheetRowAction.tsx @@ -187,12 +187,7 @@ export function DataTableSheetRowAction { if (e.key === 'ArrowDown') { // REMINDER: default behavior is to open the dropdown menu diff --git a/apps/studio/components/ui/DataTable/primitives/Slider.tsx b/apps/studio/components/ui/DataTable/primitives/Slider.tsx index a5ab8302b15..c3b0cec7aae 100644 --- a/apps/studio/components/ui/DataTable/primitives/Slider.tsx +++ b/apps/studio/components/ui/DataTable/primitives/Slider.tsx @@ -22,7 +22,7 @@ export const Slider = forwardRef< {initialValue.map((_, index) => ( - + ))} diff --git a/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx b/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx index a1c2ecb786a..26ee2b57cbf 100644 --- a/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx +++ b/apps/studio/components/ui/ProductMenu/ProductMenuItem.tsx @@ -85,7 +85,7 @@ export const ProductMenuItem = ({ } const link = ( - + {menuItem} ) diff --git a/apps/studio/pages/_app.tsx b/apps/studio/pages/_app.tsx index b4559f72dbd..f7b7474a307 100644 --- a/apps/studio/pages/_app.tsx +++ b/apps/studio/pages/_app.tsx @@ -1,5 +1,4 @@ import '@/styles/code.css' -import '@/styles/focus.css' import '@/styles/globals.css' import '@/styles/graphiql-base.css' import '@/styles/grid.css' diff --git a/apps/studio/routes/__root.tsx b/apps/studio/routes/__root.tsx index a8b53eb521b..1e5542d5c7f 100644 --- a/apps/studio/routes/__root.tsx +++ b/apps/studio/routes/__root.tsx @@ -2,7 +2,6 @@ import 'react-data-grid/lib/styles.css' import '@/styles/code.css' -import '@/styles/focus.css' // Vite-only: defines @font-face for the custom fonts. The Next pipeline // (pages/_app.tsx) loads these via next/font instead, so this import has no // counterpart there — but dropping it under Vite makes the browser fall back diff --git a/apps/studio/styles/focus.css b/apps/studio/styles/focus.css deleted file mode 100644 index 605031f36d1..00000000000 --- a/apps/studio/styles/focus.css +++ /dev/null @@ -1,6 +0,0 @@ -@reference "./globals.css"; - -/* Focus styles for keyboard navigation on interactive table rows */ -.inset-focus { - @apply ease-out duration-100 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-brand-600 focus-visible:rounded-md transition-all; -} diff --git a/packages/config/css/utilities.css b/packages/config/css/utilities.css index 7ea8e9d28a1..473245def85 100644 --- a/packages/config/css/utilities.css +++ b/packages/config/css/utilities.css @@ -180,3 +180,29 @@ -webkit-text-fill-color: currentColor; } } + +/* + * Canonical keyboard focus rings. Prefer these over inventing local ring/outline + * stacks. + * + * - focus-ring: default offset ring (buttons, inputs, most controls). + * `outline-hidden` stays always-on so mouse click does not show the browser + * default; the ring is `:focus-visible` only. + * - focus-inset: dense/flush surfaces such as interactive s. Must use + * outline (not ring/box-shadow) — box-shadow on table-row is unreliable, + * especially in Safari. Do NOT pair with outline-hidden: that sets + * outline-style: none and suppresses the focus outline. + */ +@utility focus-ring { + @apply outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background; +} + +@utility focus-inset { + &:focus-visible { + outline-style: solid; + outline-width: 2px; + outline-offset: -2px; + outline-color: var(--ring); + border-radius: var(--radius-md, 0.375rem); + } +} diff --git a/packages/ui-patterns/src/CommandMenu/api/CommandMenu.tsx b/packages/ui-patterns/src/CommandMenu/api/CommandMenu.tsx index 415350946f8..30fabea2155 100644 --- a/packages/ui-patterns/src/CommandMenu/api/CommandMenu.tsx +++ b/packages/ui-patterns/src/CommandMenu/api/CommandMenu.tsx @@ -160,7 +160,7 @@ function CommandMenuTrigger({ children }: PropsWithChildren) { 'rounded-md border border-input bg-background', 'text-sm', 'hover:bg-accent hover:text-accent-foreground', - 'ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2', + 'focus-ring', 'disabled:pointer-events-none disabled:opacity-50', 'transition-colors', childFromProps.props.className @@ -182,6 +182,7 @@ function CommandMenuTriggerInput({