Skip to content

fix(web): keep the ring border on focused overlays - #59

Merged
imneov merged 1 commit into
modelsphere:mainfrom
imneov:fix/popup-ring-border
Oct 13, 2026
Merged

imneov merged 1 commit into
modelsphere:mainfrom
imneov:fix/popup-ring-border

Conversation

@imneov

@imneov imneov commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • bug fix
  • feature
  • cleanup / refactor (no behaviour change)
  • documentation
  • install / chart
  • CI / tooling
  • breaking: API, config key, chart value, or CRD field changed

What this PR does and why

The site-wide no-focus-ring rule in web/packages/ui/styles/base.css zeroes --tw-ring-shadow on any focused element. [data-slot='card'] was excluded because a card's ring-1 is its border, not a focus ring. Overlay shells are the same case and were missed: menus, popovers, selects, comboboxes and dialogs have no border — bg-popover + ring-1 ring-foreground/10 is their edge — and Base UI moves focus to the shell when it opens (dropdown-menu-content carries tabindex="-1"). So the edge was wiped exactly while the panel was on screen: a white panel on the white page kept only a faint shadow, and the top-bar avatar menu read as a line of text floating under the header.

The exclusion now covers container surfaces by their naming convention (data-slot ending in -content) next to card, so a new overlay cannot regress the same way. Nothing else changes: form controls still get their focus ring suppressed (that is the deliberate decision this rule exists for), and card behaves as before.

Which issue(s) this PR fixes

Fixes #58

How it was tested

  • web/: npm run typecheck, npm test (272 passed, 31 files), vite build — all on this branch.
  • Loaded the built bundle in the live preview and measured the open menu:
    • before: --tw-ring-shadow: 0 0 #0000 while document.activeElement is the popup;
    • after: --tw-ring-shadow: 0 0 0 1px <--tw-ring-color> and box-shadow contains oklab(0.145 0 0 / 0.1) 0 0 0 1px, with the popup rect unchanged (128×32 at the same position).
  • Regression probes on the same page: a focused <input class="ring-2 ring-ring"> still computes --tw-ring-shadow: 0 0 #0000, and a [data-slot='card'] with ring-2 still computes 0 0 0 2px — both unchanged.
  • Screenshots (top-right, before / after) reviewed during the session; before shows only the label with no edge, after shows the 1px panel border.

Checks

  • go test ./... and gofmt -l . is empty
  • npm run typecheck && npm test && npm run build in web/ (if web/ changed)
  • helm lint --strict helm/console (if the chart changed)
  • Docs updated where behaviour, a config key or a chart value moved
  • No internal hostnames, IPs, registries or credentials

Notes for reviewers

One file of CSS plus a CHANGELOG line. The *-content suffix is the design-system convention for an overlay shell (dropdown-menu-content, popover-content, select-content, combobox-content, dialog-content, alert-dialog-content, dropdown-menu-sub-content); tabs-content / tooltip-content / empty-content come along for the ride, which is harmless — no form control ends in -content.

The focus-visible:ring-2 on ResourceTable rows stays suppressed by this rule as it is today; if rows should show a focus ring again, that is a separate decision (the rule is the site-wide "no focus ring" call, WCAG 2.4.7 traded deliberately).

Release note

Overlay menus, popovers, selects, comboboxes and dialogs keep their 1px border while open; it was being erased by the site-wide no-focus-ring rule, which left a white panel on a white page looking like floating text.

The site-wide "no focus ring" rule zeroes --tw-ring-shadow on any focused
element. Card was excluded for this in September, because its ring-1 is the
border, not a focus ring. Overlay shells are the same case and were missed:
menus, popovers, selects, comboboxes and dialogs have no border — bg-popover
plus ring-1 is their edge — and Base UI hands focus to the shell when it opens
(dropdown-menu-content carries tabindex="-1"). The edge vanished the moment
they opened, leaving a white panel on the white page with only a faint shadow:
the top-bar avatar menu looked like a line of text floating under the header.

Excluding container surfaces by their naming convention (data-slot ending in
-content) keeps the decision in one place and stops the next overlay from
regressing the same way. Form controls still lose the focus ring.
@imneov
imneov merged commit 4622bf9 into modelsphere:main Oct 13, 2026
4 checks passed
@imneov
imneov deleted the fix/popup-ring-border branch October 13, 2026 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

shell: overlay menus lose their border when they open

1 participant