[EuiButton] Support focusable disabled behavior with hasAriaDisabled prop#9201
Merged
mgadewoll merged 15 commits intoelastic:mainfrom Nov 14, 2025
Merged
Conversation
347efc9 to
c0d44e2
Compare
Merged
15 tasks
c0d44e2 to
9e283de
Compare
9e283de to
d9f31e8
Compare
41 tasks
acstll
requested changes
Nov 13, 2025
Contributor
There was a problem hiding this comment.
Not approving yet but shared mostly nits and non-blocking suggestions (would like to know what you think). I really like how this turned out and how the featured has been implemented.
I went through the suggested QA steps and it's all working as expected. I also thought (again) about naming of test helpers and they seem just right.
Amazing work ✨
packages/eui/src/components/button/button_group/button_group.test.tsx
Outdated
Show resolved
Hide resolved
d9f31e8 to
2fddd0c
Compare
acstll
approved these changes
Nov 14, 2025
Contributor
acstll
left a comment
There was a problem hiding this comment.
🟢 Thanks for addressing my comments. The only thing left is reverting the TESTING_EXAMPLE story. Again, awesome work!
Contributor
Author
|
@acstll Thanks for the thorough review and suggestions! ❤️ |
2fddd0c to
cd47a4f
Compare
Collaborator
💚 Build SucceededHistory
cc @mgadewoll |
Collaborator
💚 Build Succeeded
History
cc @mgadewoll |
3 tasks
acstll
added a commit
to elastic/kibana
that referenced
this pull request
Nov 20, 2025
- `@elastic/eui`: `v109.0.0` ⏩ `v109.1.0` - `@elastic/eslint-plugin-eui`: `v2.5.0` ⏩ `v2.6.0` --- ## Changes - Updated i18n EUI mapping 6cc95b0 - Updated test in Unified Search 668948f ## Package updates ### `@elastic/eui` [`v109.1.0`](https://github.com/elastic/eui/releases/v109.1.0) - Added `--euiBottomBarOffset` CSS variable to `EuiBottomBar` for positioning other fixed elements relative to the bottom bar's height ([#9211](elastic/eui#9211)) - Updated `boxesVertical` icon and restored `checkInCircleFilled`, `errorFilled`, and `warningFilled` icons. ([#9194](elastic/eui#9194)) - Updated `EuiSuperDatePicker` with new time zone information, opt-in via `timeZoneDisplayProps`. ([#9191](elastic/eui#9191)) - Updated the position of `EuiModal` by removing bottom padding in `EuiOverlayMask` ([#9190](elastic/eui#9190)) - Added `EuiPopover` and `EuiToolTip`'s `repositionOnScroll` to `componentDefaults` ([#9152](elastic/eui#9152)) - Updated `EuiSuperDatePicker` with new time window buttons for time shifting and zoom out, opt-in via `showTimeWindowButtons` boolean prop. ([#9151](elastic/eui#9151)) - Added beta prop `hasAriaDisabled` to all base button components: `EuiButton`, `EuiButtonEmpty`, `EuiButtonIcon`, `EuibuttonGroup`, `EuiFilterButton` ([#9201](elastic/eui#9201)) - Added `euiDisabledSelector` variable that combines CSS selectors `:disabled` and `[aria-disabled="true"]` ([#9201](elastic/eui#9201)) - Added custom test matchers that check for both `disabled` and `aria-disabled` attributes: ([#9201](elastic/eui#9201)) - React testing Library: `.toBeEuiDisabled()` - Enzyme: `.toHaveEuiDisabledProp()` - Cypress: `should('be.euiDisabled)` **Bug fixes** - Fixed unexpected duplicate columns in `EuiDataGrid` crashing the column sorting by removing duplicate columns entirely ([#9209](elastic/eui#9209)) - Fixed a visual bug in `EuiTable` where long table row content would be cut off on mobile screens ([#9206](elastic/eui#9206)) - Fixed virtualized `EuiCodeBlock` rendering blank lines when content updates if scrolled. ([#9196](elastic/eui#9196)) - Fixed `EuiButtonGroup` button sizing to ensure square buttons when used with `isIconOnly=true` ([#9170](elastic/eui#9170)) **Accessibility** - Fixed an issue where portalled components like `EuiPopover` were not included in `EuiFlyout`'s focus trap through `includeSelectorInFocusTrap`, making them inaccessible to keyboard users ([#9103](elastic/eui#9103)) ### `@elastic/eslint-plugin-eui` [`v2.6.0`](https://github.com/elastic/eui/blob/main/packages/eslint-plugin/changelogs/CHANGELOG_2025.md#v260) - Added new `require-table-caption` rule. ([#9168](elastic/eui#9168)) --------- Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
15 tasks
andrimal
pushed a commit
to andrimal/kibana
that referenced
this pull request
Nov 20, 2025
- `@elastic/eui`: `v109.0.0` ⏩ `v109.1.0` - `@elastic/eslint-plugin-eui`: `v2.5.0` ⏩ `v2.6.0` --- ## Changes - Updated i18n EUI mapping 6cc95b0 - Updated test in Unified Search 668948f ## Package updates ### `@elastic/eui` [`v109.1.0`](https://github.com/elastic/eui/releases/v109.1.0) - Added `--euiBottomBarOffset` CSS variable to `EuiBottomBar` for positioning other fixed elements relative to the bottom bar's height ([elastic#9211](elastic/eui#9211)) - Updated `boxesVertical` icon and restored `checkInCircleFilled`, `errorFilled`, and `warningFilled` icons. ([elastic#9194](elastic/eui#9194)) - Updated `EuiSuperDatePicker` with new time zone information, opt-in via `timeZoneDisplayProps`. ([elastic#9191](elastic/eui#9191)) - Updated the position of `EuiModal` by removing bottom padding in `EuiOverlayMask` ([elastic#9190](elastic/eui#9190)) - Added `EuiPopover` and `EuiToolTip`'s `repositionOnScroll` to `componentDefaults` ([elastic#9152](elastic/eui#9152)) - Updated `EuiSuperDatePicker` with new time window buttons for time shifting and zoom out, opt-in via `showTimeWindowButtons` boolean prop. ([elastic#9151](elastic/eui#9151)) - Added beta prop `hasAriaDisabled` to all base button components: `EuiButton`, `EuiButtonEmpty`, `EuiButtonIcon`, `EuibuttonGroup`, `EuiFilterButton` ([elastic#9201](elastic/eui#9201)) - Added `euiDisabledSelector` variable that combines CSS selectors `:disabled` and `[aria-disabled="true"]` ([elastic#9201](elastic/eui#9201)) - Added custom test matchers that check for both `disabled` and `aria-disabled` attributes: ([elastic#9201](elastic/eui#9201)) - React testing Library: `.toBeEuiDisabled()` - Enzyme: `.toHaveEuiDisabledProp()` - Cypress: `should('be.euiDisabled)` **Bug fixes** - Fixed unexpected duplicate columns in `EuiDataGrid` crashing the column sorting by removing duplicate columns entirely ([elastic#9209](elastic/eui#9209)) - Fixed a visual bug in `EuiTable` where long table row content would be cut off on mobile screens ([elastic#9206](elastic/eui#9206)) - Fixed virtualized `EuiCodeBlock` rendering blank lines when content updates if scrolled. ([elastic#9196](elastic/eui#9196)) - Fixed `EuiButtonGroup` button sizing to ensure square buttons when used with `isIconOnly=true` ([elastic#9170](elastic/eui#9170)) **Accessibility** - Fixed an issue where portalled components like `EuiPopover` were not included in `EuiFlyout`'s focus trap through `includeSelectorInFocusTrap`, making them inaccessible to keyboard users ([elastic#9103](elastic/eui#9103)) ### `@elastic/eslint-plugin-eui` [`v2.6.0`](https://github.com/elastic/eui/blob/main/packages/eslint-plugin/changelogs/CHANGELOG_2025.md#v260) - Added new `require-table-caption` rule. ([elastic#9168](elastic/eui#9168)) --------- Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
eokoneyo
pushed a commit
to eokoneyo/kibana
that referenced
this pull request
Dec 2, 2025
- `@elastic/eui`: `v109.0.0` ⏩ `v109.1.0` - `@elastic/eslint-plugin-eui`: `v2.5.0` ⏩ `v2.6.0` --- ## Changes - Updated i18n EUI mapping 6cc95b0 - Updated test in Unified Search 668948f ## Package updates ### `@elastic/eui` [`v109.1.0`](https://github.com/elastic/eui/releases/v109.1.0) - Added `--euiBottomBarOffset` CSS variable to `EuiBottomBar` for positioning other fixed elements relative to the bottom bar's height ([elastic#9211](elastic/eui#9211)) - Updated `boxesVertical` icon and restored `checkInCircleFilled`, `errorFilled`, and `warningFilled` icons. ([elastic#9194](elastic/eui#9194)) - Updated `EuiSuperDatePicker` with new time zone information, opt-in via `timeZoneDisplayProps`. ([elastic#9191](elastic/eui#9191)) - Updated the position of `EuiModal` by removing bottom padding in `EuiOverlayMask` ([elastic#9190](elastic/eui#9190)) - Added `EuiPopover` and `EuiToolTip`'s `repositionOnScroll` to `componentDefaults` ([elastic#9152](elastic/eui#9152)) - Updated `EuiSuperDatePicker` with new time window buttons for time shifting and zoom out, opt-in via `showTimeWindowButtons` boolean prop. ([elastic#9151](elastic/eui#9151)) - Added beta prop `hasAriaDisabled` to all base button components: `EuiButton`, `EuiButtonEmpty`, `EuiButtonIcon`, `EuibuttonGroup`, `EuiFilterButton` ([elastic#9201](elastic/eui#9201)) - Added `euiDisabledSelector` variable that combines CSS selectors `:disabled` and `[aria-disabled="true"]` ([elastic#9201](elastic/eui#9201)) - Added custom test matchers that check for both `disabled` and `aria-disabled` attributes: ([elastic#9201](elastic/eui#9201)) - React testing Library: `.toBeEuiDisabled()` - Enzyme: `.toHaveEuiDisabledProp()` - Cypress: `should('be.euiDisabled)` **Bug fixes** - Fixed unexpected duplicate columns in `EuiDataGrid` crashing the column sorting by removing duplicate columns entirely ([elastic#9209](elastic/eui#9209)) - Fixed a visual bug in `EuiTable` where long table row content would be cut off on mobile screens ([elastic#9206](elastic/eui#9206)) - Fixed virtualized `EuiCodeBlock` rendering blank lines when content updates if scrolled. ([elastic#9196](elastic/eui#9196)) - Fixed `EuiButtonGroup` button sizing to ensure square buttons when used with `isIconOnly=true` ([elastic#9170](elastic/eui#9170)) **Accessibility** - Fixed an issue where portalled components like `EuiPopover` were not included in `EuiFlyout`'s focus trap through `includeSelectorInFocusTrap`, making them inaccessible to keyboard users ([elastic#9103](elastic/eui#9103)) ### `@elastic/eslint-plugin-eui` [`v2.6.0`](https://github.com/elastic/eui/blob/main/packages/eslint-plugin/changelogs/CHANGELOG_2025.md#v260) - Added new `require-table-caption` rule. ([elastic#9168](elastic/eui#9168)) --------- Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.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.
Summary
closes #9098
This PR introduces custom disabled behavior for all base button components (
EuiButton,EuiButtonEmpty,EuiButtonIcon,EuiButtonGroup,EuiFilterButton) via a new prophasAriaDisabled.Important
The new custom disabled behavior via
hasAriaDisabledwill be added as opt-in Beta feature and we will monitor usages and adjust/fix the functionality as needed.If
hasAriaDisabled=trueis added, the buttons render with thearia-disabledattribute instead of the nativedisabledattribute. The main purpose for this is to preserve focusability of buttons while also keeping them semantically and functionally disabled. This is useful when wanting to add tooltips on disabled buttons provide additional information about the state.aria-disabledprovides the same semantic state asdisabledbut besides that does not prevent any events from firing.This PR introduces a hook for handling disabled behavior that's used under the hood in the updated button components.
The hook ensures that:
aria-disabledordisabledare returnedonClick).click())dispatchEvent)API changes
These apply to
EuiButton,EuiButtonEmpty,EuiButtonIcon,EuiButtonGroupandEuiFilterButton.hasAriaDisabledbooleanfalsedisabledattribute toaria-disabledto preserve focusability. This results in a semantically disabled button with a custom disabled state behavior instead of the default browser one.Additional changes
Because usages with
hasAriaDisabledrenderaria-disabledinstead ofdisabled, there are additional considerations for its usage::disabledwon't workdisabledtest framework matchers won't workTo support the usage of
hasAriaDisabled, this PR adds the following:euiDisabledSelector- variable that provides the combined CSS disabled selectors:disabled, [aria-disabled="true"].toBeEuiDisabledfor react-testing-library.toHaveEuiDisabledPropfor enzymeshould('be.euiDisabled)for CypressWhy are we making this change?
💪
Usability: The update provides an enhanced disabled behavior that preserves focusability and supports consumer requests to allow adding tooltips on disabled buttons.
Screenshots #
Screen.Recording.2025-11-10.at.18.15.56.mov
Impact to users
🟢 There are no immediate updates needed on consumer side. The added functionality is in beta state and opt-in only.
Note
The changes have been run as pre-release in Kibana CI here)
ℹ️ Consumers that want to start using
hasAriaDisabledon buttons, will need to update the following if used:disabledattribute -> use the new EUI test helpers instead:disabledpseudo-selector -> useeuiDisabledSelectorin CSS-in-JS/JS or:disabled, [aria-disabled="true"]in CSS insteadNote
Examples of test updates for RTL, Enzyme, Cypress, FTR and Playwright on Kibana have been prepared here.
QA
Note
It's suggested to review changes commit by commit.
🧪 Testing Story
📖 Documentation:
View added documentation screenshots
hasAriaDisabled=falsehas no regressions with productionhasAriaDisabled={true}supports focus, blur andTabandEscapekey eventsisDisabledstatehasAriaDisabled={true}prevents any mouse/pointer/touch event as well as any other keyboard event (notTaborEscapekey)yarn buildand verify that the added test helpers are correctly bundled in@elastic/eui/lib/testGeneral checklist
@defaultif default values are missing) and playground togglesToDo
hasAriaDisabledfor button components #9214