Skip to content

Selector: the overlay menu covers its own trigger — clicking it commits the option on top instead of closing #5004

Description

@cixzhang

What happens

With the default (selected-item overlay) placement, Selector's open menu is positioned on top of its own trigger — that is the point of the overlay. The consequence is that the trigger is no longer clickable: a click at the trigger's own coordinates lands on whichever option is painted over it, and that option is committed as the value.

Hit-testing the trigger of an open, default Selector in Chrome 151 (document.elementFromPoint at the trigger's top edge, centre, and bottom edge) returns an option inside the popover in every case, and clicking there changes the value:

story value before click the trigger value after
Core/Selector → Default (placeholder state) Select a fruit… hits option Apple Apple
Core/Selector → With Status (placeholder state) Select a fruit… hits option Apple Apple
Core/Selector → Pre-Selected Banana hits option Banana Banana

So a form that has never been touched can be given a value by a user who was only trying to dismiss the menu — and the menu closes at the same time, which makes it read as an ordinary dismissal. The placeholder state is the one every form starts in.

Two more consequences of the same geometry:

  • There is no click-to-close. Every "click the button again to close it" gesture is a selection instead. (Playwright's actionability check refuses the click outright — <div popover> subtree intercepts pointer events — on Default, Clearable, Ghost Variant, Hidden Label, With Description, Pre-Selected and Size Variants.)
  • WCAG 2.4.11 (Focus Not Obscured). The trigger keeps DOM focus while the menu is open — Selector deliberately does not move focus into the listbox — and the menu covers it.

What is not broken

The trigger toggles correctly in every non-overlay mode. Verified on main and on the #4976 preview, in Chrome 151 and WebKit, with mouse (instant and 120 ms hold) and with touch: placement="above", placement="below", hasSearch, and MultiSelector all close on a second trigger click. The light-dismiss toggle event is queued and always arrives after the trigger's click, so the "closed by light dismiss, then re-opened by the click" race that DropdownMenu and Popover guard against with a 50 ms window does not fire on desktop here.

Fix

#4976 removes this by flipping the default placement to below. If the overlay survives as opt-in (hasSelectedItemOverlay), it needs its own answer for click-to-close and for 2.4.11 — a native <select> gets this right only because the platform popup swallows the whole gesture.

Related: #4227.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions