-
Notifications
You must be signed in to change notification settings - Fork 863
[EuiButton] Support focusable disabled behavior with hasAriaDisabled prop
#9201
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[EuiButton] Support focusable disabled behavior with hasAriaDisabled prop
#9201
Conversation
347efc9 to
c0d44e2
Compare
c0d44e2 to
9e283de
Compare
9e283de to
d9f31e8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟢 Thanks for addressing my comments. The only thing left is reverting the TESTING_EXAMPLE story. Again, awesome work!
|
@acstll Thanks for the thorough review and suggestions! ❤️ |
2fddd0c to
cd47a4f
Compare
💚 Build SucceededHistory
cc @mgadewoll |
💚 Build Succeeded
History
cc @mgadewoll |
- `@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 <[email protected]>
- `@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 <[email protected]>
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