Skip to content

Comments

fix(EuiInputPopover): close popover on Tab, not Shift Tab#8950

Merged
weronikaolejniczak merged 6 commits intoelastic:mainfrom
weronikaolejniczak:fix/shift-tab-in-eui-input-popover
Aug 14, 2025
Merged

fix(EuiInputPopover): close popover on Tab, not Shift Tab#8950
weronikaolejniczak merged 6 commits intoelastic:mainfrom
weronikaolejniczak:fix/shift-tab-in-eui-input-popover

Conversation

@weronikaolejniczak
Copy link
Contributor

@weronikaolejniczak weronikaolejniczak commented Aug 7, 2025

Summary

If disableFocusTrap is false, regardless of ownFocus, the active item is the last tabbable item in the EuiInputPopover overlay and if we press Shift + Tab, the popover will close. It's expected to close only on pressing Tab because it will mean circling back to the first tabbable element. But in the other direction, it should not close.

Why are we making this change?

Resolves #8949

This PR comes out of a triage, so I kept the changes to the minimum, only to address the issue that the consumer is struggling with.

That being said, the keyboard navigation in this component feels weird to me. It seems that only some combination of disableTrapFocus and ownFocus produces the expected result. From my perspective, it's best if the keyboard navigation in this component is reworked.

⚠️ I also noticed on Esc nothing happens.

If you have an idea how to best handle the popover, I'm open to suggestions! Otherwise, we can address it separately whenever the time allows 😄

Screenshots

Prod Local
disableTrapFocus={true}, ownFocus={true} prod-true-true local-true-true
disableTrapFocus={true}, ownFocus={false} prod-true-false local-true-false
disableTrapFocus={false}, ownFocus={true} prod-false-true local-false-true
disableTrapFocus={false}, ownFocus={false} prod-false-false local-false-false

Impact to users

🟠 It's not a breaking change BUT it's a difference in component behavior which may affect some use cases detrimentally, and especially automated tests.

This change should prompt a cleanup of: elastic/kibana#230852 (comment)

QA

Specific checklist

  • Verify in Storybook that the EuiInputPopover doesn't close on Shift + Tab when the last interactive element is active

General checklist

  • Browser QA
    • Checked in both light and dark modes
    • Checked in both MacOS and Windows high contrast modes
    • Checked in mobile
    • Checked in Chrome, Safari, Edge, and Firefox
    • Checked for accessibility including keyboard-only and screenreader modes
  • Docs site QA
  • Code quality checklist
  • Release checklist
    • A changelog entry exists and is marked appropriately.
    • If applicable, added the breaking change issue label (and filled out the breaking change checklist)
  • Designer checklist
    • If applicable, file an issue to update EUI's Figma library with any corresponding UI changes. (This is an internal repo, if you are external to Elastic, ask a maintainer to submit this request)

@weronikaolejniczak weronikaolejniczak self-assigned this Aug 7, 2025
@weronikaolejniczak weronikaolejniczak force-pushed the fix/shift-tab-in-eui-input-popover branch from 2e63a47 to 4a40697 Compare August 7, 2025 11:17
@weronikaolejniczak weronikaolejniczak marked this pull request as ready for review August 7, 2025 11:18
@weronikaolejniczak weronikaolejniczak requested a review from a team as a code owner August 7, 2025 11:18
@weronikaolejniczak weronikaolejniczak added the support-duty-flywheel Label for PRs, see eui-private #310 label Aug 7, 2025
@weronikaolejniczak weronikaolejniczak force-pushed the fix/shift-tab-in-eui-input-popover branch from 4a40697 to f0c2a0f Compare August 7, 2025 13:16
@mgadewoll
Copy link
Contributor

mgadewoll commented Aug 11, 2025

@weronikaolejniczak Thanks for raising the mentioned issues. I had a look at what's going on and you're right, the keyboard behavior is currently a bit weird. Additionally I'm a bit confused why EuiInputPopover has it's own EuiFocusTrap while the internal EuiPopover already has one, but that's a different topic 🤷‍♀️

🗒️ Anyway, from what I understand these are the focus behaviors base on the two props disableFocusTrap and ownFocus:

  • disableFocusTrap=true & ownFocus=true

    • panel has a focus stop (ownFocus)
    • focus is not trapped (disableFocusTrap disables the focus trap in EuiInputPopover)
  • disableFocusTrap=false & ownFocus=false

    • panel has no focus stop (due to ownFocus=false)
    • focus is not trapped (ownFocus=false disables the focus trap in EuiPopover)
  • disableFocusTrap=false & ownFocus=true

    • panel has a focus stop (due to ownFocus=true)
    • focus is trapped (due to disableFocusTrap=false)
  • disableFocusTrap=true & ownFocus=false

    • panel has no focus stop (due to ownFocus=false)
    • focus is not trapped (ownFocus=false disables the focus trap in EuiPopover, disableFocusTrap=true disables the trap in EuiInputPopover)

