From e06809e42ea0a134a7da38711907cdad50f222e4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 21 Jul 2026 14:36:26 +0000
Subject: [PATCH 1/2] Extract Autocomplete blur behavior fix and test from
#7644
Co-authored-by: iansan5653 <2294248+iansan5653@users.noreply.github.com>
---
.../src/Autocomplete/Autocomplete.test.tsx | 24 +++++++++++++++++++
.../src/Autocomplete/AutocompleteInput.tsx | 18 ++++++++++----
2 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/packages/react/src/Autocomplete/Autocomplete.test.tsx b/packages/react/src/Autocomplete/Autocomplete.test.tsx
index 054a9b52e0a..ac92ef3c7ae 100644
--- a/packages/react/src/Autocomplete/Autocomplete.test.tsx
+++ b/packages/react/src/Autocomplete/Autocomplete.test.tsx
@@ -180,6 +180,30 @@ describe('Autocomplete', () => {
await waitFor(() => expect(inputNode.getAttribute('aria-expanded')).not.toBe('true'))
})
+ it('keeps the menu open when focus moves into the menu', async () => {
+ const {getByRole} = render(
+ ,
+ )
+ const inputNode = getByRole('combobox')
+
+ expect(inputNode.getAttribute('aria-expanded')).not.toBe('true')
+ fireEvent.click(inputNode)
+ fireEvent.keyDown(inputNode, {key: 'ArrowDown'})
+
+ expect(inputNode.getAttribute('aria-expanded')).toBe('true')
+
+ // Blurring the input while focus moves into the menu should not close the menu, e.g. when
+ // the user clicks an option in the menu. The blur handler relies on `relatedTarget` to
+ // detect this rather than the input's ref, so it works regardless of how the ref is wired up.
+ const menu = getByRole('listbox')
+ // eslint-disable-next-line github/no-blur
+ fireEvent.blur(inputNode, {relatedTarget: menu})
+
+ await waitFor(() => expect(inputNode.getAttribute('aria-expanded')).toBe('true'))
+ })
+
it('sets the input value to the suggested item text and highlights the untyped part of the word', async () => {
const user = userEvent.setup()
const {container, getByDisplayValue} = render(
diff --git a/packages/react/src/Autocomplete/AutocompleteInput.tsx b/packages/react/src/Autocomplete/AutocompleteInput.tsx
index f7622d7013a..e60f7af19b2 100644
--- a/packages/react/src/Autocomplete/AutocompleteInput.tsx
+++ b/packages/react/src/Autocomplete/AutocompleteInput.tsx
@@ -58,11 +58,19 @@ const AutocompleteInput = React.forwardRef(
event => {
onBlur && onBlur(event)
- // HACK: wait a tick and check the focused element before hiding the autocomplete menu
- // this prevents the menu from hiding when the user is clicking an option in the Autoselect.Menu,
- // but still hides the menu when the user blurs the input by tabbing out or clicking somewhere else on the page
+ // HACK: wait a tick before hiding the menu so click interactions can complete.
+ // Use the blur event's relatedTarget to determine whether focus is moving into the
+ // autocomplete menu; if not, hide the menu when focus leaves the input. Relying on
+ // relatedTarget instead of `document.activeElement` makes this robust regardless of how
+ // the input's ref is wired up.
safeSetTimeout(() => {
- if (document.activeElement !== inputRef.current) {
+ const nextFocusedElement = event.relatedTarget as Node | null
+ const menuElement = document.getElementById(`${id}-listbox`)
+
+ if (
+ !nextFocusedElement ||
+ (nextFocusedElement !== menuElement && !menuElement?.contains(nextFocusedElement))
+ ) {
setShowMenu(false)
// Reset the input's value to the text the user actually typed rather than leaving the
@@ -75,7 +83,7 @@ const AutocompleteInput = React.forwardRef(
}
}, 0)
},
- [onBlur, setShowMenu, inputRef, safeSetTimeout, autocompleteSuggestion, inputValue],
+ [onBlur, setShowMenu, inputRef, safeSetTimeout, autocompleteSuggestion, inputValue, id],
)
const handleInputChange: ChangeEventHandler = event => {
From 64f9a95189160768aa5736692bb087a40fbf55ff Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 21 Jul 2026 14:38:11 +0000
Subject: [PATCH 2/2] Add changeset for Autocomplete blur fix
Co-authored-by: iansan5653 <2294248+iansan5653@users.noreply.github.com>
---
.changeset/autocomplete-blur-related-target.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/autocomplete-blur-related-target.md
diff --git a/.changeset/autocomplete-blur-related-target.md b/.changeset/autocomplete-blur-related-target.md
new file mode 100644
index 00000000000..beb635179e4
--- /dev/null
+++ b/.changeset/autocomplete-blur-related-target.md
@@ -0,0 +1,5 @@
+---
+'@primer/react': patch
+---
+
+Autocomplete: the input's blur handler now uses the blur event's `relatedTarget` to decide whether to close the menu, so the menu reliably stays open when focus moves into it and closes when focus leaves.