Skip to content

🐛 fix: stop the Select reopening when a Drawer or Modal returns focus - #686

Merged
futjesus merged 1 commit into
mainfrom
fix/select-reopen-on-focus-return
Jul 27, 2026
Merged

🐛 fix: stop the Select reopening when a Drawer or Modal returns focus#686
futjesus merged 1 commit into
mainfrom
fix/select-reopen-on-focus-return

Conversation

@futjesus

Copy link
Copy Markdown
Member

What

Stops the Select from reopening its listbox when a Drawer or Modal returns focus to the combobox, and moves opening to explicit keyboard intent.

  • useSelect no longer opens the list from a focusin whose target matches :focus-visible.
  • The combobox gets an onKeyDown: ArrowDown opens and, once open, moves focus to the first option; Enter/Space toggle it, but only while the combobox itself holds focus.
  • Both imperative addEventListener calls in useSelect are consolidated into that React handler, where isOpen can never be stale.

Why

0.1.2-alpha.104 wrapped the Modal and Drawer panels in react-focus-lock (#672). That made every Select inside them unusable:

  1. Clicking an option focuses the <li>.
  2. toggleOpen(false) unmounts the list, so the focused element disappears.
  3. The focus lock returns focus into the panel — the div[role="combobox"].
  4. That fired the focusin listener which opened the list whenever the target matched :focus-visible.

The list reopened immediately and covered every field below it, so the form could not be filled in at all. Verified in a real browser (see below).

Opening on focus was wrong regardless of the focus lock: per the ARIA select-only combobox pattern, focus alone must not expand the listbox — ArrowDown, Enter and Space are the open keys. Keeping Enter/Space scoped to event.target === event.currentTarget means both keys still reach the search input of a searchable Select.

Testing

  • vitest run — 574/574 pass.
  • npm run check:types, npm run lint, prettier --check — clean.
  • 6 new tests in Select.test.tsx. The 4 keyboard-open ones fail on main and pass here (confirmed by stashing only the source changes), plus one asserting focus alone does not expand and one for a Select inside a Drawer.
  • Real-browser check with this branch built and dropped into civo/dashboard/dns-micro-frontend (whose add-record Cypress spec is what surfaced the bug): e2e 13/13 (was 12/13) and visual regression 8/8, including the domain-records-after-create snapshot.

Worth noting: jsdom returns false for matches(':focus-visible') on every element, so the focusin branch was dead code under unit tests. That is why the existing "should close select list after selecting an option in modal" test stayed green while the behaviour was broken in real browsers.

Wrapping the Modal and Drawer panels in react-focus-lock (0.1.2-alpha.104)
made the Select unusable inside them. Clicking an option focuses the `<li>`,
the list then unmounts, and the focus lock returns focus to the combobox —
which fired the `focusin` listener that opened the list whenever the target
matched `:focus-visible`. The list reopened immediately and covered every
field below it, so the form could not be filled in at all.

Opening on focus was wrong regardless of the focus lock: per the ARIA
select-only combobox pattern, focus alone must not expand the listbox. It is
replaced with explicit keyboard intent on the combobox — ArrowDown opens and,
once open, moves to the first option; Enter and Space toggle it, but only
while the combobox itself holds focus, so both keys still reach the search
input of a searchable Select.

Both imperative listeners in `useSelect` are consolidated into a React
`onKeyDown`, where `isOpen` can never be stale.

jsdom reports `false` for `:focus-visible` on every element, which is why the
existing "closes after selecting an option in modal" test stayed green while
the behaviour was broken in real browsers. The new tests cover the keyboard
open paths and the drawer focus-return.
@futjesus
futjesus merged commit 1c7685c into main Jul 27, 2026
2 checks passed
@futjesus
futjesus deleted the fix/select-reopen-on-focus-return branch July 27, 2026 19:07
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.

1 participant