🐞 And concerning the keyboard navigation I saw 3 main issues:

  1. Shift + Tab on the last item closes the popover

    • This is fixed by your update for disableFocusTrap=false but it also happens for disableFocusTrap=true. Looks like we need to update the function to apply to all cases of !ownFocus
  2. Tab from the first focusable item closes the popover unexpectedly when disableFocusTrap=true & ownFocus=false

    • We should also add tabbingFromFirstItemInPopover && e.shiftKey to the closing condition
  3. As mentioned by you: Escape doesn't work as expected

    • This looks to be use case specific. The stories have a custom onFocus handler which opens the popover on focus. So when the popover closes and returns the focus, the focus on the input triggers the popover to open again as it's simply reacting to the isOpen prop. 💀

@mgadewoll
Copy link
Contributor

mgadewoll commented Aug 13, 2025

ℹ️ @weronikaolejniczak I pushed up changes to address the issues mentioned here.

  • ensure Tab and Tab + Shift don't close the popover from last or first focusable item
  • update the onFocus handler in our stories to prevent reopening popovers after closing the popover

@mgadewoll mgadewoll self-assigned this Aug 13, 2025
@weronikaolejniczak
Copy link
Contributor Author

@mgadewoll LGTM 🟢 2 small things:

  1. A test is failing:
/app/packages/eui/cypress/screenshots/components/popover/input_popover.spec.tsx/     (1280x633)
--
  | EuiPopover -- focustab management -- with focus trap disabled -- automatically c
  | loses the popover when users tab from anywhere in the popover
  1. disableTrapFocus={false} is not working as I'd expect it to, i.e. doesn't trap focus:
    Kapture 2025-08-13 at 19 03 05

I think we can investigate the trap focus separately.

@mgadewoll
Copy link
Contributor

mgadewoll commented Aug 13, 2025

2. disableTrapFocus={false} is not working as I'd expect it to, i.e. doesn't trap focus:

@weronikaolejniczak When disableTrapFocus=false and ownFocus=false it shouldn't trap focus, as the focus trap is disabled in EuiPopover due to the ownFocus=false 😅 (code)

@weronikaolejniczak
Copy link
Contributor Author

As you wrote above:

disableFocusTrap=false & ownFocus=false

  • panel has no focus stop (due to ownFocus=false)
  • focus is not trapped (ownFocus=false disables the focus trap in EuiPopover)

I can imagine if it's confusing to me then it could be more confusing to the consumer. That being said, it seems like the expected behavior.

@mgadewoll
Copy link
Contributor

As you wrote above:

disableFocusTrap=false & ownFocus=false

  • panel has no focus stop (due to ownFocus=false)
  • focus is not trapped (ownFocus=false disables the focus trap in EuiPopover)

I can imagine if it's confusing to me then it could be more confusing to the consumer. That being said, it seems like the expected behavior.

Yeah, I'm also confused by it 😅 I still don't understand why it has duplicate FocusTraps. Probably something we could look into in the future on how to make this better.

weronikaolejniczak and others added 6 commits August 14, 2025 11:12
- ensures that tab cycling works without unexpected closing
- the test asserts an unexpected behavior. Checking EuiDualRange, there are no tab stops inside the popover and even if, it would be wrong to close the popover on tab
- this is a bit of a spicy decision, but it's meant to prevent issues with unexpected focus traps, as the popover doesn't have focusable content
@mgadewoll mgadewoll force-pushed the fix/shift-tab-in-eui-input-popover branch from e983fa5 to 3827ff7 Compare August 14, 2025 09:41
@elasticmachine
Copy link
Collaborator

💚 Build Succeeded

History

cc @weronikaolejniczak @mgadewoll

@elasticmachine
Copy link
Collaborator

💚 Build Succeeded

History

cc @weronikaolejniczak @mgadewoll

@weronikaolejniczak
Copy link
Contributor Author

@mgadewoll I reviewed the recent changes: 3827ff7 and 1ecc1c2, I believe both make sense.

refactor: remove support for ownFocus on EuiDualRange inputPopoverProps

  • this is a bit of a spicy decision, but it's meant to prevent issues with unexpected focus traps, as the popover doesn't have focusable content

test: remove cypress test

  • the test asserts an unexpected behavior. Checking EuiDualRange, there are no tab stops inside the popover and even if, it would be wrong to close the popover on tab

@mgadewoll
Copy link
Contributor

mgadewoll commented Aug 14, 2025

@weronikaolejniczak Sorry, I hadn't posted my comment about the changes yet. You're too fast 😄
Glad you agree with the changes 👍

Anyway here still the comments:

  1. removed the failing cypress test
    • the test was already commented as potentially wrong. Imho, the test asserts a behavior that's unexpected. I checked on the EuiDualRange behavior and usages and didn't see an issue in removing the test.
  2. when checking EuiDualRange I noticed that there would be an issue with focus traps if ownFocus=true as the popover doesn't have focusable content. To prevent confusion I chose to remove support for ownFocus on EuiDualRange (there are no usages of it across Kibana or Cloud)
    • the changes are currently running against Kibana CI as sanity check
  3. rebased with main (because of wanting to run it in latest Kibana)

ℹ️ I'm currently still waiting for the Kibana CI to finish.

Copy link
Contributor

@mgadewoll mgadewoll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 The check in Kibana CI succeeded and the overall changes in this PR ensure a more predictable keyboard navigation for EuiInputPopover.

@weronikaolejniczak weronikaolejniczak merged commit 9b71b8a into elastic:main Aug 14, 2025
5 checks passed
mgadewoll added a commit to elastic/kibana that referenced this pull request Aug 27, 2025
- `@elastic/eui`: `v106.3.0` ⏩ `v106.4.0`
- `@elastic/eui-theme-borealis`: `v3.3.1` ⏩ `v3.3.2`

[Questions? Please see our Kibana upgrade
FAQ.](https://github.com/elastic/eui/blob/main/wiki/eui-team-processes/upgrading-kibana.md#faq-for-kibana-teams)

## Package updates

## [`v106.4.0`](https://github.com/elastic/eui/releases/v106.4.0)

- Added prop `focusTrapProps` on `EuiModal`
([#8945](elastic/eui#8945))

**Bug fixes**

- Fixed the syntax of the SCSS variable `$euiColorTransparent` to ensure
a valid value ([#8966](elastic/eui#8966))
- Fixed `restrictWidth` not applying to `EuiPageHeaderContent` when only
`children` are used as content
([#8965](elastic/eui#8965))

**Accessibility**

- Fixed an issue where pressing Shift + Tab on the last tabbable element
inside `EuiInputPopover` popover would close the popover unexpectedly
([#8950](elastic/eui#8950))

### `@elastic/eui-theme-borealis`

## [`v3.3.2`](https://github.com/elastic/eui/releases/v3.3.2)

**Bug fixes**

- Fixed the syntax of the SCSS variable `$euiColorTransparent` to ensure
a valid value ([#8966](elastic/eui#8966))
kowalczyk-krzysztof pushed a commit to kowalczyk-krzysztof/kibana that referenced this pull request Aug 30, 2025
- `@elastic/eui`: `v106.3.0` ⏩ `v106.4.0`
- `@elastic/eui-theme-borealis`: `v3.3.1` ⏩ `v3.3.2`

[Questions? Please see our Kibana upgrade
FAQ.](https://github.com/elastic/eui/blob/main/wiki/eui-team-processes/upgrading-kibana.md#faq-for-kibana-teams)

## Package updates

## [`v106.4.0`](https://github.com/elastic/eui/releases/v106.4.0)

- Added prop `focusTrapProps` on `EuiModal`
([elastic#8945](elastic/eui#8945))

**Bug fixes**

- Fixed the syntax of the SCSS variable `$euiColorTransparent` to ensure
a valid value ([elastic#8966](elastic/eui#8966))
- Fixed `restrictWidth` not applying to `EuiPageHeaderContent` when only
`children` are used as content
([elastic#8965](elastic/eui#8965))

**Accessibility**

- Fixed an issue where pressing Shift + Tab on the last tabbable element
inside `EuiInputPopover` popover would close the popover unexpectedly
([elastic#8950](elastic/eui#8950))

### `@elastic/eui-theme-borealis`

## [`v3.3.2`](https://github.com/elastic/eui/releases/v3.3.2)

**Bug fixes**

- Fixed the syntax of the SCSS variable `$euiColorTransparent` to ensure
a valid value ([elastic#8966](elastic/eui#8966))
qn895 pushed a commit to qn895/kibana that referenced this pull request Sep 2, 2025
- `@elastic/eui`: `v106.3.0` ⏩ `v106.4.0`
- `@elastic/eui-theme-borealis`: `v3.3.1` ⏩ `v3.3.2`

[Questions? Please see our Kibana upgrade
FAQ.](https://github.com/elastic/eui/blob/main/wiki/eui-team-processes/upgrading-kibana.md#faq-for-kibana-teams)

## Package updates

## [`v106.4.0`](https://github.com/elastic/eui/releases/v106.4.0)

- Added prop `focusTrapProps` on `EuiModal`
([elastic#8945](elastic/eui#8945))

**Bug fixes**

- Fixed the syntax of the SCSS variable `$euiColorTransparent` to ensure
a valid value ([elastic#8966](elastic/eui#8966))
- Fixed `restrictWidth` not applying to `EuiPageHeaderContent` when only
`children` are used as content
([elastic#8965](elastic/eui#8965))

**Accessibility**

- Fixed an issue where pressing Shift + Tab on the last tabbable element
inside `EuiInputPopover` popover would close the popover unexpectedly
([elastic#8950](elastic/eui#8950))

### `@elastic/eui-theme-borealis`

## [`v3.3.2`](https://github.com/elastic/eui/releases/v3.3.2)

**Bug fixes**

- Fixed the syntax of the SCSS variable `$euiColorTransparent` to ensure
a valid value ([elastic#8966](elastic/eui#8966))
@weronikaolejniczak weronikaolejniczak deleted the fix/shift-tab-in-eui-input-popover branch February 10, 2026 10:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accessibility support-duty-flywheel Label for PRs, see eui-private #310

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[EuiInputPopover] closePopover triggered when Shift+Tabbing away from last tabbable child

3 participants