@elastic/eui 113.0.0 → 113.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -246,7 +246,7 @@ EuiBreadcrumbContent.propTypes = {
246
246
  * however, the popover will attempt to reposition itself along the secondary
247
247
  * cross axis if there is room there instead.
248
248
  *
249
- * If you do not not want this repositioning to occur (and it is acceptable for
249
+ * If you do not want this repositioning to occur (and it is acceptable for
250
250
  * the popover to appear offscreen), set this to false to disable this behavior.
251
251
  *
252
252
  * @default true
@@ -257,7 +257,7 @@ EuiBreadcrumbs.propTypes = {
257
257
  * however, the popover will attempt to reposition itself along the secondary
258
258
  * cross axis if there is room there instead.
259
259
  *
260
- * If you do not not want this repositioning to occur (and it is acceptable for
260
+ * If you do not want this repositioning to occur (and it is acceptable for
261
261
  * the popover to appear offscreen), set this to false to disable this behavior.
262
262
  *
263
263
  * @default true
@@ -46,7 +46,8 @@ var BackButton = function BackButton(props) {
46
46
  return ___EmotionJSX(EuiButtonEmpty, _extends({
47
47
  size: "xs",
48
48
  color: "text",
49
- iconType: "editorUndo"
49
+ iconType: "editorUndo",
50
+ "data-test-subj": "euiFlyoutMenuBackButton"
50
51
  }, props), ___EmotionJSX(EuiI18n, {
51
52
  token: "euiFlyoutMenu.back",
52
53
  default: "Back"
@@ -65,7 +66,8 @@ var HistoryPopover = function HistoryPopover(_ref) {
65
66
  button: ___EmotionJSX(EuiButtonIcon, {
66
67
  iconType: "arrowDown",
67
68
  color: "text",
68
- "aria-label": useEuiI18n('euiFlyoutMenu.history', 'History')
69
+ "aria-label": useEuiI18n('euiFlyoutMenu.history', 'History'),
70
+ "data-test-subj": "euiFlyoutMenuHistoryButton"
69
71
  }),
70
72
  isOpen: isPopoverOpen,
71
73
  onClick: handlePopoverButtonClick,
@@ -84,7 +86,8 @@ var HistoryPopover = function HistoryPopover(_ref) {
84
86
  onClick: function onClick() {
85
87
  item.onClick();
86
88
  setIsPopoverOpen(false);
87
- }
89
+ },
90
+ "data-test-subj": "euiFlyoutMenuHistoryItem-".concat(index)
88
91
  }, item.title);
89
92
  })));
90
93
  };
@@ -203,7 +203,7 @@ EuiHeaderBreadcrumbs.propTypes = {
203
203
  * however, the popover will attempt to reposition itself along the secondary
204
204
  * cross axis if there is room there instead.
205
205
  *
206
- * If you do not not want this repositioning to occur (and it is acceptable for
206
+ * If you do not want this repositioning to occur (and it is acceptable for
207
207
  * the popover to appear offscreen), set this to false to disable this behavior.
208
208
  *
209
209
  * @default true
@@ -240,7 +240,7 @@ EuiHeaderLinks.propTypes = {
240
240
  * however, the popover will attempt to reposition itself along the secondary
241
241
  * cross axis if there is room there instead.
242
242
  *
243
- * If you do not not want this repositioning to occur (and it is acceptable for
243
+ * If you do not want this repositioning to occur (and it is acceptable for
244
244
  * the popover to appear offscreen), set this to false to disable this behavior.
245
245
  *
246
246
  * @default true
@@ -417,7 +417,7 @@ EuiPageHeaderContent.propTypes = {
417
417
  * however, the popover will attempt to reposition itself along the secondary
418
418
  * cross axis if there is room there instead.
419
419
  *
420
- * If you do not not want this repositioning to occur (and it is acceptable for
420
+ * If you do not want this repositioning to occur (and it is acceptable for
421
421
  * the popover to appear offscreen), set this to false to disable this behavior.
422
422
  *
423
423
  * @default true
@@ -112,7 +112,9 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
112
112
  _defineProperty(_this, "closingTransitionAnimationFrame", void 0);
113
113
  _defineProperty(_this, "button", null);
114
114
  _defineProperty(_this, "panel", null);
115
- _defineProperty(_this, "descriptionId", htmlIdGenerator()());
115
+ _defineProperty(_this, "idGenerator", htmlIdGenerator('euiPopover'));
116
+ _defineProperty(_this, "panelId", _this.idGenerator('panelId'));
117
+ _defineProperty(_this, "descriptionId", _this.idGenerator('descriptionId'));
116
118
  _defineProperty(_this, "closePopover", function () {
117
119
  if (_this.props.isOpen) {
118
120
  _this.props.closePopover();
@@ -126,6 +128,19 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
126
128
  _this.handleStrandedFocus();
127
129
  }
128
130
  });
131
+ _defineProperty(_this, "getFocusableToggleButton", function () {
132
+ if (_this.button) {
133
+ try {
134
+ var focusableItems = focusable(_this.button);
135
+ if (focusableItems.length) {
136
+ return focusableItems[0];
137
+ }
138
+ } catch (_unused) {
139
+ // tabbable's focusable() can throw in environments that don't
140
+ // fully support CSS selector parsing (e.g. jsdom with :has())
141
+ }
142
+ }
143
+ });
129
144
  _defineProperty(_this, "handleStrandedFocus", function () {
130
145
  _this.strandedFocusTimeout = window.setTimeout(function () {
131
146
  var _this$panel;
@@ -135,11 +150,10 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
135
150
  // it will be on the panel instead on mount when isOpen=true
136
151
  if (document.activeElement === document.body || (_this$panel = _this.panel) !== null && _this$panel !== void 0 && _this$panel.contains(document.activeElement) // if focus is on OR within this.panel
137
152
  ) {
138
- if (!_this.button) return;
139
- var focusableItems = focusable(_this.button);
140
- if (!focusableItems.length) return;
141
- var toggleButton = focusableItems[0];
142
- toggleButton.focus(returnFocusConfig);
153
+ var toggleButton = _this.getFocusableToggleButton();
154
+ if (toggleButton) {
155
+ toggleButton.focus(returnFocusConfig);
156
+ }
143
157
  }
144
158
  }, closingTransitionTime);
145
159
  });
@@ -195,6 +209,25 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
195
209
  });
196
210
  }, durationMatch + delayMatch);
197
211
  });
212
+ /**
213
+ * Updates ARIA attributes on the popover trigger button
214
+ * Only applies ARIA when the trigger is button-like (semantic <button> or role="button").
215
+ * Avoids adding incorrect ARIA on inputs or other non-button elements.
216
+ */
217
+ _defineProperty(_this, "updateTriggerButtonAriaAttributes", function (toggleButton, isOpen) {
218
+ var _toggleButton$tagName, _toggleButton$getAttr;
219
+ if (!toggleButton) return;
220
+ var tag = (_toggleButton$tagName = toggleButton.tagName) === null || _toggleButton$tagName === void 0 ? void 0 : _toggleButton$tagName.toLowerCase();
221
+ var role = (_toggleButton$getAttr = toggleButton.getAttribute('role')) === null || _toggleButton$getAttr === void 0 ? void 0 : _toggleButton$getAttr.toLowerCase();
222
+ var isButtonLike = tag === 'button' || role === 'button';
223
+ if (!isButtonLike) return;
224
+ toggleButton.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
225
+ if (isOpen) {
226
+ toggleButton.setAttribute('aria-controls', _this.panelId);
227
+ } else {
228
+ toggleButton.removeAttribute('aria-controls');
229
+ }
230
+ });
198
231
  _defineProperty(_this, "onMutation", function (records) {
199
232
  var waitDuration = getWaitDuration(records);
200
233
  _this.positionPopoverFixed();
@@ -314,7 +347,8 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
314
347
  return _createClass(EuiPopover, [{
315
348
  key: "componentDidMount",
316
349
  value: function componentDidMount() {
317
- var _this2 = this;
350
+ var _this2 = this,
351
+ _this$props$isOpen;
318
352
  if (this.state.suppressingPopover) {
319
353
  // component was created with isOpen=true; now that it's mounted
320
354
  // stop suppressing and start opening
@@ -325,6 +359,7 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
325
359
  _this2.onOpenPopover();
326
360
  });
327
361
  }
362
+ this.updateTriggerButtonAriaAttributes(this.getFocusableToggleButton(), (_this$props$isOpen = this.props.isOpen) !== null && _this$props$isOpen !== void 0 ? _this$props$isOpen : false);
328
363
  this.repositionOnScroll.subscribe();
329
364
  }
330
365
  }, {
@@ -336,6 +371,12 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
336
371
  this.onOpenPopover();
337
372
  }
338
373
 
374
+ // Update ARIA attributes on the toggle when open state changes
375
+ if (prevProps.isOpen !== this.props.isOpen) {
376
+ var _this$props$isOpen2;
377
+ this.updateTriggerButtonAriaAttributes(this.getFocusableToggleButton(), (_this$props$isOpen2 = this.props.isOpen) !== null && _this$props$isOpen2 !== void 0 ? _this$props$isOpen2 : false);
378
+ }
379
+
339
380
  // ensure recalculation of panel position on prop updates
340
381
  if (this.props.isOpen && (prevProps.anchorPosition !== this.props.anchorPosition || prevProps.buffer !== this.props.buffer || prevProps.offset !== this.props.offset || prevProps.panelPaddingSize !== this.props.panelPaddingSize)) {
341
382
  this.positionPopoverFluid();
@@ -455,7 +496,9 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
455
496
  initialFocus: initialFocus,
456
497
  onEscapeKey: this.onEscapeKey,
457
498
  disabled: !ownFocus || !this.state.isOpenStable || this.state.isClosing
458
- }, focusTrapProps), ___EmotionJSX(EuiPopoverPanel, _extends({}, panelProps, {
499
+ }, focusTrapProps), ___EmotionJSX(EuiPopoverPanel, _extends({
500
+ id: this.panelId
501
+ }, panelProps, {
459
502
  panelRef: this.panelRef,
460
503
  isOpen: this.state.isOpening,
461
504
  position: this.state.arrowPosition,
@@ -664,7 +707,7 @@ EuiPopover.propTypes = {
664
707
  * however, the popover will attempt to reposition itself along the secondary
665
708
  * cross axis if there is room there instead.
666
709
  *
667
- * If you do not not want this repositioning to occur (and it is acceptable for
710
+ * If you do not want this repositioning to occur (and it is acceptable for
668
711
  * the popover to appear offscreen), set this to false to disable this behavior.
669
712
  *
670
713
  * @default true
@@ -254,7 +254,7 @@ EuiTourStep.propTypes = {
254
254
  * however, the popover will attempt to reposition itself along the secondary
255
255
  * cross axis if there is room there instead.
256
256
  *
257
- * If you do not not want this repositioning to occur (and it is acceptable for
257
+ * If you do not want this repositioning to occur (and it is acceptable for
258
258
  * the popover to appear offscreen), set this to false to disable this behavior.
259
259
  *
260
260
  * @default true
package/eui.d.ts CHANGED
@@ -14525,6 +14525,7 @@ declare module '@elastic/eui/src/components/popover/popover_panel' {
14525
14525
  }
14526
14526
  declare module '@elastic/eui/src/components/popover/popover' {
14527
14527
  import React, { Component, KeyboardEvent, CSSProperties, HTMLAttributes, ReactNode, Ref, RefCallback, PropsWithChildren, ContextType } from 'react';
14528
+ import { type FocusableElement } from 'tabbable';
14528
14529
  import { CommonProps, NoArgCallback } from '@elastic/eui/src/components/common';
14529
14530
  import { FocusTarget, EuiFocusTrapProps } from '@elastic/eui/src/components/focus_trap';
14530
14531
  import { EuiPopoverPosition } from '@elastic/eui/src/services/popover';
@@ -14632,7 +14633,7 @@ declare module '@elastic/eui/src/components/popover/popover' {
14632
14633
  * however, the popover will attempt to reposition itself along the secondary
14633
14634
  * cross axis if there is room there instead.
14634
14635
  *
14635
- * If you do not not want this repositioning to occur (and it is acceptable for
14636
+ * If you do not want this repositioning to occur (and it is acceptable for
14636
14637
  * the popover to appear offscreen), set this to false to disable this behavior.
14637
14638
  *
14638
14639
  * @default true
@@ -14708,14 +14709,23 @@ declare module '@elastic/eui/src/components/popover/popover' {
14708
14709
  private closingTransitionAnimationFrame;
14709
14710
  private button;
14710
14711
  private panel;
14712
+ private idGenerator;
14713
+ private panelId;
14711
14714
  private descriptionId;
14712
14715
  constructor(props: Props);
14713
14716
  closePopover: () => void;
14714
14717
  onEscapeKey: (event: Event) => void;
14718
+ getFocusableToggleButton: () => FocusableElement | undefined;
14715
14719
  handleStrandedFocus: () => void;
14716
14720
  onKeyDown: (event: KeyboardEvent) => void;
14717
14721
  onClickOutside: (event: Event) => void;
14718
14722
  onOpenPopover: () => void;
14723
+ /**
14724
+ * Updates ARIA attributes on the popover trigger button
14725
+ * Only applies ARIA when the trigger is button-like (semantic <button> or role="button").
14726
+ * Avoids adding incorrect ARIA on inputs or other non-button elements.
14727
+ */
14728
+ private updateTriggerButtonAriaAttributes;
14719
14729
  componentDidMount(): void;
14720
14730
  componentDidUpdate(prevProps: Props): void;
14721
14731
  componentWillUnmount(): void;
@@ -255,7 +255,7 @@ EuiBreadcrumbContent.propTypes = {
255
255
  * however, the popover will attempt to reposition itself along the secondary
256
256
  * cross axis if there is room there instead.
257
257
  *
258
- * If you do not not want this repositioning to occur (and it is acceptable for
258
+ * If you do not want this repositioning to occur (and it is acceptable for
259
259
  * the popover to appear offscreen), set this to false to disable this behavior.
260
260
  *
261
261
  * @default true
@@ -48,7 +48,8 @@ var BackButton = function BackButton(props) {
48
48
  return (0, _react2.jsx)(_button.EuiButtonEmpty, _extends({
49
49
  size: "xs",
50
50
  color: "text",
51
- iconType: "editorUndo"
51
+ iconType: "editorUndo",
52
+ "data-test-subj": "euiFlyoutMenuBackButton"
52
53
  }, props), (0, _react2.jsx)(_i18n.EuiI18n, {
53
54
  token: "euiFlyoutMenu.back",
54
55
  default: "Back"
@@ -67,7 +68,8 @@ var HistoryPopover = function HistoryPopover(_ref) {
67
68
  button: (0, _react2.jsx)(_button.EuiButtonIcon, {
68
69
  iconType: "arrowDown",
69
70
  color: "text",
70
- "aria-label": (0, _i18n.useEuiI18n)('euiFlyoutMenu.history', 'History')
71
+ "aria-label": (0, _i18n.useEuiI18n)('euiFlyoutMenu.history', 'History'),
72
+ "data-test-subj": "euiFlyoutMenuHistoryButton"
71
73
  }),
72
74
  isOpen: isPopoverOpen,
73
75
  onClick: handlePopoverButtonClick,
@@ -86,7 +88,8 @@ var HistoryPopover = function HistoryPopover(_ref) {
86
88
  onClick: function onClick() {
87
89
  item.onClick();
88
90
  setIsPopoverOpen(false);
89
- }
91
+ },
92
+ "data-test-subj": "euiFlyoutMenuHistoryItem-".concat(index)
90
93
  }, item.title);
91
94
  })));
92
95
  };
@@ -121,7 +121,9 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
121
121
  _defineProperty(_this, "closingTransitionAnimationFrame", void 0);
122
122
  _defineProperty(_this, "button", null);
123
123
  _defineProperty(_this, "panel", null);
124
- _defineProperty(_this, "descriptionId", (0, _services.htmlIdGenerator)()());
124
+ _defineProperty(_this, "idGenerator", (0, _services.htmlIdGenerator)('euiPopover'));
125
+ _defineProperty(_this, "panelId", _this.idGenerator('panelId'));
126
+ _defineProperty(_this, "descriptionId", _this.idGenerator('descriptionId'));
125
127
  _defineProperty(_this, "closePopover", function () {
126
128
  if (_this.props.isOpen) {
127
129
  _this.props.closePopover();
@@ -135,6 +137,19 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
135
137
  _this.handleStrandedFocus();
136
138
  }
137
139
  });
140
+ _defineProperty(_this, "getFocusableToggleButton", function () {
141
+ if (_this.button) {
142
+ try {
143
+ var focusableItems = (0, _tabbable.focusable)(_this.button);
144
+ if (focusableItems.length) {
145
+ return focusableItems[0];
146
+ }
147
+ } catch (_unused) {
148
+ // tabbable's focusable() can throw in environments that don't
149
+ // fully support CSS selector parsing (e.g. jsdom with :has())
150
+ }
151
+ }
152
+ });
138
153
  _defineProperty(_this, "handleStrandedFocus", function () {
139
154
  _this.strandedFocusTimeout = window.setTimeout(function () {
140
155
  var _this$panel;
@@ -144,11 +159,10 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
144
159
  // it will be on the panel instead on mount when isOpen=true
145
160
  if (document.activeElement === document.body || (_this$panel = _this.panel) !== null && _this$panel !== void 0 && _this$panel.contains(document.activeElement) // if focus is on OR within this.panel
146
161
  ) {
147
- if (!_this.button) return;
148
- var focusableItems = (0, _tabbable.focusable)(_this.button);
149
- if (!focusableItems.length) return;
150
- var toggleButton = focusableItems[0];
151
- toggleButton.focus(returnFocusConfig);
162
+ var toggleButton = _this.getFocusableToggleButton();
163
+ if (toggleButton) {
164
+ toggleButton.focus(returnFocusConfig);
165
+ }
152
166
  }
153
167
  }, closingTransitionTime);
154
168
  });
@@ -204,6 +218,25 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
204
218
  });
205
219
  }, durationMatch + delayMatch);
206
220
  });
221
+ /**
222
+ * Updates ARIA attributes on the popover trigger button
223
+ * Only applies ARIA when the trigger is button-like (semantic <button> or role="button").
224
+ * Avoids adding incorrect ARIA on inputs or other non-button elements.
225
+ */
226
+ _defineProperty(_this, "updateTriggerButtonAriaAttributes", function (toggleButton, isOpen) {
227
+ var _toggleButton$tagName, _toggleButton$getAttr;
228
+ if (!toggleButton) return;
229
+ var tag = (_toggleButton$tagName = toggleButton.tagName) === null || _toggleButton$tagName === void 0 ? void 0 : _toggleButton$tagName.toLowerCase();
230
+ var role = (_toggleButton$getAttr = toggleButton.getAttribute('role')) === null || _toggleButton$getAttr === void 0 ? void 0 : _toggleButton$getAttr.toLowerCase();
231
+ var isButtonLike = tag === 'button' || role === 'button';
232
+ if (!isButtonLike) return;
233
+ toggleButton.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
234
+ if (isOpen) {
235
+ toggleButton.setAttribute('aria-controls', _this.panelId);
236
+ } else {
237
+ toggleButton.removeAttribute('aria-controls');
238
+ }
239
+ });
207
240
  _defineProperty(_this, "onMutation", function (records) {
208
241
  var waitDuration = (0, _services.getWaitDuration)(records);
209
242
  _this.positionPopoverFixed();
@@ -323,7 +356,8 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
323
356
  return _createClass(EuiPopover, [{
324
357
  key: "componentDidMount",
325
358
  value: function componentDidMount() {
326
- var _this2 = this;
359
+ var _this2 = this,
360
+ _this$props$isOpen;
327
361
  if (this.state.suppressingPopover) {
328
362
  // component was created with isOpen=true; now that it's mounted
329
363
  // stop suppressing and start opening
@@ -334,6 +368,7 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
334
368
  _this2.onOpenPopover();
335
369
  });
336
370
  }
371
+ this.updateTriggerButtonAriaAttributes(this.getFocusableToggleButton(), (_this$props$isOpen = this.props.isOpen) !== null && _this$props$isOpen !== void 0 ? _this$props$isOpen : false);
337
372
  this.repositionOnScroll.subscribe();
338
373
  }
339
374
  }, {
@@ -345,6 +380,12 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
345
380
  this.onOpenPopover();
346
381
  }
347
382
 
383
+ // Update ARIA attributes on the toggle when open state changes
384
+ if (prevProps.isOpen !== this.props.isOpen) {
385
+ var _this$props$isOpen2;
386
+ this.updateTriggerButtonAriaAttributes(this.getFocusableToggleButton(), (_this$props$isOpen2 = this.props.isOpen) !== null && _this$props$isOpen2 !== void 0 ? _this$props$isOpen2 : false);
387
+ }
388
+
348
389
  // ensure recalculation of panel position on prop updates
349
390
  if (this.props.isOpen && (prevProps.anchorPosition !== this.props.anchorPosition || prevProps.buffer !== this.props.buffer || prevProps.offset !== this.props.offset || prevProps.panelPaddingSize !== this.props.panelPaddingSize)) {
350
391
  this.positionPopoverFluid();
@@ -464,7 +505,9 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
464
505
  initialFocus: initialFocus,
465
506
  onEscapeKey: this.onEscapeKey,
466
507
  disabled: !ownFocus || !this.state.isOpenStable || this.state.isClosing
467
- }, focusTrapProps), (0, _react2.jsx)(_popover_panel.EuiPopoverPanel, _extends({}, panelProps, {
508
+ }, focusTrapProps), (0, _react2.jsx)(_popover_panel.EuiPopoverPanel, _extends({
509
+ id: this.panelId
510
+ }, panelProps, {
468
511
  panelRef: this.panelRef,
469
512
  isOpen: this.state.isOpening,
470
513
  position: this.state.arrowPosition,
@@ -654,7 +697,7 @@ EuiPopover.propTypes = {
654
697
  * however, the popover will attempt to reposition itself along the secondary
655
698
  * cross axis if there is room there instead.
656
699
  *
657
- * If you do not not want this repositioning to occur (and it is acceptable for
700
+ * If you do not want this repositioning to occur (and it is acceptable for
658
701
  * the popover to appear offscreen), set this to false to disable this behavior.
659
702
  *
660
703
  * @default true
@@ -39,7 +39,8 @@ var BackButton = function BackButton(props) {
39
39
  return ___EmotionJSX(EuiButtonEmpty, _extends({
40
40
  size: "xs",
41
41
  color: "text",
42
- iconType: "editorUndo"
42
+ iconType: "editorUndo",
43
+ "data-test-subj": "euiFlyoutMenuBackButton"
43
44
  }, props), ___EmotionJSX(EuiI18n, {
44
45
  token: "euiFlyoutMenu.back",
45
46
  default: "Back"
@@ -58,7 +59,8 @@ var HistoryPopover = function HistoryPopover(_ref) {
58
59
  button: ___EmotionJSX(EuiButtonIcon, {
59
60
  iconType: "arrowDown",
60
61
  color: "text",
61
- "aria-label": useEuiI18n('euiFlyoutMenu.history', 'History')
62
+ "aria-label": useEuiI18n('euiFlyoutMenu.history', 'History'),
63
+ "data-test-subj": "euiFlyoutMenuHistoryButton"
62
64
  }),
63
65
  isOpen: isPopoverOpen,
64
66
  onClick: handlePopoverButtonClick,
@@ -77,7 +79,8 @@ var HistoryPopover = function HistoryPopover(_ref) {
77
79
  onClick: function onClick() {
78
80
  item.onClick();
79
81
  setIsPopoverOpen(false);
80
- }
82
+ },
83
+ "data-test-subj": "euiFlyoutMenuHistoryItem-".concat(index)
81
84
  }, item.title);
82
85
  })));
83
86
  };
@@ -96,7 +96,9 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
96
96
  _defineProperty(_this, "closingTransitionAnimationFrame", void 0);
97
97
  _defineProperty(_this, "button", null);
98
98
  _defineProperty(_this, "panel", null);
99
- _defineProperty(_this, "descriptionId", htmlIdGenerator()());
99
+ _defineProperty(_this, "idGenerator", htmlIdGenerator('euiPopover'));
100
+ _defineProperty(_this, "panelId", _this.idGenerator('panelId'));
101
+ _defineProperty(_this, "descriptionId", _this.idGenerator('descriptionId'));
100
102
  _defineProperty(_this, "closePopover", function () {
101
103
  if (_this.props.isOpen) {
102
104
  _this.props.closePopover();
@@ -110,6 +112,19 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
110
112
  _this.handleStrandedFocus();
111
113
  }
112
114
  });
115
+ _defineProperty(_this, "getFocusableToggleButton", function () {
116
+ if (_this.button) {
117
+ try {
118
+ var focusableItems = focusable(_this.button);
119
+ if (focusableItems.length) {
120
+ return focusableItems[0];
121
+ }
122
+ } catch (_unused) {
123
+ // tabbable's focusable() can throw in environments that don't
124
+ // fully support CSS selector parsing (e.g. jsdom with :has())
125
+ }
126
+ }
127
+ });
113
128
  _defineProperty(_this, "handleStrandedFocus", function () {
114
129
  _this.strandedFocusTimeout = window.setTimeout(function () {
115
130
  var _this$panel;
@@ -119,11 +134,10 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
119
134
  // it will be on the panel instead on mount when isOpen=true
120
135
  if (document.activeElement === document.body || (_this$panel = _this.panel) !== null && _this$panel !== void 0 && _this$panel.contains(document.activeElement) // if focus is on OR within this.panel
121
136
  ) {
122
- if (!_this.button) return;
123
- var focusableItems = focusable(_this.button);
124
- if (!focusableItems.length) return;
125
- var toggleButton = focusableItems[0];
126
- toggleButton.focus(returnFocusConfig);
137
+ var toggleButton = _this.getFocusableToggleButton();
138
+ if (toggleButton) {
139
+ toggleButton.focus(returnFocusConfig);
140
+ }
127
141
  }
128
142
  }, closingTransitionTime);
129
143
  });
@@ -179,6 +193,25 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
179
193
  });
180
194
  }, durationMatch + delayMatch);
181
195
  });
196
+ /**
197
+ * Updates ARIA attributes on the popover trigger button
198
+ * Only applies ARIA when the trigger is button-like (semantic <button> or role="button").
199
+ * Avoids adding incorrect ARIA on inputs or other non-button elements.
200
+ */
201
+ _defineProperty(_this, "updateTriggerButtonAriaAttributes", function (toggleButton, isOpen) {
202
+ var _toggleButton$tagName, _toggleButton$getAttr;
203
+ if (!toggleButton) return;
204
+ var tag = (_toggleButton$tagName = toggleButton.tagName) === null || _toggleButton$tagName === void 0 ? void 0 : _toggleButton$tagName.toLowerCase();
205
+ var role = (_toggleButton$getAttr = toggleButton.getAttribute('role')) === null || _toggleButton$getAttr === void 0 ? void 0 : _toggleButton$getAttr.toLowerCase();
206
+ var isButtonLike = tag === 'button' || role === 'button';
207
+ if (!isButtonLike) return;
208
+ toggleButton.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
209
+ if (isOpen) {
210
+ toggleButton.setAttribute('aria-controls', _this.panelId);
211
+ } else {
212
+ toggleButton.removeAttribute('aria-controls');
213
+ }
214
+ });
182
215
  _defineProperty(_this, "onMutation", function (records) {
183
216
  var waitDuration = getWaitDuration(records);
184
217
  _this.positionPopoverFixed();
@@ -298,7 +331,8 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
298
331
  return _createClass(EuiPopover, [{
299
332
  key: "componentDidMount",
300
333
  value: function componentDidMount() {
301
- var _this2 = this;
334
+ var _this2 = this,
335
+ _this$props$isOpen;
302
336
  if (this.state.suppressingPopover) {
303
337
  // component was created with isOpen=true; now that it's mounted
304
338
  // stop suppressing and start opening
@@ -309,6 +343,7 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
309
343
  _this2.onOpenPopover();
310
344
  });
311
345
  }
346
+ this.updateTriggerButtonAriaAttributes(this.getFocusableToggleButton(), (_this$props$isOpen = this.props.isOpen) !== null && _this$props$isOpen !== void 0 ? _this$props$isOpen : false);
312
347
  this.repositionOnScroll.subscribe();
313
348
  }
314
349
  }, {
@@ -320,6 +355,12 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
320
355
  this.onOpenPopover();
321
356
  }
322
357
 
358
+ // Update ARIA attributes on the toggle when open state changes
359
+ if (prevProps.isOpen !== this.props.isOpen) {
360
+ var _this$props$isOpen2;
361
+ this.updateTriggerButtonAriaAttributes(this.getFocusableToggleButton(), (_this$props$isOpen2 = this.props.isOpen) !== null && _this$props$isOpen2 !== void 0 ? _this$props$isOpen2 : false);
362
+ }
363
+
323
364
  // ensure recalculation of panel position on prop updates
324
365
  if (this.props.isOpen && (prevProps.anchorPosition !== this.props.anchorPosition || prevProps.buffer !== this.props.buffer || prevProps.offset !== this.props.offset || prevProps.panelPaddingSize !== this.props.panelPaddingSize)) {
325
366
  this.positionPopoverFluid();
@@ -439,7 +480,9 @@ export var EuiPopover = /*#__PURE__*/function (_Component) {
439
480
  initialFocus: initialFocus,
440
481
  onEscapeKey: this.onEscapeKey,
441
482
  disabled: !ownFocus || !this.state.isOpenStable || this.state.isClosing
442
- }, focusTrapProps), ___EmotionJSX(EuiPopoverPanel, _extends({}, panelProps, {
483
+ }, focusTrapProps), ___EmotionJSX(EuiPopoverPanel, _extends({
484
+ id: this.panelId
485
+ }, panelProps, {
443
486
  panelRef: this.panelRef,
444
487
  isOpen: this.state.isOpening,
445
488
  position: this.state.arrowPosition,
@@ -45,7 +45,8 @@ var BackButton = function BackButton(props) {
45
45
  return (0, _react2.jsx)(_button.EuiButtonEmpty, (0, _extends2.default)({
46
46
  size: "xs",
47
47
  color: "text",
48
- iconType: "editorUndo"
48
+ iconType: "editorUndo",
49
+ "data-test-subj": "euiFlyoutMenuBackButton"
49
50
  }, props), (0, _react2.jsx)(_i18n.EuiI18n, {
50
51
  token: "euiFlyoutMenu.back",
51
52
  default: "Back"
@@ -64,7 +65,8 @@ var HistoryPopover = function HistoryPopover(_ref) {
64
65
  button: (0, _react2.jsx)(_button.EuiButtonIcon, {
65
66
  iconType: "arrowDown",
66
67
  color: "text",
67
- "aria-label": (0, _i18n.useEuiI18n)('euiFlyoutMenu.history', 'History')
68
+ "aria-label": (0, _i18n.useEuiI18n)('euiFlyoutMenu.history', 'History'),
69
+ "data-test-subj": "euiFlyoutMenuHistoryButton"
68
70
  }),
69
71
  isOpen: isPopoverOpen,
70
72
  onClick: handlePopoverButtonClick,
@@ -83,7 +85,8 @@ var HistoryPopover = function HistoryPopover(_ref) {
83
85
  onClick: function onClick() {
84
86
  item.onClick();
85
87
  setIsPopoverOpen(false);
86
- }
88
+ },
89
+ "data-test-subj": "euiFlyoutMenuHistoryItem-".concat(index)
87
90
  }, item.title);
88
91
  })));
89
92
  };
@@ -106,7 +106,9 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
106
106
  (0, _defineProperty2.default)(_this, "closingTransitionAnimationFrame", void 0);
107
107
  (0, _defineProperty2.default)(_this, "button", null);
108
108
  (0, _defineProperty2.default)(_this, "panel", null);
109
- (0, _defineProperty2.default)(_this, "descriptionId", (0, _services.htmlIdGenerator)()());
109
+ (0, _defineProperty2.default)(_this, "idGenerator", (0, _services.htmlIdGenerator)('euiPopover'));
110
+ (0, _defineProperty2.default)(_this, "panelId", _this.idGenerator('panelId'));
111
+ (0, _defineProperty2.default)(_this, "descriptionId", _this.idGenerator('descriptionId'));
110
112
  (0, _defineProperty2.default)(_this, "closePopover", function () {
111
113
  if (_this.props.isOpen) {
112
114
  _this.props.closePopover();
@@ -120,6 +122,19 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
120
122
  _this.handleStrandedFocus();
121
123
  }
122
124
  });
125
+ (0, _defineProperty2.default)(_this, "getFocusableToggleButton", function () {
126
+ if (_this.button) {
127
+ try {
128
+ var focusableItems = (0, _tabbable.focusable)(_this.button);
129
+ if (focusableItems.length) {
130
+ return focusableItems[0];
131
+ }
132
+ } catch (_unused) {
133
+ // tabbable's focusable() can throw in environments that don't
134
+ // fully support CSS selector parsing (e.g. jsdom with :has())
135
+ }
136
+ }
137
+ });
123
138
  (0, _defineProperty2.default)(_this, "handleStrandedFocus", function () {
124
139
  _this.strandedFocusTimeout = window.setTimeout(function () {
125
140
  var _this$panel;
@@ -129,11 +144,10 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
129
144
  // it will be on the panel instead on mount when isOpen=true
130
145
  if (document.activeElement === document.body || (_this$panel = _this.panel) !== null && _this$panel !== void 0 && _this$panel.contains(document.activeElement) // if focus is on OR within this.panel
131
146
  ) {
132
- if (!_this.button) return;
133
- var focusableItems = (0, _tabbable.focusable)(_this.button);
134
- if (!focusableItems.length) return;
135
- var toggleButton = focusableItems[0];
136
- toggleButton.focus(returnFocusConfig);
147
+ var toggleButton = _this.getFocusableToggleButton();
148
+ if (toggleButton) {
149
+ toggleButton.focus(returnFocusConfig);
150
+ }
137
151
  }
138
152
  }, closingTransitionTime);
139
153
  });
@@ -189,6 +203,25 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
189
203
  });
190
204
  }, durationMatch + delayMatch);
191
205
  });
206
+ /**
207
+ * Updates ARIA attributes on the popover trigger button
208
+ * Only applies ARIA when the trigger is button-like (semantic <button> or role="button").
209
+ * Avoids adding incorrect ARIA on inputs or other non-button elements.
210
+ */
211
+ (0, _defineProperty2.default)(_this, "updateTriggerButtonAriaAttributes", function (toggleButton, isOpen) {
212
+ var _toggleButton$tagName, _toggleButton$getAttr;
213
+ if (!toggleButton) return;
214
+ var tag = (_toggleButton$tagName = toggleButton.tagName) === null || _toggleButton$tagName === void 0 ? void 0 : _toggleButton$tagName.toLowerCase();
215
+ var role = (_toggleButton$getAttr = toggleButton.getAttribute('role')) === null || _toggleButton$getAttr === void 0 ? void 0 : _toggleButton$getAttr.toLowerCase();
216
+ var isButtonLike = tag === 'button' || role === 'button';
217
+ if (!isButtonLike) return;
218
+ toggleButton.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
219
+ if (isOpen) {
220
+ toggleButton.setAttribute('aria-controls', _this.panelId);
221
+ } else {
222
+ toggleButton.removeAttribute('aria-controls');
223
+ }
224
+ });
192
225
  (0, _defineProperty2.default)(_this, "onMutation", function (records) {
193
226
  var waitDuration = (0, _services.getWaitDuration)(records);
194
227
  _this.positionPopoverFixed();
@@ -308,7 +341,8 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
308
341
  return (0, _createClass2.default)(EuiPopover, [{
309
342
  key: "componentDidMount",
310
343
  value: function componentDidMount() {
311
- var _this2 = this;
344
+ var _this2 = this,
345
+ _this$props$isOpen;
312
346
  if (this.state.suppressingPopover) {
313
347
  // component was created with isOpen=true; now that it's mounted
314
348
  // stop suppressing and start opening
@@ -319,6 +353,7 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
319
353
  _this2.onOpenPopover();
320
354
  });
321
355
  }
356
+ this.updateTriggerButtonAriaAttributes(this.getFocusableToggleButton(), (_this$props$isOpen = this.props.isOpen) !== null && _this$props$isOpen !== void 0 ? _this$props$isOpen : false);
322
357
  this.repositionOnScroll.subscribe();
323
358
  }
324
359
  }, {
@@ -330,6 +365,12 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
330
365
  this.onOpenPopover();
331
366
  }
332
367
 
368
+ // Update ARIA attributes on the toggle when open state changes
369
+ if (prevProps.isOpen !== this.props.isOpen) {
370
+ var _this$props$isOpen2;
371
+ this.updateTriggerButtonAriaAttributes(this.getFocusableToggleButton(), (_this$props$isOpen2 = this.props.isOpen) !== null && _this$props$isOpen2 !== void 0 ? _this$props$isOpen2 : false);
372
+ }
373
+
333
374
  // ensure recalculation of panel position on prop updates
334
375
  if (this.props.isOpen && (prevProps.anchorPosition !== this.props.anchorPosition || prevProps.buffer !== this.props.buffer || prevProps.offset !== this.props.offset || prevProps.panelPaddingSize !== this.props.panelPaddingSize)) {
335
376
  this.positionPopoverFluid();
@@ -449,7 +490,9 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
449
490
  initialFocus: initialFocus,
450
491
  onEscapeKey: this.onEscapeKey,
451
492
  disabled: !ownFocus || !this.state.isOpenStable || this.state.isClosing
452
- }, focusTrapProps), (0, _react2.jsx)(_popover_panel.EuiPopoverPanel, (0, _extends2.default)({}, panelProps, {
493
+ }, focusTrapProps), (0, _react2.jsx)(_popover_panel.EuiPopoverPanel, (0, _extends2.default)({
494
+ id: this.panelId
495
+ }, panelProps, {
453
496
  panelRef: this.panelRef,
454
497
  isOpen: this.state.isOpening,
455
498
  position: this.state.arrowPosition,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elastic/eui",
3
3
  "description": "Elastic UI Component Library",
4
- "version": "113.0.0",
4
+ "version": "113.1.0",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "lib",
7
7
  "module": "es",
@@ -21,6 +21,7 @@
21
21
  "build:i18ntokens": "node ./scripts/build_i18ntokens.mjs",
22
22
  "build": "yarn build:clean && yarn build:i18ntokens && node ./scripts/compile-eui.js",
23
23
  "build-pack": "yarn build && yarn pack",
24
+ "watch": "node ../../scripts/watch-eui.js --package @elastic/eui",
24
25
  "compile-icons": "node ./scripts/compile-icons.js && prettier --write --loglevel=warn \"./src/components/icon/assets/**/*.tsx\"",
25
26
  "lint": "yarn tsc --noEmit && yarn lint-es && yarn lint-css-in-js && yarn lint-sass",
26
27
  "lint-fix": "yarn lint-es --fix && yarn lint-css-in-js --fix",
@@ -52,7 +53,7 @@
52
53
  "directory": "packages/eui"
53
54
  },
54
55
  "dependencies": {
55
- "@elastic/eui-theme-common": "8.0.0",
56
+ "@elastic/eui-theme-common": "8.1.0",
56
57
  "@elastic/prismjs-esql": "^1.1.2",
57
58
  "@hello-pangea/dnd": "^16.6.0",
58
59
  "@types/lodash": "^4.14.202",
@@ -107,7 +108,7 @@
107
108
  "@cypress/webpack-dev-server": "^1.7.0",
108
109
  "@elastic/charts": "^64.1.0",
109
110
  "@elastic/datemath": "^5.0.3",
110
- "@elastic/eui-theme-borealis": "6.0.0",
111
+ "@elastic/eui-theme-borealis": "6.1.0",
111
112
  "@emotion/babel-preset-css-prop": "^11.11.0",
112
113
  "@emotion/cache": "^11.11.0",
113
114
  "@emotion/css": "^11.11.0",
@@ -167,8 +168,6 @@
167
168
  "buffer": "^6.0.3",
168
169
  "buildkite-test-collector": "^1.7.2",
169
170
  "cache-loader": "^4.1.0",
170
- "chalk": "^4.1.0",
171
- "chokidar": "^3.4.2",
172
171
  "circular-dependency-plugin": "^5.2.2",
173
172
  "codesandbox": "^2.1.16",
174
173
  "core-js": "^3.6.5",
@@ -257,7 +256,7 @@
257
256
  },
258
257
  "peerDependencies": {
259
258
  "@elastic/datemath": "^5.0.2",
260
- "@elastic/eui-theme-borealis": "6.0.0",
259
+ "@elastic/eui-theme-borealis": "6.1.0",
261
260
  "@emotion/css": "11.x",
262
261
  "@emotion/react": "11.x",
263
262
  "@types/react": "^17.0 || ^18.0",
@@ -246,7 +246,7 @@ EuiBreadcrumbContent.propTypes = {
246
246
  * however, the popover will attempt to reposition itself along the secondary
247
247
  * cross axis if there is room there instead.
248
248
  *
249
- * If you do not not want this repositioning to occur (and it is acceptable for
249
+ * If you do not want this repositioning to occur (and it is acceptable for
250
250
  * the popover to appear offscreen), set this to false to disable this behavior.
251
251
  *
252
252
  * @default true
@@ -46,7 +46,8 @@ var BackButton = function BackButton(props) {
46
46
  return (0, _react2.jsx)(_button.EuiButtonEmpty, (0, _extends2.default)({
47
47
  size: "xs",
48
48
  color: "text",
49
- iconType: "editorUndo"
49
+ iconType: "editorUndo",
50
+ "data-test-subj": "euiFlyoutMenuBackButton"
50
51
  }, props), (0, _react2.jsx)(_i18n.EuiI18n, {
51
52
  token: "euiFlyoutMenu.back",
52
53
  default: "Back"
@@ -65,7 +66,8 @@ var HistoryPopover = function HistoryPopover(_ref) {
65
66
  button: (0, _react2.jsx)(_button.EuiButtonIcon, {
66
67
  iconType: "arrowDown",
67
68
  color: "text",
68
- "aria-label": (0, _i18n.useEuiI18n)('euiFlyoutMenu.history', 'History')
69
+ "aria-label": (0, _i18n.useEuiI18n)('euiFlyoutMenu.history', 'History'),
70
+ "data-test-subj": "euiFlyoutMenuHistoryButton"
69
71
  }),
70
72
  isOpen: isPopoverOpen,
71
73
  onClick: handlePopoverButtonClick,
@@ -84,7 +86,8 @@ var HistoryPopover = function HistoryPopover(_ref) {
84
86
  onClick: function onClick() {
85
87
  item.onClick();
86
88
  setIsPopoverOpen(false);
87
- }
89
+ },
90
+ "data-test-subj": "euiFlyoutMenuHistoryItem-".concat(index)
88
91
  }, item.title);
89
92
  })));
90
93
  };
@@ -107,7 +107,9 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
107
107
  (0, _defineProperty2.default)(_this, "closingTransitionAnimationFrame", void 0);
108
108
  (0, _defineProperty2.default)(_this, "button", null);
109
109
  (0, _defineProperty2.default)(_this, "panel", null);
110
- (0, _defineProperty2.default)(_this, "descriptionId", (0, _services.htmlIdGenerator)()());
110
+ (0, _defineProperty2.default)(_this, "idGenerator", (0, _services.htmlIdGenerator)('euiPopover'));
111
+ (0, _defineProperty2.default)(_this, "panelId", _this.idGenerator('panelId'));
112
+ (0, _defineProperty2.default)(_this, "descriptionId", _this.idGenerator('descriptionId'));
111
113
  (0, _defineProperty2.default)(_this, "closePopover", function () {
112
114
  if (_this.props.isOpen) {
113
115
  _this.props.closePopover();
@@ -121,6 +123,19 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
121
123
  _this.handleStrandedFocus();
122
124
  }
123
125
  });
126
+ (0, _defineProperty2.default)(_this, "getFocusableToggleButton", function () {
127
+ if (_this.button) {
128
+ try {
129
+ var focusableItems = (0, _tabbable.focusable)(_this.button);
130
+ if (focusableItems.length) {
131
+ return focusableItems[0];
132
+ }
133
+ } catch (_unused) {
134
+ // tabbable's focusable() can throw in environments that don't
135
+ // fully support CSS selector parsing (e.g. jsdom with :has())
136
+ }
137
+ }
138
+ });
124
139
  (0, _defineProperty2.default)(_this, "handleStrandedFocus", function () {
125
140
  _this.strandedFocusTimeout = window.setTimeout(function () {
126
141
  var _this$panel;
@@ -130,11 +145,10 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
130
145
  // it will be on the panel instead on mount when isOpen=true
131
146
  if (document.activeElement === document.body || (_this$panel = _this.panel) !== null && _this$panel !== void 0 && _this$panel.contains(document.activeElement) // if focus is on OR within this.panel
132
147
  ) {
133
- if (!_this.button) return;
134
- var focusableItems = (0, _tabbable.focusable)(_this.button);
135
- if (!focusableItems.length) return;
136
- var toggleButton = focusableItems[0];
137
- toggleButton.focus(returnFocusConfig);
148
+ var toggleButton = _this.getFocusableToggleButton();
149
+ if (toggleButton) {
150
+ toggleButton.focus(returnFocusConfig);
151
+ }
138
152
  }
139
153
  }, closingTransitionTime);
140
154
  });
@@ -190,6 +204,25 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
190
204
  });
191
205
  }, durationMatch + delayMatch);
192
206
  });
207
+ /**
208
+ * Updates ARIA attributes on the popover trigger button
209
+ * Only applies ARIA when the trigger is button-like (semantic <button> or role="button").
210
+ * Avoids adding incorrect ARIA on inputs or other non-button elements.
211
+ */
212
+ (0, _defineProperty2.default)(_this, "updateTriggerButtonAriaAttributes", function (toggleButton, isOpen) {
213
+ var _toggleButton$tagName, _toggleButton$getAttr;
214
+ if (!toggleButton) return;
215
+ var tag = (_toggleButton$tagName = toggleButton.tagName) === null || _toggleButton$tagName === void 0 ? void 0 : _toggleButton$tagName.toLowerCase();
216
+ var role = (_toggleButton$getAttr = toggleButton.getAttribute('role')) === null || _toggleButton$getAttr === void 0 ? void 0 : _toggleButton$getAttr.toLowerCase();
217
+ var isButtonLike = tag === 'button' || role === 'button';
218
+ if (!isButtonLike) return;
219
+ toggleButton.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
220
+ if (isOpen) {
221
+ toggleButton.setAttribute('aria-controls', _this.panelId);
222
+ } else {
223
+ toggleButton.removeAttribute('aria-controls');
224
+ }
225
+ });
193
226
  (0, _defineProperty2.default)(_this, "onMutation", function (records) {
194
227
  var waitDuration = (0, _services.getWaitDuration)(records);
195
228
  _this.positionPopoverFixed();
@@ -309,7 +342,8 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
309
342
  return (0, _createClass2.default)(EuiPopover, [{
310
343
  key: "componentDidMount",
311
344
  value: function componentDidMount() {
312
- var _this2 = this;
345
+ var _this2 = this,
346
+ _this$props$isOpen;
313
347
  if (this.state.suppressingPopover) {
314
348
  // component was created with isOpen=true; now that it's mounted
315
349
  // stop suppressing and start opening
@@ -320,6 +354,7 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
320
354
  _this2.onOpenPopover();
321
355
  });
322
356
  }
357
+ this.updateTriggerButtonAriaAttributes(this.getFocusableToggleButton(), (_this$props$isOpen = this.props.isOpen) !== null && _this$props$isOpen !== void 0 ? _this$props$isOpen : false);
323
358
  this.repositionOnScroll.subscribe();
324
359
  }
325
360
  }, {
@@ -331,6 +366,12 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
331
366
  this.onOpenPopover();
332
367
  }
333
368
 
369
+ // Update ARIA attributes on the toggle when open state changes
370
+ if (prevProps.isOpen !== this.props.isOpen) {
371
+ var _this$props$isOpen2;
372
+ this.updateTriggerButtonAriaAttributes(this.getFocusableToggleButton(), (_this$props$isOpen2 = this.props.isOpen) !== null && _this$props$isOpen2 !== void 0 ? _this$props$isOpen2 : false);
373
+ }
374
+
334
375
  // ensure recalculation of panel position on prop updates
335
376
  if (this.props.isOpen && (prevProps.anchorPosition !== this.props.anchorPosition || prevProps.buffer !== this.props.buffer || prevProps.offset !== this.props.offset || prevProps.panelPaddingSize !== this.props.panelPaddingSize)) {
336
377
  this.positionPopoverFluid();
@@ -450,7 +491,9 @@ var EuiPopover = exports.EuiPopover = /*#__PURE__*/function (_Component) {
450
491
  initialFocus: initialFocus,
451
492
  onEscapeKey: this.onEscapeKey,
452
493
  disabled: !ownFocus || !this.state.isOpenStable || this.state.isClosing
453
- }, focusTrapProps), (0, _react2.jsx)(_popover_panel.EuiPopoverPanel, (0, _extends2.default)({}, panelProps, {
494
+ }, focusTrapProps), (0, _react2.jsx)(_popover_panel.EuiPopoverPanel, (0, _extends2.default)({
495
+ id: this.panelId
496
+ }, panelProps, {
454
497
  panelRef: this.panelRef,
455
498
  isOpen: this.state.isOpening,
456
499
  position: this.state.arrowPosition,
@@ -640,7 +683,7 @@ EuiPopover.propTypes = {
640
683
  * however, the popover will attempt to reposition itself along the secondary
641
684
  * cross axis if there is room there instead.
642
685
  *
643
- * If you do not not want this repositioning to occur (and it is acceptable for
686
+ * If you do not want this repositioning to occur (and it is acceptable for
644
687
  * the popover to appear offscreen), set this to false to disable this behavior.
645
688
  *
646
689
  * @default true