fix(metrics): Prevent metric selector hover from stealing search input focus#111292
Merged
nsdeschenes merged 13 commits intomasterfrom Apr 13, 2026
Merged
Conversation
Contributor
Author
|
@sentry review |
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Autofix Details
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Two items can show focus styling simultaneously
- Replaced
isFocused || isHoveredwithlistState.selectionManager.isFocused && isFocusedto properly coordinate focus styling using the list's focus state as a guard.
- Replaced
- ✅ Fixed: Stale focus persists after mouse leaves hovered item
- Removed redundant
isHoveredstate andonMouseLeavehandler; the proper focus guard now ensures focus styling is cleared when the list loses focus.
- Removed redundant
Or push these changes by commenting:
@cursor push f8f85efef0
Preview (f8f85efef0)
diff --git a/static/app/views/explore/metrics/metricToolbar/metricSelector.tsx b/static/app/views/explore/metrics/metricToolbar/metricSelector.tsx
--- a/static/app/views/explore/metrics/metricToolbar/metricSelector.tsx
+++ b/static/app/views/explore/metrics/metricToolbar/metricSelector.tsx
@@ -597,7 +597,6 @@
}: MetricListBoxOptionProps) {
const ref = useRef<HTMLLIElement>(null);
const option = item.value!;
- const [isHovered, setIsHovered] = useState(false);
const {optionProps, isFocused, isSelected, isDisabled, isPressed} = useOption(
{key: item.key, 'aria-label': option.label},
listState,
@@ -609,9 +608,7 @@
// setFocused(true) triggers a useEffect in useSelectableItem that calls
// focusSafely(ref.current), which would steal DOM focus from the search input.
listState.selectionManager.setFocusedKey(item.key);
- setIsHovered(true);
},
- onMouseLeave: () => setIsHovered(false),
});
return (
@@ -622,7 +619,7 @@
ref={mergeRefs(ref, measureRef)}
size={size}
label={option.label}
- isFocused={isFocused || isHovered}
+ isFocused={listState.selectionManager.isFocused && isFocused}
isSelected={isSelected}
isPressed={isPressed}
disabled={isDisabled}This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
9b9dc89 to
31809c1
Compare
9ba9f2e to
7bc63ea
Compare
k-fish
reviewed
Mar 30, 2026
Member
k-fish
left a comment
There was a problem hiding this comment.
Do we need to hand roll input logic? Doesn't react aria combobox do this?
…t focus When hovering over options in the metric selector listbox, setFocused(true) was triggering a useEffect in useSelectableItem that called focusSafely(ref.current), stealing DOM focus from the search input. Replace setFocused(true) with only setFocusedKey for hover, and track hover state separately so options still get visual focus styling without moving actual DOM focus. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> Made-with: Cursor
…lector Switch to shouldUseVirtualFocus so DOM focus stays on the search input while browsing the metric list. Replace the old useKeyboard-based search handler with a plain onKeyDown callback that drives the selectionManager directly for ArrowDown, ArrowUp, Home, End, and Enter keys. This keeps the search input editable while allowing full keyboard navigation and item selection. Co-Authored-By: Claude Opus <noreply@anthropic.com> Made-with: Cursor
Clear the focused key on close so re-opening the dropdown doesn't show a stale highlight. The selected item remains visually indicated via its selection state instead. Co-Authored-By: Claude Opus <noreply@anthropic.com> Made-with: Cursor
The metric selector now uses virtual focus for keyboard navigation, keeping DOM focus on the search input while ArrowDown moves virtual focus to list options. Update the test assertion accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…h input Home and End keys were intercepted and prevented from propagating to the search input, breaking cursor navigation to the start/end of typed text. Since the input always retains DOM focus via virtual focus, these keys should be passed through to the input element unchanged. Co-Authored-By: Claude Sonnet 4 <noreply@example.com>
Replace useListState + useListBox + manual keyboard handling with the standard useComboBox + useComboBoxState from react-aria. This removes ~40 lines of hand-rolled ArrowDown/ArrowUp/Enter bridging logic and aligns with the combobox pattern used elsewhere in the codebase. Key changes: - useComboBoxState manages collection, selection, and open/close state - useComboBox provides input props with aria-activedescendant, keyboard navigation, and accessibility announcements - useOverlay and useComboBoxState sync open/close via a shared handleOpenChange with a re-entrancy guard - Search input focuses via a ref callback on mount instead of a useEffect - Virtual focus (shouldUseVirtualFocus) passed directly to useOption since useListBox no longer sets it up via listData Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove wrapperRef by using triggerRef and popoverRef from useOverlay for focus management on close. Replace searchRefCallback useMemo with autoFocus on the input. Merge isSyncingOpenStateRef and lastSelectionRef into a single stateGuardRef object. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…with combobox state Remove the stateGuard ref and re-entrant open/close synchronization between useOverlay and useComboBoxState. Instead, pass comboBoxState's isOpen directly to useOverlay and let each hook manage its own state with a simple bridging onOpenChange. Filter duplicate onSelectionChange fires by checking comboBoxState.isOpen. Fixes LOGS-627 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…vert Replace the onClick-based close with toggle() in onSelectionChange to avoid the combobox's commitValue flow re-firing onSelectionChange with the previous key. Remove the now-unnecessary onSelect prop from MetricListBoxOption. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Scroll the listbox back to the top when the overlay opens so users always see the beginning of the metric list. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
87520e8 to
77e8355
Compare
… filter
- Replace scrollTo({top: 0}) with scrollTop = 0 for JSDOM compatibility
- Add defaultFilter: () => true to prevent double-filtering since search
is already handled server-side via useMetricOptions
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
…option When the metric selector overlay is dismissed by clicking outside, the combobox close() method commits the currently highlighted key, spuriously firing onSelectionChange. Use toggle() instead so the dismissal does not alter the selection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
k-fish
approved these changes
Apr 10, 2026
…cemetrics-keep-input-focus-in-metric-selector # Conflicts: # static/app/views/explore/metrics/metricToolbar/metricSelector.spec.tsx
wedamija
pushed a commit
that referenced
this pull request
Apr 13, 2026
…t focus (#111292) This PR refactors the metrics selector from a list state setup over to a combobox state setup. This resolves the issue with the input losing focus, as well as bringing the selector more in line with what we're trying to achieve with it. --------- Co-authored-by: Claude Opus 4 <noreply@anthropic.com> Co-authored-by: Claude Sonnet 4 <noreply@example.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


This PR refactors the metrics selector from a list state setup over to a combobox state setup. This resolves the issue with the input losing focus, as well as bringing the selector more in line with what we're trying to achieve with it.