Fix GlOutsideDirective closing dropdowns on mousedown in Safari

Summary

This MR fixes issue gitlab-org/gitlab#605177 (closed)

Safari doesn't focus <button> elements (and similar non-text controls) on click — it's a long-standing, deliberate WebKit behavior. Instead of focusing the clicked button, Safari blurs whatever was previously focused.

This breaks any GlOutsideDirective-based dropdown/popover that has a focused element inside it (e.g. a searchable listbox's search input) and also contains a <button> action, such as a "Clear"/reset button:

  1. User opens the dropdown; the search input is focused.
  2. User clicks the "Clear" button inside the dropdown.
  3. On mousedown, Safari blurs the search input without focusing the button, moving focus to <body> instead.
  4. That fires a native focusin targeting <body>, which is outside the dropdown's bound element, so GlOutsideDirective's capture-phase focusin listener treats it as an outside interaction and closes the dropdown immediately — before the subsequent click event ever reaches the button.
  5. The button is now gone from the DOM, so its @click handler never runs.

Chrome and Firefox don't hit this because they do focus the button on click, so the resulting focusin targets an element inside the dropdown and is correctly ignored.

Fix

GlOutsideDirective already had a mousedown-based fallback for click events, to handle text selection ending outside the element it started in. This MR extends that same fallback to focusin events: if a focusin follows a mousedown that started inside the bound element, it's treated as an inside interaction, regardless of where the browser decided to move focus.

Also tightened the mousedown listener bookkeeping (now tracked via activeEventTypes) so it's only ever attached/detached once, since it's now shared between the click and focusin paths instead of being tied only to click.

🤖 Generated with Claude Code

Screenshots

before after
Edited by Coung Ngo

Merge request reports

Loading
Loading