Skip to content

[eslint-plugin] Added new @elastic/eui/no-nested-copy-tooltip rule - #9852

Merged
alexwizp merged 11 commits into
elastic:mainfrom
alexwizp:copy-component-rules
Jul 30, 2026
Merged

[eslint-plugin] Added new @elastic/eui/no-nested-copy-tooltip rule#9852
alexwizp merged 11 commits into
elastic:mainfrom
alexwizp:copy-component-rules

Conversation

@alexwizp

@alexwizp alexwizp commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • What: Adds a new ESLint rule @elastic/eui/no-nested-copy-tooltip and updates the existing @elastic/eui/tooltip-button-icon-wrap rule to avoid a conflict between the two.
  • Why: EuiCopy already wraps its render-prop child in an EuiToolTip internally, using the beforeMessage prop as that tooltip's content. When the render-prop child is itself an EuiToolTip, the result is a nested, conflicting tooltip. The new rule flags this pattern; the tooltip-button-icon-wrap update prevents it from demanding a wrapper that no-nested-copy-tooltip forbids.
  • How:
    • no-nested-copy-tooltip (a11y): reports when EuiCopy sets beforeMessage and its render-prop root child is an EuiToolTip, recommending removal of the EuiToolTip wrapper and moving its message into beforeMessage. It resolves the render-prop root through implicit arrow returns, block-body return statements (including block bodies with an early return), and function expressions. It is report-only (no autofix), because the tooltip's content and an existing beforeMessage value cannot always be merged safely (e.g. when either is a variable or JSX).
    • tooltip-button-icon-wrap: added an EuiCopy ancestor exception so an EuiButtonIcon rendered inside an EuiCopy that sets beforeMessage is no longer flagged for a missing EuiToolTip wrapper (the tooltip is provided by EuiCopy). Without beforeMessage there is no tooltip, so the button is still flagged. A browser-native title prop is still reported in all cases.
    • Registered the new rule in src/index.ts (recommended config, warn level), added tests, and updated the plugin README.md.

API Changes

component / parent prop / child change description
@elastic/eslint-plugin-eui no-nested-copy-tooltip Added New a11y rule flagging EuiCopy + beforeMessage with an EuiToolTip render-prop child
@elastic/eslint-plugin-eui tooltip-button-icon-wrap Changed No longer requires an EuiToolTip wrapper for an EuiButtonIcon rendered inside an EuiCopy that sets beforeMessage

No changes to the @elastic/eui component public API.

Screenshots

N/A — lint-only change, no visual output.

Impact Assessment

Note: Most PRs should be tested in Kibana to help gauge their Impact before merging.

  • 🔴 Breaking changes — None.
  • 💅 Visual changes — None (lint-only).
  • 🧪 Test impact — The new rule ships in the recommended config at warn level, so consumers (e.g. Kibana) may see new lint warnings where EuiCopy + beforeMessage wraps an EuiToolTip. Warnings only — no build breakage.
  • 🔧 Hard to integrate — No.

Impact level: 🟢 Low

Release Readiness

  • Documentation: packages/eslint-plugin/README.md (rule docs with examples for both rules)
  • Figma
  • Migration guide — new warn-level rule, no migration required
  • Adoption plan — enabled via the existing recommended config

QA instructions for reviewer

  • Run yarn test in packages/eslint-plugin.
  • Confirm no_nested_copy_tooltip.test.ts passes (valid/invalid cases for implicit return, expression beforeMessage, block-body return, function expression, and early return).
  • Confirm tooltip_button_icon_wrap.test.ts passes, including the new EuiCopy exception cases (with and without beforeMessage) and that a title prop inside EuiCopy is still reported.

Checklist before marking Ready for Review

  • Filled out all sections above
  • QA: light/dark modes, high contrast, mobile, browsers, keyboard, screen reader — lint-only change
  • QA: Tested in CodeSandbox and Kibana
  • QA: Tested docs changes
  • Tests: Added/updated Jest tests
  • Changelog: Added changelog entry
  • Breaking changes: label — not applicable

Reviewer checklist

  • Approved Impact Assessment — Acceptable to merge given the consumer impact.
  • Approved Release Readiness — Docs and migration info are sufficient to ship.

{
code: dedent`
const MyComponent = () => (
<EuiCopy textToCopy="some text">

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

A question for the reviewers: should this be considered a problem? I don't think so—perhaps it can be allowed for the sake of flexibility.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This pattern works reliably. The issue would be if both beforeMessage and child EuiToolTip existed. Because we no longer bubble events as of v118.0.0, only the innermost tooltip shows (most often the EUI internal one that consumers should be able to override with a prop, as is the case with EuiCopy).

I don't see any issue with this composition. And linting should get rid of any ambiguity anyway because of a developer/an agent see this pattern somewhere, decide to use it but with beforeMessage, the linter will flag it.

@alexwizp
alexwizp marked this pull request as ready for review July 29, 2026 13:15
@alexwizp
alexwizp requested a review from a team as a code owner July 29, 2026 13:15
Copilot AI review requested due to automatic review settings July 29, 2026 13:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new a11y-focused ESLint rule to prevent nested/conflicting tooltips when EuiCopy is used with beforeMessage, and updates the existing tooltip-button-icon-wrap rule/docs/tests so the two rules don’t fight each other.

Changes:

  • Added new @elastic/eui/copy-component-rules rule (report-only) to flag EuiCopy + beforeMessage when the render-prop returns an EuiToolTip as the root element.
  • Updated @elastic/eui/tooltip-button-icon-wrap to exempt EuiButtonIcon inside EuiCopy from the “must be wrapped in EuiToolTip” report.
  • Registered the new rule in the plugin’s recommended config, and updated tests/docs/changelog.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/eslint-plugin/src/rules/a11y/tooltip_button_icon_wrap.ts Adds EuiCopy ancestor exception to avoid requiring a wrapper tooltip that would conflict with the new rule
packages/eslint-plugin/src/rules/a11y/tooltip_button_icon_wrap.test.ts Adds test coverage for the new EuiCopy exception behavior (and title reporting)
packages/eslint-plugin/src/rules/a11y/copy_component_rules.ts Introduces the new rule detecting redundant EuiToolTip wrapping inside EuiCopy when beforeMessage is set
packages/eslint-plugin/src/rules/a11y/copy_component_rules.test.ts Adds valid/invalid rule tests for implicit and explicit render-prop returns
packages/eslint-plugin/src/index.ts Registers the new rule and enables it in recommended at warn level
packages/eslint-plugin/README.md Documents the new rule and the updated tooltip-button-icon-wrap exception
packages/eslint-plugin/changelogs/upcoming/9852.md Adds changelog entry for the new rule and the exception update

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/eslint-plugin/src/rules/a11y/tooltip_button_icon_wrap.ts
Comment thread packages/eslint-plugin/README.md Outdated
Comment thread packages/eslint-plugin/changelogs/upcoming/9852.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
… to beforeMessage

The `tooltip-button-icon-wrap` EuiCopy exception previously skipped the
missing-tooltip report for any EuiButtonIcon inside EuiCopy. EuiCopy only
renders its internal EuiToolTip when `beforeMessage` is set (empty tooltip
content is suppressed), so the exception is now conditional on `beforeMessage`.
Updated the README and added regression tests for the no-beforeMessage case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@weronikaolejniczak

Copy link
Copy Markdown
Contributor

@alexwizp ESLint plugin tests are finally resolved in CI: https://buildkite.com/elastic/eui-pull-request-test/builds/7051#019fae26-2f8a-4b88-9fe5-73f34d49660d 🎉 So no need to run them locally, if CI is 🟢 then we're good.

@weronikaolejniczak

Copy link
Copy Markdown
Contributor

@kapral18 could you also take a look at it since you raised this? 🙏🏻

Comment thread packages/eslint-plugin/src/rules/a11y/no_nested_copy_tooltip.ts
Comment thread packages/eslint-plugin/src/index.ts
};
},
meta: {
type: 'problem',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No action required: I was thinking if this should be a "suggestion" instead because it's a warning and there's no issue at runtime but it will produce an undesired result to what was coded, so I'm fine categorizing it as a "problem".

Comment thread packages/eslint-plugin/README.md Outdated

@weronikaolejniczak weronikaolejniczak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This whole PR looks great to me, thank you for tackling it, @alexwizp 🙏🏻 You're a champ!

I see there are only 8 violations in Kibana. All of them use an arrow function expression. There's one potential case we could handle too that won't be flagged, an early return:

<EuiCopy beforeMessage="Click to copy" textToCopy="some text">
  {(copy) => {
    if (!condition) return null;
    return <EuiToolTip content="Copy me"><EuiButton onClick={copy}>Copy</EuiButton></EuiToolTip>;
  }}
</EuiCopy>

Address PR elastic#9852 review feedback:
- Rename the generic `copy-component-rules` rule to `no-nested-copy-tooltip`
  (file, export, rule id, index registration, README, changelog, messages).
- Sort the rule alphabetically among the `no-*` rules in `index.ts`.
- Add invalid test cases for a function-expression render prop and a
  block body with an early return before the tooltip return.
- De-duplicate the redundant "Good" example in the README.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alexwizp alexwizp changed the title [eslint-plugin] Added new @elastic/eui/copy-component-rules rule [eslint-plugin] Added new @elastic/eui/no-nested-copy-tooltip rule Jul 30, 2026

@kapral18 kapral18 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Leaving a few edge cases around the new static checks. cc: @weronikaolejniczak for a quick glance as well.

Comment thread packages/eslint-plugin/src/rules/a11y/no_nested_copy_tooltip.ts Outdated
Comment thread packages/eslint-plugin/src/rules/a11y/tooltip_button_icon_wrap.ts Outdated
Comment thread packages/eslint-plugin/src/rules/a11y/tooltip_button_icon_wrap.ts

if (
!isWrappedByTooltip(node) &&
!isInsideEuiCopyWithBeforeMessage(node) &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Minor/nit: the spread handling is asymmetric between the two components here.

hasSpread skips the report when the EuiButtonIcon itself has spread props, on the grounds that its final prop set is not statically knowable. But beforeMessage can arrive on EuiCopy the same way:

<EuiCopy textToCopy="x" {...props}>
  {(copy) => <EuiButtonIcon aria-label="Copy" iconType="copy" onClick={copy} />}
</EuiCopy>

isInsideEuiCopyWithBeforeMessage returns false here and the button is reported, even though props may well carry beforeMessage. Worth applying the same "can't statically determine" treatment to a spread on the EuiCopy ancestor, or noting explicitly that unknown spread is intentionally treated as absent.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Withdrawing this one — you're right it isn't worth the complexity. Silently skipping unknown spread is already the convention across this plugin, and Kibana's a11y docs list it as an expected manual-review caveat for this rule. Resolving.

alexwizp and others added 2 commits July 30, 2026 13:50
Address kapral18 review feedback on PR elastic#9852:

- no-nested-copy-tooltip: resolve the render-prop child by its function
  container instead of the first JSX expression container, so a leading
  JSX comment no longer hides a nested EuiToolTip.
- Add a generic, component-agnostic `hasMeaningfulAttr` util that treats a
  statically empty/falsy attribute value (`""`, `{''}`, `{0}`, `{false}`,
  `{null}`, `{undefined}`) as absent while leaving dynamic values as present.
  Both rules now use it for `beforeMessage`, so an empty `beforeMessage`
  neither exempts a bare EuiButtonIcon nor flags a child EuiToolTip.
- tooltip-button-icon-wrap: bail the EuiCopy ancestor walk at a JSXAttribute
  boundary so a button passed through the `beforeMessage` prop (not the
  render-prop child) is still reported.
- Add tests for all three cases and update README wording.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cover meaningful, dynamic, and statically empty/falsy attribute values,
plus name lookup and spread-attribute handling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

💚 Build Succeeded

History

@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

💚 Build Succeeded

History

@alexwizp

alexwizp commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

@kapral18 could you review it again? I'm a bit skeptical about fixing very specific edge cases in the static analyzer. It seems to me that the important thing here is to strike a balance between real-world and hypothetical cases. Thanks

@alexwizp
alexwizp requested a review from kapral18 July 30, 2026 11:15

@kapral18 kapral18 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM — all three findings fixed, and hasMeaningfulAttr is a better shape than what I suggested: component-agnostic and separately tested. Verified the repros on 4a4fece, including that meaningful/dynamic beforeMessage still behaves as before. Suites green.

On balance vs. hypotheticals: agreed, and I've withdrawn both remaining edge cases. The motivating Kibana case is pivot_function_form.tsx, which carries an eslint-disable for tooltip-button-icon-wrap today — this PR lets us delete it.

@weronikaolejniczak weronikaolejniczak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM! 🟢 Thank you both 🙏🏻

@alexwizp
alexwizp merged commit 6b32c6d into elastic:main Jul 30, 2026
7 checks passed
alexwizp added a commit to elastic/kibana that referenced this pull request Jul 31, 2026
…281965)

## Summary

Updates the `.agents/skills/accessibility` skill for
[elastic/eui#9852](elastic/eui#9852), which
added the `@elastic/eui/no-nested-copy-tooltip` rule and gave
`@elastic/eui/tooltip-button-icon-wrap` an `EuiCopy` exception.

`EuiCopy` already wraps its render-prop child in an `EuiToolTip`, using
`beforeMessage` as that tooltip's content. Wrapping the child in another
`EuiToolTip` nests two tooltips on one anchor; conversely, an
`EuiButtonIcon` inside an `EuiCopy` with a meaningful `beforeMessage`
should *not* be wrapped. Without this update the skill's existing
"always wrap `EuiButtonIcon` with `EuiToolTip`" guidance contradicts the
new rule.

**New:** `references/components/copy_tooltip.md` — canonical pattern
(`beforeMessage` + `aria-label`, no wrapper), common mistakes, and
manual-review cases: no autofix (tooltip `content` and `beforeMessage`
cannot be merged automatically), statically empty/falsy `beforeMessage`
(no tooltip is rendered, so a wrapper is still required), render-prop
roots the rule cannot resolve, and buttons passed through the
`beforeMessage` prop itself.

**Updated:**
- `references/components/index.md` — new guide row.
- `references/eslint.md` — `no-nested-copy-tooltip` row;
`tooltip-button-icon-wrap` row extended with the `EuiCopy` exception.
- `references/components/tooltip_icon.md` — exception callout
(`aria-label` still required, `title` still forbidden).

`SKILL.md` is unchanged — it routes by table, not by rule id.

Note: Kibana pins `@elastic/eslint-plugin-eui` at `2.14.1` and the rule
is not in that release, so this documents the guidance ahead of the
plugin bump. Lint will not flag these patterns until then.

### Checklist

- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)

Not applicable — no user-facing text, no runtime code.
Documentation-only change to an agent skill; no tests, no release note,
no backport.

### Identify risks

None. No product code, configuration, or CI behavior is affected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
alexwizp added a commit to elastic/kibana that referenced this pull request Jul 31, 2026
…elastic/eui/tooltip-button-icon-wrap` rules at the error level (#281458)

## Summary

This PR enforces `@elastic/eui/icon-accessibility-rules` and
`@elastic/eui/tooltip-button-icon-wrap` rules at the error level

- **`@elastic/eui/icon-accessibility-rules`** — Ensure the `EuiIcon`
includes appropriate accessibility attributes.
.`EuiIcon` has an accessible name via `title`, `aria-label`, or
`aria-labelledby`; otherwise mark it decorative with
`aria-hidden={true}`. Do not combine `tabIndex` with `aria-hidden`
- **`@elastic/eui/tooltip-button-icon-wrap`** — Ensure `EuiButtonIcon`
is wrapped with `EuiToolTip` for sighted users. Browser-native tooltips
(the `title` prop) are unstyled, have no delay control, and are not
keyboard-accessible. Every icon button should have a visible tooltip so
that sighted users who do not rely on screen readers can understand its
purpose.

### Changes
- `packages/kbn-eslint-config/.eslintrc.js`
- This PR also includes fixes for newly discovered issues, as well as a
fix for the case where EuiCopy is used with beforeMessage together with
EuiTooltip: elastic/eui#9852

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
mdefazio pushed a commit to mdefazio/kibana that referenced this pull request Aug 3, 2026
…lastic#281965)

## Summary

Updates the `.agents/skills/accessibility` skill for
[elastic/eui#9852](elastic/eui#9852), which
added the `@elastic/eui/no-nested-copy-tooltip` rule and gave
`@elastic/eui/tooltip-button-icon-wrap` an `EuiCopy` exception.

`EuiCopy` already wraps its render-prop child in an `EuiToolTip`, using
`beforeMessage` as that tooltip's content. Wrapping the child in another
`EuiToolTip` nests two tooltips on one anchor; conversely, an
`EuiButtonIcon` inside an `EuiCopy` with a meaningful `beforeMessage`
should *not* be wrapped. Without this update the skill's existing
"always wrap `EuiButtonIcon` with `EuiToolTip`" guidance contradicts the
new rule.

**New:** `references/components/copy_tooltip.md` — canonical pattern
(`beforeMessage` + `aria-label`, no wrapper), common mistakes, and
manual-review cases: no autofix (tooltip `content` and `beforeMessage`
cannot be merged automatically), statically empty/falsy `beforeMessage`
(no tooltip is rendered, so a wrapper is still required), render-prop
roots the rule cannot resolve, and buttons passed through the
`beforeMessage` prop itself.

**Updated:**
- `references/components/index.md` — new guide row.
- `references/eslint.md` — `no-nested-copy-tooltip` row;
`tooltip-button-icon-wrap` row extended with the `EuiCopy` exception.
- `references/components/tooltip_icon.md` — exception callout
(`aria-label` still required, `title` still forbidden).

`SKILL.md` is unchanged — it routes by table, not by rule id.

Note: Kibana pins `@elastic/eslint-plugin-eui` at `2.14.1` and the rule
is not in that release, so this documents the guidance ahead of the
plugin bump. Lint will not flag these patterns until then.

### Checklist

- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)

Not applicable — no user-facing text, no runtime code.
Documentation-only change to an agent skill; no tests, no release note,
no backport.

### Identify risks

None. No product code, configuration, or CI behavior is affected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
mdefazio pushed a commit to mdefazio/kibana that referenced this pull request Aug 3, 2026
…elastic/eui/tooltip-button-icon-wrap` rules at the error level (elastic#281458)

## Summary

This PR enforces `@elastic/eui/icon-accessibility-rules` and
`@elastic/eui/tooltip-button-icon-wrap` rules at the error level

- **`@elastic/eui/icon-accessibility-rules`** — Ensure the `EuiIcon`
includes appropriate accessibility attributes.
.`EuiIcon` has an accessible name via `title`, `aria-label`, or
`aria-labelledby`; otherwise mark it decorative with
`aria-hidden={true}`. Do not combine `tabIndex` with `aria-hidden`
- **`@elastic/eui/tooltip-button-icon-wrap`** — Ensure `EuiButtonIcon`
is wrapped with `EuiToolTip` for sighted users. Browser-native tooltips
(the `title` prop) are unstyled, have no delay control, and are not
keyboard-accessible. Every icon button should have a visible tooltip so
that sighted users who do not rely on screen readers can understand its
purpose.

### Changes
- `packages/kbn-eslint-config/.eslintrc.js`
- This PR also includes fixes for newly discovered issues, as well as a
fix for the case where EuiCopy is used with beforeMessage together with
EuiTooltip: elastic/eui#9852

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
acstll added a commit to elastic/kibana that referenced this pull request Aug 13, 2026
## Dependency updates

`@elastic/eui` - 118.0.0 ⏩ 119.0.0
`@elastic/eslint-plugin-eui` - 2.15.0 ⏩ 2.16.0
`@elastic/eui-test-helpers` - 1.2.0 ⏩ 1.3.0

## Changes

- Added 3 new `EuiFlyoutMenu` i18n tokens
(`euiFlyoutMenu.history.tooltip`, `euiFlyoutMenu.pagination.first`,
`euiFlyoutMenu.pagination.last`) to `i18n_eui_mapping.tsx` and all
translation files
- Replaced removed `plusInCircle` icon alias with `plusCircle` in the ML
plugin (data frame analytics, anomaly detection jobs, and trained models
menus)

## Package updates

### `@elastic/eslint-plugin-eui`
[v2.16.0](https://github.com/elastic/eui/blob/main/packages/eslint-plugin/changelogs/CHANGELOG_2026.md)

- Added new `@elastic/eui/no-nested-copy-tooltip` rule to improve
`EuiCopy` usage ([#9852](elastic/eui#9852))
- Updated `@elastic/eui/tooltip-button-icon-wrap` with an exception for
`EuiCopy` usage covered by `@elastic/eui/no-nested-copy-tooltip`
([#9852](elastic/eui#9852))
- Added `button-group-no-invalid-children` rule
([#9849](elastic/eui#9849))
- Added `no-deprecated-icon-aliases` rule
([#9815](elastic/eui#9815))

### `@elastic/eui`
[v119.0.0](https://github.com/elastic/eui/blob/main/packages/eui/changelogs/CHANGELOG_2026.md)

- Bundled icon glyph files into `dist/svgs/` and added
`dist/eui-icons.json` manifest (mapping icon filename stems to SVG
content strings) ([#9873](elastic/eui#9873))
- Added `hasAriaDisabled` prop to `EuiContextMenuItem`
([#9870](elastic/eui#9870))
- Updated `EuiButtonGroup`:
([#9845](elastic/eui#9845))
- Added new render API via `children` prop that allows passing button
components as children
  - Added `variant` prop (usable only with `children` prop)
- Added `gutterSize` prop (usable only with `children` and
`variant="default"` prop)
- Updated `EuiButton`, `EuiButtonEmpty` and `EuiButtonIcon` to consume a
`EuiButtonContext` allowing the group to control common props
([#9845](elastic/eui#9845))
- Updated `EuiFlyoutMenu`:
([#9856](elastic/eui#9856))
- Added `leadingActions` and `trailingActions` props, which accept the
new `EuiFlyoutMenuAction` type supporting `toolTipContent` and
`toolTipProps`
  - Changed the history trigger icon to `clockCounter`
  - Added control-group dividers between built-in controls
- Added `onFirst`, `onLast` to `pagination`, which render optional
buttons for jumping to the beginning and end of the list.
- Deprecated additional `EuiIcon` types that are not represented in
Figma ([#9815](elastic/eui#9815))

**Bug fixes**

- Fixed the missing type declaration for the `focusEuiToolTipTrigger`
test helper ([#9870](elastic/eui#9870))
- Fixed generated icon IDs to remain stable during server-side rendering
([#9866](elastic/eui#9866))
- Fixed a visual bug in `EuiButtonGroup` that rendered duplicate borders
on disabled buttons ([#9845](elastic/eui#9845))
- The `EuiFlyoutMenu` history popover now only appears when
`historyItems` has more than one entry. When there is a single entry in
history, only the Back button is shown.
([#9856](elastic/eui#9856))
- Fixed `EuiFlyoutMenu` pagination controls disappearing when
`pagination.total` is `1`; the controls now render (as "1 of 1" with
both Prev/Next disabled) for any `total` of at least `1`
([#9856](elastic/eui#9856))

**Deprecations**

- Deprecated `customActions` and `EuiFlyoutMenuCustomAction` in
`EuiFlyoutMenu`; use `trailingActions` and `EuiFlyoutMenuAction` instead
([#9856](elastic/eui#9856))

**Breaking changes**

- Removed most deprecated `EuiIcon` types and their icon assets. 16
widely-used deprecated aliases (e.g. `alert`, `search`, `visPie`) remain
temporarily and will be removed in a future release
([#9832](elastic/eui#9832))
([#9815](elastic/eui#9815))

### `@elastic/eui-test-helpers`
[v1.3.0](https://github.com/elastic/eui/blob/main/packages/test-helpers/changelogs/CHANGELOG_2026.md)

- Added `EuiDataGridObject` with `rows`, `cell()`, `cells()`,
`doActionOnColumn()` and `openFullScreenMode()`/`closeFullScreenMode()`
([#9874](elastic/eui#9874))
- Added `EuiSuperSelectObject` with `selectOptionByValue()`,
`selectOptionByLabel()` and `getSelectedValue()`
([#9874](elastic/eui#9874))
- Added `EuiGlobalToastListObject` with a `toasts` locator and
`closeAll()` ([#9874](elastic/eui#9874))

---------

Co-authored-by: Lene Gadewoll <lene.gadewoll@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
qn895 pushed a commit to qn895/kibana that referenced this pull request Aug 13, 2026
## Dependency updates

`@elastic/eui` - 118.0.0 ⏩ 119.0.0
`@elastic/eslint-plugin-eui` - 2.15.0 ⏩ 2.16.0
`@elastic/eui-test-helpers` - 1.2.0 ⏩ 1.3.0

## Changes

- Added 3 new `EuiFlyoutMenu` i18n tokens
(`euiFlyoutMenu.history.tooltip`, `euiFlyoutMenu.pagination.first`,
`euiFlyoutMenu.pagination.last`) to `i18n_eui_mapping.tsx` and all
translation files
- Replaced removed `plusInCircle` icon alias with `plusCircle` in the ML
plugin (data frame analytics, anomaly detection jobs, and trained models
menus)

## Package updates

### `@elastic/eslint-plugin-eui`
[v2.16.0](https://github.com/elastic/eui/blob/main/packages/eslint-plugin/changelogs/CHANGELOG_2026.md)

- Added new `@elastic/eui/no-nested-copy-tooltip` rule to improve
`EuiCopy` usage ([elastic#9852](elastic/eui#9852))
- Updated `@elastic/eui/tooltip-button-icon-wrap` with an exception for
`EuiCopy` usage covered by `@elastic/eui/no-nested-copy-tooltip`
([elastic#9852](elastic/eui#9852))
- Added `button-group-no-invalid-children` rule
([elastic#9849](elastic/eui#9849))
- Added `no-deprecated-icon-aliases` rule
([elastic#9815](elastic/eui#9815))

### `@elastic/eui`
[v119.0.0](https://github.com/elastic/eui/blob/main/packages/eui/changelogs/CHANGELOG_2026.md)

- Bundled icon glyph files into `dist/svgs/` and added
`dist/eui-icons.json` manifest (mapping icon filename stems to SVG
content strings) ([elastic#9873](elastic/eui#9873))
- Added `hasAriaDisabled` prop to `EuiContextMenuItem`
([elastic#9870](elastic/eui#9870))
- Updated `EuiButtonGroup`:
([elastic#9845](elastic/eui#9845))
- Added new render API via `children` prop that allows passing button
components as children
  - Added `variant` prop (usable only with `children` prop)
- Added `gutterSize` prop (usable only with `children` and
`variant="default"` prop)
- Updated `EuiButton`, `EuiButtonEmpty` and `EuiButtonIcon` to consume a
`EuiButtonContext` allowing the group to control common props
([elastic#9845](elastic/eui#9845))
- Updated `EuiFlyoutMenu`:
([elastic#9856](elastic/eui#9856))
- Added `leadingActions` and `trailingActions` props, which accept the
new `EuiFlyoutMenuAction` type supporting `toolTipContent` and
`toolTipProps`
  - Changed the history trigger icon to `clockCounter`
  - Added control-group dividers between built-in controls
- Added `onFirst`, `onLast` to `pagination`, which render optional
buttons for jumping to the beginning and end of the list.
- Deprecated additional `EuiIcon` types that are not represented in
Figma ([elastic#9815](elastic/eui#9815))

**Bug fixes**

- Fixed the missing type declaration for the `focusEuiToolTipTrigger`
test helper ([elastic#9870](elastic/eui#9870))
- Fixed generated icon IDs to remain stable during server-side rendering
([elastic#9866](elastic/eui#9866))
- Fixed a visual bug in `EuiButtonGroup` that rendered duplicate borders
on disabled buttons ([elastic#9845](elastic/eui#9845))
- The `EuiFlyoutMenu` history popover now only appears when
`historyItems` has more than one entry. When there is a single entry in
history, only the Back button is shown.
([elastic#9856](elastic/eui#9856))
- Fixed `EuiFlyoutMenu` pagination controls disappearing when
`pagination.total` is `1`; the controls now render (as "1 of 1" with
both Prev/Next disabled) for any `total` of at least `1`
([elastic#9856](elastic/eui#9856))

**Deprecations**

- Deprecated `customActions` and `EuiFlyoutMenuCustomAction` in
`EuiFlyoutMenu`; use `trailingActions` and `EuiFlyoutMenuAction` instead
([elastic#9856](elastic/eui#9856))

**Breaking changes**

- Removed most deprecated `EuiIcon` types and their icon assets. 16
widely-used deprecated aliases (e.g. `alert`, `search`, `visPie`) remain
temporarily and will be removed in a future release
([elastic#9832](elastic/eui#9832))
([elastic#9815](elastic/eui#9815))

### `@elastic/eui-test-helpers`
[v1.3.0](https://github.com/elastic/eui/blob/main/packages/test-helpers/changelogs/CHANGELOG_2026.md)

- Added `EuiDataGridObject` with `rows`, `cell()`, `cells()`,
`doActionOnColumn()` and `openFullScreenMode()`/`closeFullScreenMode()`
([elastic#9874](elastic/eui#9874))
- Added `EuiSuperSelectObject` with `selectOptionByValue()`,
`selectOptionByLabel()` and `getSelectedValue()`
([elastic#9874](elastic/eui#9874))
- Added `EuiGlobalToastListObject` with a `toasts` locator and
`closeAll()` ([elastic#9874](elastic/eui#9874))

---------

Co-authored-by: Lene Gadewoll <lene.gadewoll@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
patrykkopycinski pushed a commit to patrykkopycinski/kibana that referenced this pull request Aug 18, 2026
## Dependency updates

`@elastic/eui` - 118.0.0 ⏩ 119.0.0
`@elastic/eslint-plugin-eui` - 2.15.0 ⏩ 2.16.0
`@elastic/eui-test-helpers` - 1.2.0 ⏩ 1.3.0

## Changes

- Added 3 new `EuiFlyoutMenu` i18n tokens
(`euiFlyoutMenu.history.tooltip`, `euiFlyoutMenu.pagination.first`,
`euiFlyoutMenu.pagination.last`) to `i18n_eui_mapping.tsx` and all
translation files
- Replaced removed `plusInCircle` icon alias with `plusCircle` in the ML
plugin (data frame analytics, anomaly detection jobs, and trained models
menus)

## Package updates

### `@elastic/eslint-plugin-eui`
[v2.16.0](https://github.com/elastic/eui/blob/main/packages/eslint-plugin/changelogs/CHANGELOG_2026.md)

- Added new `@elastic/eui/no-nested-copy-tooltip` rule to improve
`EuiCopy` usage ([elastic#9852](elastic/eui#9852))
- Updated `@elastic/eui/tooltip-button-icon-wrap` with an exception for
`EuiCopy` usage covered by `@elastic/eui/no-nested-copy-tooltip`
([elastic#9852](elastic/eui#9852))
- Added `button-group-no-invalid-children` rule
([elastic#9849](elastic/eui#9849))
- Added `no-deprecated-icon-aliases` rule
([elastic#9815](elastic/eui#9815))

### `@elastic/eui`
[v119.0.0](https://github.com/elastic/eui/blob/main/packages/eui/changelogs/CHANGELOG_2026.md)

- Bundled icon glyph files into `dist/svgs/` and added
`dist/eui-icons.json` manifest (mapping icon filename stems to SVG
content strings) ([elastic#9873](elastic/eui#9873))
- Added `hasAriaDisabled` prop to `EuiContextMenuItem`
([elastic#9870](elastic/eui#9870))
- Updated `EuiButtonGroup`:
([elastic#9845](elastic/eui#9845))
- Added new render API via `children` prop that allows passing button
components as children
  - Added `variant` prop (usable only with `children` prop)
- Added `gutterSize` prop (usable only with `children` and
`variant="default"` prop)
- Updated `EuiButton`, `EuiButtonEmpty` and `EuiButtonIcon` to consume a
`EuiButtonContext` allowing the group to control common props
([elastic#9845](elastic/eui#9845))
- Updated `EuiFlyoutMenu`:
([elastic#9856](elastic/eui#9856))
- Added `leadingActions` and `trailingActions` props, which accept the
new `EuiFlyoutMenuAction` type supporting `toolTipContent` and
`toolTipProps`
  - Changed the history trigger icon to `clockCounter`
  - Added control-group dividers between built-in controls
- Added `onFirst`, `onLast` to `pagination`, which render optional
buttons for jumping to the beginning and end of the list.
- Deprecated additional `EuiIcon` types that are not represented in
Figma ([elastic#9815](elastic/eui#9815))

**Bug fixes**

- Fixed the missing type declaration for the `focusEuiToolTipTrigger`
test helper ([elastic#9870](elastic/eui#9870))
- Fixed generated icon IDs to remain stable during server-side rendering
([elastic#9866](elastic/eui#9866))
- Fixed a visual bug in `EuiButtonGroup` that rendered duplicate borders
on disabled buttons ([elastic#9845](elastic/eui#9845))
- The `EuiFlyoutMenu` history popover now only appears when
`historyItems` has more than one entry. When there is a single entry in
history, only the Back button is shown.
([elastic#9856](elastic/eui#9856))
- Fixed `EuiFlyoutMenu` pagination controls disappearing when
`pagination.total` is `1`; the controls now render (as "1 of 1" with
both Prev/Next disabled) for any `total` of at least `1`
([elastic#9856](elastic/eui#9856))

**Deprecations**

- Deprecated `customActions` and `EuiFlyoutMenuCustomAction` in
`EuiFlyoutMenu`; use `trailingActions` and `EuiFlyoutMenuAction` instead
([elastic#9856](elastic/eui#9856))

**Breaking changes**

- Removed most deprecated `EuiIcon` types and their icon assets. 16
widely-used deprecated aliases (e.g. `alert`, `search`, `visPie`) remain
temporarily and will be removed in a future release
([elastic#9832](elastic/eui#9832))
([elastic#9815](elastic/eui#9815))

### `@elastic/eui-test-helpers`
[v1.3.0](https://github.com/elastic/eui/blob/main/packages/test-helpers/changelogs/CHANGELOG_2026.md)

- Added `EuiDataGridObject` with `rows`, `cell()`, `cells()`,
`doActionOnColumn()` and `openFullScreenMode()`/`closeFullScreenMode()`
([elastic#9874](elastic/eui#9874))
- Added `EuiSuperSelectObject` with `selectOptionByValue()`,
`selectOptionByLabel()` and `getSelectedValue()`
([elastic#9874](elastic/eui#9874))
- Added `EuiGlobalToastListObject` with a `toasts` locator and
`closeAll()` ([elastic#9874](elastic/eui#9874))

---------

Co-authored-by: Lene Gadewoll <lene.gadewoll@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
patrykkopycinski pushed a commit to patrykkopycinski/kibana that referenced this pull request Aug 18, 2026
## Dependency updates

`@elastic/eui` - 118.0.0 ⏩ 119.0.0
`@elastic/eslint-plugin-eui` - 2.15.0 ⏩ 2.16.0
`@elastic/eui-test-helpers` - 1.2.0 ⏩ 1.3.0

## Changes

- Added 3 new `EuiFlyoutMenu` i18n tokens
(`euiFlyoutMenu.history.tooltip`, `euiFlyoutMenu.pagination.first`,
`euiFlyoutMenu.pagination.last`) to `i18n_eui_mapping.tsx` and all
translation files
- Replaced removed `plusInCircle` icon alias with `plusCircle` in the ML
plugin (data frame analytics, anomaly detection jobs, and trained models
menus)

## Package updates

### `@elastic/eslint-plugin-eui`
[v2.16.0](https://github.com/elastic/eui/blob/main/packages/eslint-plugin/changelogs/CHANGELOG_2026.md)

- Added new `@elastic/eui/no-nested-copy-tooltip` rule to improve
`EuiCopy` usage ([elastic#9852](elastic/eui#9852))
- Updated `@elastic/eui/tooltip-button-icon-wrap` with an exception for
`EuiCopy` usage covered by `@elastic/eui/no-nested-copy-tooltip`
([elastic#9852](elastic/eui#9852))
- Added `button-group-no-invalid-children` rule
([elastic#9849](elastic/eui#9849))
- Added `no-deprecated-icon-aliases` rule
([elastic#9815](elastic/eui#9815))

### `@elastic/eui`
[v119.0.0](https://github.com/elastic/eui/blob/main/packages/eui/changelogs/CHANGELOG_2026.md)

- Bundled icon glyph files into `dist/svgs/` and added
`dist/eui-icons.json` manifest (mapping icon filename stems to SVG
content strings) ([elastic#9873](elastic/eui#9873))
- Added `hasAriaDisabled` prop to `EuiContextMenuItem`
([elastic#9870](elastic/eui#9870))
- Updated `EuiButtonGroup`:
([elastic#9845](elastic/eui#9845))
- Added new render API via `children` prop that allows passing button
components as children
  - Added `variant` prop (usable only with `children` prop)
- Added `gutterSize` prop (usable only with `children` and
`variant="default"` prop)
- Updated `EuiButton`, `EuiButtonEmpty` and `EuiButtonIcon` to consume a
`EuiButtonContext` allowing the group to control common props
([elastic#9845](elastic/eui#9845))
- Updated `EuiFlyoutMenu`:
([elastic#9856](elastic/eui#9856))
- Added `leadingActions` and `trailingActions` props, which accept the
new `EuiFlyoutMenuAction` type supporting `toolTipContent` and
`toolTipProps`
  - Changed the history trigger icon to `clockCounter`
  - Added control-group dividers between built-in controls
- Added `onFirst`, `onLast` to `pagination`, which render optional
buttons for jumping to the beginning and end of the list.
- Deprecated additional `EuiIcon` types that are not represented in
Figma ([elastic#9815](elastic/eui#9815))

**Bug fixes**

- Fixed the missing type declaration for the `focusEuiToolTipTrigger`
test helper ([elastic#9870](elastic/eui#9870))
- Fixed generated icon IDs to remain stable during server-side rendering
([elastic#9866](elastic/eui#9866))
- Fixed a visual bug in `EuiButtonGroup` that rendered duplicate borders
on disabled buttons ([elastic#9845](elastic/eui#9845))
- The `EuiFlyoutMenu` history popover now only appears when
`historyItems` has more than one entry. When there is a single entry in
history, only the Back button is shown.
([elastic#9856](elastic/eui#9856))
- Fixed `EuiFlyoutMenu` pagination controls disappearing when
`pagination.total` is `1`; the controls now render (as "1 of 1" with
both Prev/Next disabled) for any `total` of at least `1`
([elastic#9856](elastic/eui#9856))

**Deprecations**

- Deprecated `customActions` and `EuiFlyoutMenuCustomAction` in
`EuiFlyoutMenu`; use `trailingActions` and `EuiFlyoutMenuAction` instead
([elastic#9856](elastic/eui#9856))

**Breaking changes**

- Removed most deprecated `EuiIcon` types and their icon assets. 16
widely-used deprecated aliases (e.g. `alert`, `search`, `visPie`) remain
temporarily and will be removed in a future release
([elastic#9832](elastic/eui#9832))
([elastic#9815](elastic/eui#9815))

### `@elastic/eui-test-helpers`
[v1.3.0](https://github.com/elastic/eui/blob/main/packages/test-helpers/changelogs/CHANGELOG_2026.md)

- Added `EuiDataGridObject` with `rows`, `cell()`, `cells()`,
`doActionOnColumn()` and `openFullScreenMode()`/`closeFullScreenMode()`
([elastic#9874](elastic/eui#9874))
- Added `EuiSuperSelectObject` with `selectOptionByValue()`,
`selectOptionByLabel()` and `getSelectedValue()`
([elastic#9874](elastic/eui#9874))
- Added `EuiGlobalToastListObject` with a `toasts` locator and
`closeAll()` ([elastic#9874](elastic/eui#9874))

---------

Co-authored-by: Lene Gadewoll <lene.gadewoll@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants