@ionic/core 8.0.0-dev.11712072527.1dd97c66 → 8.0.0-dev.11712850753.10c4a960

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.
Files changed (161) hide show
  1. package/components/button.js +2 -2
  2. package/components/ion-datetime.js +8 -6
  3. package/components/ion-modal.js +9 -7
  4. package/components/overlays.js +3 -2
  5. package/components/popover.js +8 -6
  6. package/css/core.css +1 -624
  7. package/css/core.css.map +1 -1
  8. package/css/display.css +1 -131
  9. package/css/display.css.map +1 -1
  10. package/css/flex-utils.css +1 -81
  11. package/css/flex-utils.css.map +1 -1
  12. package/css/float-elements.css +1 -293
  13. package/css/float-elements.css.map +1 -1
  14. package/css/global.bundle.css +1 -457
  15. package/css/global.bundle.css.map +1 -1
  16. package/css/ionic-swiper.css +1 -127
  17. package/css/ionic-swiper.css.map +1 -1
  18. package/css/ionic.bundle.css +1 -1
  19. package/css/ionic.bundle.css.map +1 -1
  20. package/css/normalize.css +1 -150
  21. package/css/normalize.css.map +1 -1
  22. package/css/padding.css +1 -202
  23. package/css/padding.css.map +1 -1
  24. package/css/palettes/dark.always.css +1 -160
  25. package/css/palettes/dark.always.css.map +1 -1
  26. package/css/palettes/dark.class.css +1 -160
  27. package/css/palettes/dark.class.css.map +1 -1
  28. package/css/palettes/dark.css +0 -2
  29. package/css/palettes/dark.system.css +1 -162
  30. package/css/palettes/dark.system.css.map +1 -1
  31. package/css/palettes/high-contrast-dark.always.css +1 -180
  32. package/css/palettes/high-contrast-dark.always.css.map +1 -1
  33. package/css/palettes/high-contrast-dark.class.css +1 -180
  34. package/css/palettes/high-contrast-dark.class.css.map +1 -1
  35. package/css/palettes/high-contrast-dark.css +0 -2
  36. package/css/palettes/high-contrast-dark.system.css +1 -182
  37. package/css/palettes/high-contrast-dark.system.css.map +1 -1
  38. package/css/palettes/high-contrast.always.css +1 -101
  39. package/css/palettes/high-contrast.always.css.map +1 -1
  40. package/css/palettes/high-contrast.class.css +1 -101
  41. package/css/palettes/high-contrast.class.css.map +1 -1
  42. package/css/palettes/high-contrast.css +0 -2
  43. package/css/palettes/high-contrast.system.css +1 -103
  44. package/css/palettes/high-contrast.system.css.map +1 -1
  45. package/css/structure.css +1 -152
  46. package/css/structure.css.map +1 -1
  47. package/css/text-alignment.css +1 -243
  48. package/css/text-alignment.css.map +1 -1
  49. package/css/text-transformation.css +1 -158
  50. package/css/text-transformation.css.map +1 -1
  51. package/css/typography.css +1 -157
  52. package/css/typography.css.map +1 -1
  53. package/css/utils.bundle.css +1 -1100
  54. package/css/utils.bundle.css.map +1 -1
  55. package/dist/cjs/index.cjs.js +1 -1
  56. package/dist/cjs/ion-action-sheet.cjs.entry.js +1 -1
  57. package/dist/cjs/ion-alert.cjs.entry.js +1 -1
  58. package/dist/cjs/ion-button_2.cjs.entry.js +2 -2
  59. package/dist/cjs/ion-datetime_3.cjs.entry.js +9 -7
  60. package/dist/cjs/ion-loading.cjs.entry.js +1 -1
  61. package/dist/cjs/ion-menu_3.cjs.entry.js +1 -1
  62. package/dist/cjs/ion-modal.cjs.entry.js +8 -7
  63. package/dist/cjs/ion-popover.cjs.entry.js +7 -6
  64. package/dist/cjs/ion-select_3.cjs.entry.js +1 -1
  65. package/dist/cjs/ion-toast.cjs.entry.js +1 -1
  66. package/dist/cjs/ionic.cjs.js +2 -2
  67. package/dist/cjs/loader.cjs.js +1 -1
  68. package/dist/cjs/{overlays-6487955a.js → overlays-66fcac49.js} +3 -1
  69. package/dist/collection/collection-manifest.json +2 -2
  70. package/dist/collection/components/button/button.ios.css +47 -8
  71. package/dist/collection/components/button/button.md.css +49 -8
  72. package/dist/collection/components/datetime/datetime.js +8 -6
  73. package/dist/collection/components/datetime/test/overlay-roles/datetime.e2e.js +34 -0
  74. package/dist/collection/components/input/input.js +1 -1
  75. package/dist/collection/components/modal/gestures/sheet.js +3 -2
  76. package/dist/collection/components/modal/modal.js +24 -5
  77. package/dist/collection/components/modal/test/basic/modal.spec.js +19 -0
  78. package/dist/collection/components/popover/popover.ios.css +0 -1
  79. package/dist/collection/components/popover/popover.js +23 -4
  80. package/dist/collection/components/popover/popover.md.css +0 -1
  81. package/dist/collection/components/popover/test/basic/popover.e2e.js +76 -0
  82. package/dist/collection/components/popover/test/basic/popover.spec.js +19 -0
  83. package/dist/collection/components/searchbar/searchbar.js +1 -1
  84. package/dist/collection/components/toolbar/test/basic/toolbar.e2e.js +133 -5
  85. package/dist/collection/utils/overlays.js +2 -1
  86. package/dist/docs.json +75 -31
  87. package/dist/esm/index.js +1 -1
  88. package/dist/esm/ion-action-sheet.entry.js +1 -1
  89. package/dist/esm/ion-alert.entry.js +1 -1
  90. package/dist/esm/ion-button_2.entry.js +2 -2
  91. package/dist/esm/ion-datetime_3.entry.js +9 -7
  92. package/dist/esm/ion-loading.entry.js +1 -1
  93. package/dist/esm/ion-menu_3.entry.js +1 -1
  94. package/dist/esm/ion-modal.entry.js +8 -7
  95. package/dist/esm/ion-popover.entry.js +7 -6
  96. package/dist/esm/ion-select_3.entry.js +1 -1
  97. package/dist/esm/ion-toast.entry.js +1 -1
  98. package/dist/esm/ionic.js +2 -2
  99. package/dist/esm/loader.js +1 -1
  100. package/dist/esm/{overlays-9472c98b.js → overlays-634df4be.js} +3 -2
  101. package/dist/esm-es5/index.js +1 -1
  102. package/dist/esm-es5/ion-action-sheet.entry.js +1 -1
  103. package/dist/esm-es5/ion-alert.entry.js +1 -1
  104. package/dist/esm-es5/ion-button_2.entry.js +1 -1
  105. package/dist/esm-es5/ion-datetime_3.entry.js +1 -1
  106. package/dist/esm-es5/ion-loading.entry.js +1 -1
  107. package/dist/esm-es5/ion-menu_3.entry.js +1 -1
  108. package/dist/esm-es5/ion-modal.entry.js +1 -1
  109. package/dist/esm-es5/ion-popover.entry.js +1 -1
  110. package/dist/esm-es5/ion-select_3.entry.js +1 -1
  111. package/dist/esm-es5/ion-toast.entry.js +1 -1
  112. package/dist/esm-es5/ionic.js +1 -1
  113. package/dist/esm-es5/loader.js +1 -1
  114. package/dist/esm-es5/{overlays-9472c98b.js → overlays-634df4be.js} +1 -1
  115. package/dist/html.html-data.json +26 -18
  116. package/dist/ionic/index.esm.js +1 -1
  117. package/dist/ionic/ionic.esm.js +1 -1
  118. package/dist/ionic/ionic.js +1 -1
  119. package/dist/ionic/p-012cc611.system.entry.js +4 -0
  120. package/dist/ionic/p-18057853.entry.js +4 -0
  121. package/dist/ionic/p-2b106d43.system.entry.js +4 -0
  122. package/dist/ionic/{p-ea6f36fb.system.entry.js → p-32950317.system.entry.js} +1 -1
  123. package/dist/ionic/{p-4665ab20.entry.js → p-33444157.entry.js} +1 -1
  124. package/dist/ionic/{p-10ad2148.system.entry.js → p-33723893.system.entry.js} +1 -1
  125. package/dist/ionic/{p-d68569fe.system.entry.js → p-414d73bc.system.entry.js} +1 -1
  126. package/dist/ionic/{p-83b6da7c.system.entry.js → p-5cf61334.system.entry.js} +1 -1
  127. package/dist/ionic/p-73281e75.system.entry.js +4 -0
  128. package/dist/ionic/{p-fab4ecad.system.entry.js → p-745eb00b.system.entry.js} +1 -1
  129. package/dist/ionic/p-88250ff0.entry.js +4 -0
  130. package/dist/ionic/p-9399625f.entry.js +4 -0
  131. package/dist/ionic/p-ab5db814.js +4 -0
  132. package/dist/ionic/{p-51ff648c.entry.js → p-ae21e7ab.entry.js} +1 -1
  133. package/dist/ionic/{p-81c91374.entry.js → p-bcbce3d9.entry.js} +1 -1
  134. package/dist/ionic/{p-16dc1af8.entry.js → p-bd516c16.entry.js} +1 -1
  135. package/dist/ionic/p-c478747f.system.js +4 -0
  136. package/dist/ionic/p-cfdb1223.entry.js +4 -0
  137. package/dist/ionic/p-d335115d.system.js +4 -0
  138. package/dist/ionic/{p-4e802677.entry.js → p-db1d7caa.entry.js} +1 -1
  139. package/dist/ionic/{p-a8f02173.system.js → p-f24e9676.system.js} +1 -1
  140. package/dist/ionic/p-f31ef319.system.entry.js +4 -0
  141. package/dist/ionic/{p-c99ccdc9.entry.js → p-f4f3b780.entry.js} +1 -1
  142. package/dist/ionic/{p-510578f3.system.entry.js → p-fe246e19.system.entry.js} +1 -1
  143. package/dist/types/components/modal/modal-interface.d.ts +1 -0
  144. package/dist/types/components/modal/modal.d.ts +18 -0
  145. package/dist/types/components/popover/popover-interface.d.ts +1 -0
  146. package/dist/types/components/popover/popover.d.ts +18 -0
  147. package/dist/types/components.d.ts +16 -0
  148. package/dist/types/utils/overlays.d.ts +1 -0
  149. package/hydrate/index.js +43 -21
  150. package/package.json +2 -2
  151. package/dist/ionic/p-23b89985.entry.js +0 -4
  152. package/dist/ionic/p-25575222.system.js +0 -4
  153. package/dist/ionic/p-55d7edd7.entry.js +0 -4
  154. package/dist/ionic/p-8e2368ae.system.entry.js +0 -4
  155. package/dist/ionic/p-aeb5a22b.system.entry.js +0 -4
  156. package/dist/ionic/p-b75155ca.entry.js +0 -4
  157. package/dist/ionic/p-bb835b4d.system.entry.js +0 -4
  158. package/dist/ionic/p-c06e1332.system.entry.js +0 -4
  159. package/dist/ionic/p-c389d18c.entry.js +0 -4
  160. package/dist/ionic/p-ea4be6ac.system.js +0 -4
  161. package/dist/ionic/p-f4cb521c.js +0 -4
@@ -85,10 +85,10 @@ export class Datetime {
85
85
  const { activeParts } = this;
86
86
  return Array.isArray(activeParts) ? activeParts[0] : activeParts;
87
87
  };
88
- this.closeParentOverlay = () => {
88
+ this.closeParentOverlay = (role) => {
89
89
  const popoverOrModal = this.el.closest('ion-modal, ion-popover');
90
90
  if (popoverOrModal) {
91
- popoverOrModal.dismiss();
91
+ popoverOrModal.dismiss(undefined, role);
92
92
  }
93
93
  };
94
94
  this.setWorkingParts = (parts) => {
@@ -758,7 +758,7 @@ export class Datetime {
758
758
  }
759
759
  }
760
760
  if (closeOverlay) {
761
- this.closeParentOverlay();
761
+ this.closeParentOverlay(CONFIRM_ROLE);
762
762
  }
763
763
  }
764
764
  /**
@@ -778,7 +778,7 @@ export class Datetime {
778
778
  async cancel(closeOverlay = false) {
779
779
  this.ionCancel.emit();
780
780
  if (closeOverlay) {
781
- this.closeParentOverlay();
781
+ this.closeParentOverlay(CANCEL_ROLE);
782
782
  }
783
783
  }
784
784
  get isCalendarPicker() {
@@ -1556,7 +1556,7 @@ export class Datetime {
1556
1556
  const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
1557
1557
  const hasWheelVariant = hasDatePresentation && preferWheel;
1558
1558
  renderHiddenInput(true, el, name, formatValue(value), disabled);
1559
- return (h(Host, { key: '89de4c9f54e7c11038c62ecaa2e90aea47948393', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
1559
+ return (h(Host, { key: '952afba4aff8f172dcdc7986afb56271f0e239aa', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
1560
1560
  [mode]: true,
1561
1561
  ['datetime-readonly']: readonly,
1562
1562
  ['datetime-disabled']: disabled,
@@ -1566,7 +1566,7 @@ export class Datetime {
1566
1566
  [`datetime-size-${size}`]: true,
1567
1567
  [`datetime-prefer-wheel`]: hasWheelVariant,
1568
1568
  [`datetime-grid`]: isGridStyle,
1569
- })) }, h("div", { key: 'b9de6cc68dc7b7773bb408fd55a7d1872460a5f9', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
1569
+ })) }, h("div", { key: '2de62751e7498f09cef364a401e65a098be4705a', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
1570
1570
  }
1571
1571
  static get is() { return "ion-datetime"; }
1572
1572
  static get encapsulation() { return "shadow"; }
@@ -2396,5 +2396,7 @@ export class Datetime {
2396
2396
  }
2397
2397
  }
2398
2398
  let datetimeIds = 0;
2399
+ const CANCEL_ROLE = 'datetime-cancel';
2400
+ const CONFIRM_ROLE = 'datetime-confirm';
2399
2401
  const WHEEL_ITEM_PART = 'wheel-item';
2400
2402
  const WHEEL_ITEM_ACTIVE_PART = `active`;
@@ -0,0 +1,34 @@
1
+ /*!
2
+ * (C) Ionic http://ionicframework.com - MIT License
3
+ */
4
+ import { expect } from "@playwright/test";
5
+ import { configs, test } from "../../../../utils/test/playwright/index";
6
+ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ config, title }) => {
7
+ test.describe(title('datetime: overlay roles'), () => {
8
+ test.beforeEach(async ({ page }) => {
9
+ await page.setContent(`
10
+ <ion-modal>
11
+ <ion-datetime></ion-datetime>
12
+ </ion-modal>
13
+ `, config);
14
+ });
15
+ test('should pass role to overlay when calling confirm method', async ({ page }) => {
16
+ const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss');
17
+ const modal = page.locator('ion-modal');
18
+ const datetime = page.locator('ion-datetime');
19
+ await modal.evaluate((el) => el.present());
20
+ await datetime.evaluate((el) => el.confirm(true));
21
+ await ionModalDidDismiss.next();
22
+ expect(ionModalDidDismiss).toHaveReceivedEventDetail({ data: undefined, role: 'datetime-confirm' });
23
+ });
24
+ test('should pass role to overlay when calling cancel method', async ({ page }) => {
25
+ const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss');
26
+ const modal = page.locator('ion-modal');
27
+ const datetime = page.locator('ion-datetime');
28
+ await modal.evaluate((el) => el.present());
29
+ await datetime.evaluate((el) => el.cancel(true));
30
+ await ionModalDidDismiss.next();
31
+ expect(ionModalDidDismiss).toHaveReceivedEventDetail({ data: undefined, role: 'datetime-cancel' });
32
+ });
33
+ });
34
+ });
@@ -480,7 +480,7 @@ export class Input {
480
480
  "mutable": false,
481
481
  "complexType": {
482
482
  "original": "AutocompleteTypes",
483
- "resolved": "\"name\" | \"on\" | \"off\" | \"honorific-prefix\" | \"given-name\" | \"additional-name\" | \"family-name\" | \"honorific-suffix\" | \"nickname\" | \"email\" | \"username\" | \"new-password\" | \"current-password\" | \"one-time-code\" | \"organization-title\" | \"organization\" | \"street-address\" | \"address-line1\" | \"address-line2\" | \"address-line3\" | \"address-level4\" | \"address-level3\" | \"address-level2\" | \"address-level1\" | \"country\" | \"country-name\" | \"postal-code\" | \"cc-name\" | \"cc-given-name\" | \"cc-additional-name\" | \"cc-family-name\" | \"cc-number\" | \"cc-exp\" | \"cc-exp-month\" | \"cc-exp-year\" | \"cc-csc\" | \"cc-type\" | \"transaction-currency\" | \"transaction-amount\" | \"language\" | \"bday\" | \"bday-day\" | \"bday-month\" | \"bday-year\" | \"sex\" | \"tel\" | \"tel-country-code\" | \"tel-national\" | \"tel-area-code\" | \"tel-local\" | \"tel-extension\" | \"impp\" | \"url\" | \"photo\"",
483
+ "resolved": "\"name\" | \"email\" | \"tel\" | \"url\" | \"on\" | \"off\" | \"honorific-prefix\" | \"given-name\" | \"additional-name\" | \"family-name\" | \"honorific-suffix\" | \"nickname\" | \"username\" | \"new-password\" | \"current-password\" | \"one-time-code\" | \"organization-title\" | \"organization\" | \"street-address\" | \"address-line1\" | \"address-line2\" | \"address-line3\" | \"address-level4\" | \"address-level3\" | \"address-level2\" | \"address-level1\" | \"country\" | \"country-name\" | \"postal-code\" | \"cc-name\" | \"cc-given-name\" | \"cc-additional-name\" | \"cc-family-name\" | \"cc-number\" | \"cc-exp\" | \"cc-exp-month\" | \"cc-exp-year\" | \"cc-csc\" | \"cc-type\" | \"transaction-currency\" | \"transaction-amount\" | \"language\" | \"bday\" | \"bday-day\" | \"bday-month\" | \"bday-year\" | \"sex\" | \"tel-country-code\" | \"tel-national\" | \"tel-area-code\" | \"tel-local\" | \"tel-extension\" | \"impp\" | \"photo\"",
484
484
  "references": {
485
485
  "AutocompleteTypes": {
486
486
  "location": "import",
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { createGesture } from "../../../utils/gesture/index";
5
5
  import { clamp, raf } from "../../../utils/helpers";
6
+ import { FOCUS_TRAP_DISABLE_CLASS } from "../../../utils/overlays";
6
7
  import { getBackdropValueForSheet } from "../utils";
7
8
  import { calculateSpringStep, handleCanDismiss } from "./utils";
8
9
  export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpoint, backdropBreakpoint, animation, breakpoints = [], getCurrentBreakpoint, onDismiss, onBreakpointChange) => {
@@ -41,7 +42,7 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
41
42
  * as inputs should not be focusable outside
42
43
  * the sheet.
43
44
  */
44
- baseEl.classList.remove('ion-disable-focus-trap');
45
+ baseEl.classList.remove(FOCUS_TRAP_DISABLE_CLASS);
45
46
  };
46
47
  const disableBackdrop = () => {
47
48
  baseEl.style.setProperty('pointer-events', 'none');
@@ -53,7 +54,7 @@ export const createSheetGesture = (baseEl, backdropEl, wrapperEl, initialBreakpo
53
54
  * Adding this class disables focus trapping
54
55
  * for the sheet temporarily.
55
56
  */
56
- baseEl.classList.add('ion-disable-focus-trap');
57
+ baseEl.classList.add(FOCUS_TRAP_DISABLE_CLASS);
57
58
  };
58
59
  /**
59
60
  * After the entering animation completes,
@@ -8,7 +8,7 @@ import { raf, inheritAttributes, hasLazyBuild } from "../../utils/helpers";
8
8
  import { createLockController } from "../../utils/lock-controller";
9
9
  import { printIonWarning } from "../../utils/logging/index";
10
10
  import { Style as StatusBarStyle, StatusBar } from "../../utils/native/status-bar";
11
- import { GESTURE, BACKDROP, dismiss, eventMethod, prepareOverlay, present, createTriggerController, setOverlayId, } from "../../utils/overlays";
11
+ import { GESTURE, BACKDROP, dismiss, eventMethod, prepareOverlay, present, createTriggerController, setOverlayId, FOCUS_TRAP_DISABLE_CLASS, } from "../../utils/overlays";
12
12
  import { getClassMap } from "../../utils/theme";
13
13
  import { deepReady, waitForMount } from "../../utils/transition/index";
14
14
  import { config } from "../../global/config";
@@ -101,6 +101,7 @@ export class Modal {
101
101
  this.isOpen = false;
102
102
  this.trigger = undefined;
103
103
  this.keepContentsMounted = false;
104
+ this.focusTrap = true;
104
105
  this.canDismiss = true;
105
106
  }
106
107
  onIsOpenChange(newValue, oldValue) {
@@ -557,14 +558,14 @@ export class Modal {
557
558
  return true;
558
559
  }
559
560
  render() {
560
- const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes } = this;
561
+ const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes, focusTrap } = this;
561
562
  const showHandle = handle !== false && isSheetModal;
562
563
  const mode = getIonMode(this);
563
564
  const isCardModal = presentingElement !== undefined && mode === 'ios';
564
565
  const isHandleCycle = handleBehavior === 'cycle';
565
- return (h(Host, Object.assign({ key: 'dbd61751e4964ad81fc1dee19468b716d4f23c8a', "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
566
+ return (h(Host, Object.assign({ key: '1fbeb502325f00153e335c235a038507e35a210e', "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
566
567
  zIndex: `${20000 + this.overlayIndex}`,
567
- }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, 'overlay-hidden': true }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle }), h("ion-backdrop", { key: 'a7646a7a7aeef7eef1bb647373f509d4a26036ad', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { class: "modal-shadow" }), h("div", Object.assign({ key: 'bc6bc6ff7d2357206265240eaa76d730a0ecfd2c',
568
+ }, class: Object.assign({ [mode]: true, ['modal-default']: !isCardModal && !isSheetModal, [`modal-card`]: isCardModal, [`modal-sheet`]: isSheetModal, 'overlay-hidden': true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false }, getClassMap(this.cssClass)), onIonBackdropTap: this.onBackdropTap, onIonModalDidPresent: this.onLifecycle, onIonModalWillPresent: this.onLifecycle, onIonModalWillDismiss: this.onLifecycle, onIonModalDidDismiss: this.onLifecycle }), h("ion-backdrop", { key: '388aa2b92fa5795d1ef9021c4df9817ac426bcea', ref: (el) => (this.backdropEl = el), visible: this.showBackdrop, tappable: this.backdropDismiss, part: "backdrop" }), mode === 'ios' && h("div", { class: "modal-shadow" }), h("div", Object.assign({ key: '752f4e329a330cc0802476404ef292f73fac257f',
568
569
  /*
569
570
  role and aria-modal must be used on the
570
571
  same element. They must also be set inside the
@@ -573,7 +574,7 @@ export class Modal {
573
574
  */
574
575
  role: "dialog" }, inheritedAttributes, { "aria-modal": "true", class: "modal-wrapper ion-overlay-wrapper", part: "content", ref: (el) => (this.wrapperEl = el) }), showHandle && (h("button", { class: "modal-handle",
575
576
  // Prevents the handle from receiving keyboard focus when it does not cycle
576
- tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle" })), h("slot", { key: '0ce06b895deb1da5fbdefa65b079dbd1ada349f7' }))));
577
+ tabIndex: !isHandleCycle ? -1 : 0, "aria-label": "Activate to adjust the size of the dialog overlaying the screen", onClick: isHandleCycle ? this.onHandleClick : undefined, part: "handle" })), h("slot", { key: '87d1d4a725c463cefed2e96a6a9fee36ba6e8311' }))));
577
578
  }
578
579
  static get is() { return "ion-modal"; }
579
580
  static get encapsulation() { return "shadow"; }
@@ -1019,6 +1020,24 @@ export class Modal {
1019
1020
  "reflect": false,
1020
1021
  "defaultValue": "false"
1021
1022
  },
1023
+ "focusTrap": {
1024
+ "type": "boolean",
1025
+ "mutable": false,
1026
+ "complexType": {
1027
+ "original": "boolean",
1028
+ "resolved": "boolean",
1029
+ "references": {}
1030
+ },
1031
+ "required": false,
1032
+ "optional": false,
1033
+ "docs": {
1034
+ "tags": [],
1035
+ "text": "If `true`, focus will not be allowed to move outside of this overlay.\nIf 'false', focus will be allowed to move outside of the overlay.\n\nIn most scenarios this property should remain set to `true`. Setting\nthis property to `false` can cause severe accessibility issues as users\nrelying on assistive technologies may be able to move focus into\na confusing state. We recommend only setting this to `false` when\nabsolutely necessary.\n\nDevelopers may want to consider disabling focus trapping if this\noverlay presents a non-Ionic overlay from a 3rd party library.\nDevelopers would disable focus trapping on the Ionic overlay\nwhen presenting the 3rd party overlay and then re-enable\nfocus trapping when dismissing the 3rd party overlay and moving\nfocus back to the Ionic overlay."
1036
+ },
1037
+ "attribute": "focus-trap",
1038
+ "reflect": false,
1039
+ "defaultValue": "true"
1040
+ },
1022
1041
  "canDismiss": {
1023
1042
  "type": "boolean",
1024
1043
  "mutable": false,
@@ -4,6 +4,7 @@
4
4
  import { h } from "@stencil/core";
5
5
  import { newSpecPage } from "@stencil/core/testing";
6
6
  import { Modal } from "../../modal";
7
+ import { FOCUS_TRAP_DISABLE_CLASS } from "../../../../utils/overlays";
7
8
  describe('modal: htmlAttributes inheritance', () => {
8
9
  it('should correctly inherit attributes on host', async () => {
9
10
  const page = await newSpecPage({
@@ -14,3 +15,21 @@ describe('modal: htmlAttributes inheritance', () => {
14
15
  await expect(modal.getAttribute('data-testid')).toBe('basic-modal');
15
16
  });
16
17
  });
18
+ describe('modal: focus trap', () => {
19
+ it('should set the focus trap class when disabled', async () => {
20
+ const page = await newSpecPage({
21
+ components: [Modal],
22
+ template: () => h("ion-modal", { focusTrap: false, overlayIndex: 1 }),
23
+ });
24
+ const modal = page.body.querySelector('ion-modal');
25
+ expect(modal.classList.contains(FOCUS_TRAP_DISABLE_CLASS)).toBe(true);
26
+ });
27
+ it('should not set the focus trap class by default', async () => {
28
+ const page = await newSpecPage({
29
+ components: [Modal],
30
+ template: () => h("ion-modal", { overlayIndex: 1 }),
31
+ });
32
+ const modal = page.body.querySelector('ion-modal');
33
+ expect(modal.classList.contains(FOCUS_TRAP_DISABLE_CLASS)).toBe(false);
34
+ });
35
+ });
@@ -141,7 +141,6 @@
141
141
  --ion-safe-area-left: 0px;
142
142
  display: flex;
143
143
  flex-direction: column;
144
- overflow: hidden;
145
144
  }
146
145
 
147
146
  :host(.popover-nested.popover-side-left) {
@@ -7,7 +7,7 @@ import { CoreDelegate, attachComponent, detachComponent } from "../../utils/fram
7
7
  import { addEventListener, raf, hasLazyBuild } from "../../utils/helpers";
8
8
  import { createLockController } from "../../utils/lock-controller";
9
9
  import { printIonWarning } from "../../utils/logging/index";
10
- import { BACKDROP, dismiss, eventMethod, prepareOverlay, present, setOverlayId } from "../../utils/overlays";
10
+ import { BACKDROP, dismiss, eventMethod, prepareOverlay, present, setOverlayId, FOCUS_TRAP_DISABLE_CLASS, } from "../../utils/overlays";
11
11
  import { isPlatform } from "../../utils/platform";
12
12
  import { getClassMap } from "../../utils/theme";
13
13
  import { deepReady, waitForMount } from "../../utils/transition/index";
@@ -107,6 +107,7 @@ export class Popover {
107
107
  this.arrow = true;
108
108
  this.isOpen = false;
109
109
  this.keyboardEvents = false;
110
+ this.focusTrap = true;
110
111
  this.keepContentsMounted = false;
111
112
  }
112
113
  onTriggerChange() {
@@ -333,12 +334,12 @@ export class Popover {
333
334
  }
334
335
  render() {
335
336
  const mode = getIonMode(this);
336
- const { onLifecycle, parentPopover, dismissOnSelect, side, arrow, htmlAttributes } = this;
337
+ const { onLifecycle, parentPopover, dismissOnSelect, side, arrow, htmlAttributes, focusTrap } = this;
337
338
  const desktop = isPlatform('desktop');
338
339
  const enableArrow = arrow && !parentPopover;
339
- return (h(Host, Object.assign({ key: 'a4a6fb333562cb2ecc2ac2350541de9be61837af', "aria-modal": "true", "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
340
+ return (h(Host, Object.assign({ key: '4c8d34559a6e383cb778566f2c6e88690def0ba0', "aria-modal": "true", "no-router": true, tabindex: "-1" }, htmlAttributes, { style: {
340
341
  zIndex: `${20000 + this.overlayIndex}`,
341
- }, class: Object.assign(Object.assign({}, getClassMap(this.cssClass)), { [mode]: true, 'popover-translucent': this.translucent, 'overlay-hidden': true, 'popover-desktop': desktop, [`popover-side-${side}`]: true, 'popover-nested': !!parentPopover }), onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }), !parentPopover && h("ion-backdrop", { tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), h("div", { key: 'de9c7ad73f221e6e9a55e2bc7e1ffad7b936b0dd', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && h("div", { class: "popover-arrow", part: "arrow" }), h("div", { key: '1cb5abc9835c044e6d14d444283f34b65b0b134e', class: "popover-content", part: "content" }, h("slot", { key: '0e4db95e6341e823f87877325bb1164193ae6676' })))));
342
+ }, class: Object.assign(Object.assign({}, getClassMap(this.cssClass)), { [mode]: true, 'popover-translucent': this.translucent, 'overlay-hidden': true, 'popover-desktop': desktop, [`popover-side-${side}`]: true, [FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false, 'popover-nested': !!parentPopover }), onIonPopoverDidPresent: onLifecycle, onIonPopoverWillPresent: onLifecycle, onIonPopoverWillDismiss: onLifecycle, onIonPopoverDidDismiss: onLifecycle, onIonBackdropTap: this.onBackdropTap }), !parentPopover && h("ion-backdrop", { tappable: this.backdropDismiss, visible: this.showBackdrop, part: "backdrop" }), h("div", { key: '710e22246d151441d80f2bbd618145d7dc651f09', class: "popover-wrapper ion-overlay-wrapper", onClick: dismissOnSelect ? () => this.dismiss() : undefined }, enableArrow && h("div", { class: "popover-arrow", part: "arrow" }), h("div", { key: 'aefcaa864ba3b941597bae15dedc51c33e1b7bb9', class: "popover-content", part: "content" }, h("slot", { key: 'b2384f79e042a5946b65511bd339bd0cf7772d18' })))));
342
343
  }
343
344
  static get is() { return "ion-popover"; }
344
345
  static get encapsulation() { return "shadow"; }
@@ -860,6 +861,24 @@ export class Popover {
860
861
  "reflect": false,
861
862
  "defaultValue": "false"
862
863
  },
864
+ "focusTrap": {
865
+ "type": "boolean",
866
+ "mutable": false,
867
+ "complexType": {
868
+ "original": "boolean",
869
+ "resolved": "boolean",
870
+ "references": {}
871
+ },
872
+ "required": false,
873
+ "optional": false,
874
+ "docs": {
875
+ "tags": [],
876
+ "text": "If `true`, focus will not be allowed to move outside of this overlay.\nIf 'false', focus will be allowed to move outside of the overlay.\n\nIn most scenarios this property should remain set to `true`. Setting\nthis property to `false` can cause severe accessibility issues as users\nrelying on assistive technologies may be able to move focus into\na confusing state. We recommend only setting this to `false` when\nabsolutely necessary.\n\nDevelopers may want to consider disabling focus trapping if this\noverlay presents a non-Ionic overlay from a 3rd party library.\nDevelopers would disable focus trapping on the Ionic overlay\nwhen presenting the 3rd party overlay and then re-enable\nfocus trapping when dismissing the 3rd party overlay and moving\nfocus back to the Ionic overlay."
877
+ },
878
+ "attribute": "focus-trap",
879
+ "reflect": false,
880
+ "defaultValue": "true"
881
+ },
863
882
  "keepContentsMounted": {
864
883
  "type": "boolean",
865
884
  "mutable": false,
@@ -141,7 +141,6 @@
141
141
  --ion-safe-area-left: 0px;
142
142
  display: flex;
143
143
  flex-direction: column;
144
- overflow: hidden;
145
144
  }
146
145
 
147
146
  :host(.popover-nested.popover-side-left) {
@@ -46,6 +46,82 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
46
46
  * Translucent popovers are only available on iOS
47
47
  */
48
48
  configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
49
+ test.describe(title('popover: scrolling'), async () => {
50
+ test.beforeEach(({ skip }) => {
51
+ test.info().annotations.push({
52
+ type: 'issue',
53
+ description: 'https://github.com/ionic-team/ionic-framework/issues/29211',
54
+ });
55
+ // We are testing if Ionic sets overflow is set correctly on elements,
56
+ // so we do not need to test across browsers
57
+ skip.browser('webkit', 'Behavior does not vary across browsers');
58
+ skip.browser('firefox', 'Behavior does not vary across browsers');
59
+ });
60
+ test('should scroll to bottom without IonContent', async ({ page }) => {
61
+ await page.setContent(`
62
+ <style>
63
+ ion-popover {
64
+ --height: 150px;
65
+ }
66
+ </style>
67
+ <ion-popover>
68
+ <p>Text</p>
69
+ <p>Text</p>
70
+ <p>Text</p>
71
+ <p>Text</p>
72
+ <p>Text</p>
73
+ <p>Text</p>
74
+ <p>Text</p>
75
+ <p>Text</p>
76
+ <p>Text</p>
77
+ <p>Text</p>
78
+ </ion-popover>
79
+ `, config);
80
+ const popover = page.locator('ion-popover');
81
+ const viewport = popover.locator('.popover-viewport');
82
+ const p = popover.locator('p');
83
+ const lastP = await p.last();
84
+ await popover.evaluate((el) => el.present());
85
+ await expect(lastP).not.toBeInViewport();
86
+ // hover over viewport and scroll to bottom
87
+ await viewport.hover();
88
+ await page.mouse.wheel(0, 500);
89
+ await expect(lastP).toBeInViewport();
90
+ });
91
+ test('should scroll to bottom with IonContent', async ({ page }) => {
92
+ await page.setContent(`
93
+ <style>
94
+ ion-popover {
95
+ --height: 150px;
96
+ }
97
+ </style>
98
+ <ion-popover>
99
+ <ion-content>
100
+ <p>Text</p>
101
+ <p>Text</p>
102
+ <p>Text</p>
103
+ <p>Text</p>
104
+ <p>Text</p>
105
+ <p>Text</p>
106
+ <p>Text</p>
107
+ <p>Text</p>
108
+ <p>Text</p>
109
+ <p>Text</p>
110
+ </ion-content>
111
+ </ion-popover>
112
+ `, config);
113
+ const popover = page.locator('ion-popover');
114
+ const content = popover.locator('ion-content');
115
+ const p = popover.locator('p');
116
+ const lastP = await p.last();
117
+ await popover.evaluate((el) => el.present());
118
+ await expect(lastP).not.toBeInViewport();
119
+ // hover over viewport and scroll to bottom
120
+ await content.hover();
121
+ await page.mouse.wheel(0, 500);
122
+ await expect(lastP).toBeInViewport();
123
+ });
124
+ });
49
125
  test.describe(title('popover: translucent variants'), async () => {
50
126
  let popoverFixture;
51
127
  test.beforeEach(async ({ page }) => {
@@ -4,6 +4,7 @@
4
4
  import { h } from "@stencil/core";
5
5
  import { newSpecPage } from "@stencil/core/testing";
6
6
  import { Popover } from "../../popover";
7
+ import { FOCUS_TRAP_DISABLE_CLASS } from "../../../../utils/overlays";
7
8
  describe('popover: htmlAttributes inheritance', () => {
8
9
  it('should correctly inherit attributes on host', async () => {
9
10
  const page = await newSpecPage({
@@ -14,3 +15,21 @@ describe('popover: htmlAttributes inheritance', () => {
14
15
  await expect(popover.getAttribute('data-testid')).toBe('basic-popover');
15
16
  });
16
17
  });
18
+ describe('popover: focus trap', () => {
19
+ it('should set the focus trap class when disabled', async () => {
20
+ const page = await newSpecPage({
21
+ components: [Popover],
22
+ template: () => h("ion-popover", { focusTrap: false, overlayIndex: 1 }),
23
+ });
24
+ const popover = page.body.querySelector('ion-popover');
25
+ expect(popover.classList.contains(FOCUS_TRAP_DISABLE_CLASS)).toBe(true);
26
+ });
27
+ it('should not set the focus trap class by default', async () => {
28
+ const page = await newSpecPage({
29
+ components: [Popover],
30
+ template: () => h("ion-popover", { overlayIndex: 1 }),
31
+ });
32
+ const popover = page.body.querySelector('ion-popover');
33
+ expect(popover.classList.contains(FOCUS_TRAP_DISABLE_CLASS)).toBe(false);
34
+ });
35
+ });
@@ -478,7 +478,7 @@ export class Searchbar {
478
478
  "mutable": false,
479
479
  "complexType": {
480
480
  "original": "AutocompleteTypes",
481
- "resolved": "\"name\" | \"on\" | \"off\" | \"honorific-prefix\" | \"given-name\" | \"additional-name\" | \"family-name\" | \"honorific-suffix\" | \"nickname\" | \"email\" | \"username\" | \"new-password\" | \"current-password\" | \"one-time-code\" | \"organization-title\" | \"organization\" | \"street-address\" | \"address-line1\" | \"address-line2\" | \"address-line3\" | \"address-level4\" | \"address-level3\" | \"address-level2\" | \"address-level1\" | \"country\" | \"country-name\" | \"postal-code\" | \"cc-name\" | \"cc-given-name\" | \"cc-additional-name\" | \"cc-family-name\" | \"cc-number\" | \"cc-exp\" | \"cc-exp-month\" | \"cc-exp-year\" | \"cc-csc\" | \"cc-type\" | \"transaction-currency\" | \"transaction-amount\" | \"language\" | \"bday\" | \"bday-day\" | \"bday-month\" | \"bday-year\" | \"sex\" | \"tel\" | \"tel-country-code\" | \"tel-national\" | \"tel-area-code\" | \"tel-local\" | \"tel-extension\" | \"impp\" | \"url\" | \"photo\"",
481
+ "resolved": "\"name\" | \"email\" | \"tel\" | \"url\" | \"on\" | \"off\" | \"honorific-prefix\" | \"given-name\" | \"additional-name\" | \"family-name\" | \"honorific-suffix\" | \"nickname\" | \"username\" | \"new-password\" | \"current-password\" | \"one-time-code\" | \"organization-title\" | \"organization\" | \"street-address\" | \"address-line1\" | \"address-line2\" | \"address-line3\" | \"address-level4\" | \"address-level3\" | \"address-level2\" | \"address-level1\" | \"country\" | \"country-name\" | \"postal-code\" | \"cc-name\" | \"cc-given-name\" | \"cc-additional-name\" | \"cc-family-name\" | \"cc-number\" | \"cc-exp\" | \"cc-exp-month\" | \"cc-exp-year\" | \"cc-csc\" | \"cc-type\" | \"transaction-currency\" | \"transaction-amount\" | \"language\" | \"bday\" | \"bday-day\" | \"bday-month\" | \"bday-year\" | \"sex\" | \"tel-country-code\" | \"tel-national\" | \"tel-area-code\" | \"tel-local\" | \"tel-extension\" | \"impp\" | \"photo\"",
482
482
  "references": {
483
483
  "AutocompleteTypes": {
484
484
  "location": "import",
@@ -3,13 +3,141 @@
3
3
  */
4
4
  import { expect } from "@playwright/test";
5
5
  import { configs, test } from "../../../../utils/test/playwright/index";
6
- configs().forEach(({ title, screenshot, config }) => {
6
+ configs({ palettes: ['light', 'dark'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
7
+ test.describe(title('toolbar: basic (LTR only)'), () => {
8
+ test('should not have visual regressions with text only', async ({ page }) => {
9
+ await page.setContent(`
10
+ <ion-header>
11
+ <ion-toolbar>
12
+ <ion-title>Toolbar</ion-title>
13
+ </ion-toolbar>
14
+ </ion-header>
15
+ `, config);
16
+ const header = page.locator('ion-header');
17
+ await expect(header).toHaveScreenshot(screenshot(`toolbar-basic-text-only`));
18
+ });
19
+ });
20
+ });
21
+ configs({ palettes: ['light', 'dark'] }).forEach(({ title, screenshot, config }) => {
7
22
  test.describe(title('toolbar: basic'), () => {
8
- test('should not have visual regressions', async ({ page }) => {
9
- await page.goto(`/src/components/toolbar/test/basic`, config);
10
- // capture both header toolbars at once, but don't include all the white space in the ion-content
23
+ test('should truncate long title with ellipsis', async ({ page }) => {
24
+ await page.setContent(`
25
+ <ion-header>
26
+ <ion-toolbar>
27
+ <ion-title>This is the title that never ends. It just goes on and on my friend.</ion-title>
28
+ </ion-toolbar>
29
+ </ion-header>
30
+ `, config);
31
+ const header = page.locator('ion-header');
32
+ await expect(header).toHaveScreenshot(screenshot(`toolbar-basic-long-text`));
33
+ });
34
+ test('should not have visual regressions with icon-only buttons', async ({ page }) => {
35
+ await page.setContent(`
36
+ <ion-header>
37
+ <ion-toolbar>
38
+ <ion-buttons slot="secondary">
39
+ <ion-button>
40
+ <ion-icon slot="icon-only" name="person-circle"></ion-icon>
41
+ </ion-button>
42
+ <ion-button>
43
+ <ion-icon slot="icon-only" name="search"></ion-icon>
44
+ </ion-button>
45
+ </ion-buttons>
46
+ <ion-buttons slot="primary">
47
+ <ion-button color="secondary">
48
+ <ion-icon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical"></ion-icon>
49
+ </ion-button>
50
+ </ion-buttons>
51
+ <ion-title>Toolbar</ion-title>
52
+ </ion-toolbar>
53
+ <ion-toolbar>
54
+ <ion-buttons slot="secondary">
55
+ <ion-button class="ion-activated">
56
+ <ion-icon slot="icon-only" name="person-circle"></ion-icon>
57
+ </ion-button>
58
+ <ion-button class="ion-activated">
59
+ <ion-icon slot="icon-only" name="search"></ion-icon>
60
+ </ion-button>
61
+ </ion-buttons>
62
+ <ion-buttons slot="primary">
63
+ <ion-button color="secondary" class="ion-activated">
64
+ <ion-icon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical"></ion-icon>
65
+ </ion-button>
66
+ </ion-buttons>
67
+ <ion-title>Activated Buttons</ion-title>
68
+ </ion-toolbar>
69
+ </ion-header>
70
+ `, config);
71
+ const header = page.locator('ion-header');
72
+ await expect(header).toHaveScreenshot(screenshot(`toolbar-basic-icon-buttons`));
73
+ });
74
+ test('should not have visual regressions with buttons with icons and text', async ({ page }) => {
75
+ await page.setContent(`
76
+ <ion-header>
77
+ <ion-toolbar>
78
+ <ion-buttons slot="secondary">
79
+ <ion-button fill="solid">
80
+ <ion-icon slot="start" name="person-circle"></ion-icon>
81
+ Solid
82
+ </ion-button>
83
+ </ion-buttons>
84
+ <ion-title>Solid</ion-title>
85
+ <ion-buttons slot="primary">
86
+ <ion-button fill="solid" color="secondary">
87
+ Help
88
+ <ion-icon slot="end" name="help-circle"></ion-icon>
89
+ </ion-button>
90
+ </ion-buttons>
91
+ </ion-toolbar>
92
+ <ion-toolbar>
93
+ <ion-buttons slot="secondary">
94
+ <ion-button fill="solid" class="ion-activated">
95
+ <ion-icon slot="start" name="person-circle"></ion-icon>
96
+ Solid
97
+ </ion-button>
98
+ </ion-buttons>
99
+ <ion-title>Solid Activated</ion-title>
100
+ <ion-buttons slot="primary">
101
+ <ion-button fill="solid" color="secondary" class="ion-activated">
102
+ Help
103
+ <ion-icon slot="end" name="help-circle"></ion-icon>
104
+ </ion-button>
105
+ </ion-buttons>
106
+ </ion-toolbar>
107
+ <ion-toolbar>
108
+ <ion-buttons slot="secondary">
109
+ <ion-button fill="outline">
110
+ <ion-icon slot="start" name="star"></ion-icon>
111
+ Star
112
+ </ion-button>
113
+ </ion-buttons>
114
+ <ion-title>Outline</ion-title>
115
+ <ion-buttons slot="primary">
116
+ <ion-button color="secondary" fill="outline">
117
+ Info
118
+ <ion-icon slot="end" name="information-circle"></ion-icon>
119
+ </ion-button>
120
+ </ion-buttons>
121
+ </ion-toolbar>
122
+ <ion-toolbar>
123
+ <ion-buttons slot="secondary">
124
+ <ion-button fill="outline" class="ion-activated">
125
+ <ion-icon slot="start" name="star"></ion-icon>
126
+ Star
127
+ </ion-button>
128
+ </ion-buttons>
129
+ <ion-title>Outline Activated</ion-title>
130
+ <ion-buttons slot="primary">
131
+ <ion-button color="secondary" fill="outline" class="ion-activated">
132
+ Info
133
+ <ion-icon slot="end" name="information-circle"></ion-icon>
134
+ </ion-button>
135
+ </ion-buttons>
136
+ </ion-toolbar>
137
+ </ion-header>
138
+ `, config);
11
139
  const header = page.locator('ion-header');
12
- await expect(header).toHaveScreenshot(screenshot(`toolbar-basic`));
140
+ await expect(header).toHaveScreenshot(screenshot(`toolbar-basic-text-icon-buttons`));
13
141
  });
14
142
  });
15
143
  });
@@ -152,7 +152,7 @@ const trapKeyboardFocus = (ev, doc) => {
152
152
  * behind the sheet should be focusable until
153
153
  * the backdrop is enabled.
154
154
  */
155
- if (lastOverlay.classList.contains('ion-disable-focus-trap')) {
155
+ if (lastOverlay.classList.contains(FOCUS_TRAP_DISABLE_CLASS)) {
156
156
  return;
157
157
  }
158
158
  const trapScopedFocus = () => {
@@ -827,3 +827,4 @@ const revealOverlaysToScreenReaders = () => {
827
827
  }
828
828
  }
829
829
  };
830
+ export const FOCUS_TRAP_DISABLE_CLASS = 'ion-disable-focus-trap';