@ionic/core 8.8.16-dev.11784841344.1aa1a41c → 8.8.16-dev.11784914346.10d0804c

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 (205) hide show
  1. package/components/ion-accordion.js +1 -1
  2. package/components/ion-action-sheet.js +1 -1
  3. package/components/ion-alert.js +1 -1
  4. package/components/ion-avatar.js +1 -1
  5. package/components/ion-back-button.js +1 -1
  6. package/components/ion-badge.js +1 -1
  7. package/components/ion-breadcrumb.js +1 -1
  8. package/components/ion-button.js +1 -1
  9. package/components/ion-buttons.js +1 -1
  10. package/components/ion-content.js +1 -1
  11. package/components/ion-datetime.js +1 -1
  12. package/components/ion-fab-button.js +1 -1
  13. package/components/ion-footer.js +1 -1
  14. package/components/ion-header.js +1 -1
  15. package/components/ion-icon.js +1 -1
  16. package/components/ion-input-password-toggle.js +1 -1
  17. package/components/ion-input.js +1 -1
  18. package/components/ion-item-option.js +1 -1
  19. package/components/ion-item.js +1 -1
  20. package/components/ion-menu-button.js +1 -1
  21. package/components/ion-refresher-content.js +1 -1
  22. package/components/ion-reorder.js +1 -1
  23. package/components/ion-searchbar.js +1 -1
  24. package/components/ion-segment-button.js +1 -1
  25. package/components/ion-select-modal.js +1 -1
  26. package/components/ion-select-popover.js +1 -1
  27. package/components/ion-select.js +1 -1
  28. package/components/ion-tab-bar.js +1 -1
  29. package/components/ion-tab-button.js +1 -1
  30. package/components/ion-title.js +1 -1
  31. package/components/ion-toast.js +1 -1
  32. package/components/ion-toggle.js +1 -1
  33. package/components/{p-DiKh2eQw.js → p-4u9RNymb.js} +1 -1
  34. package/components/{p-B8KYxaMx.js → p-B8xhFBOE.js} +1 -1
  35. package/components/p-BAnNwWMA.js +4 -0
  36. package/components/p-BYZR_5L4.js +4 -0
  37. package/components/p-B_zaqq5F.js +4 -0
  38. package/components/p-CO9VfZyc.js +4 -0
  39. package/components/p-Cjx0xPoU.js +4 -0
  40. package/components/p-CyWeCU8e.js +4 -0
  41. package/components/p-DRnK3A-V.js +4 -0
  42. package/components/p-DcVqGRkT.js +4 -0
  43. package/components/p-Dght1fh7.js +4 -0
  44. package/components/p-GpxJMpJu.js +4 -0
  45. package/dist/cjs/{index-Cu9JNpPi.js → index-CgAbCW6L.js} +1 -1
  46. package/dist/cjs/ion-accordion_2.cjs.entry.js +1 -1
  47. package/dist/cjs/ion-action-sheet.cjs.entry.js +3 -3
  48. package/dist/cjs/ion-alert.cjs.entry.js +3 -3
  49. package/dist/cjs/ion-app_8.cjs.entry.js +194 -65
  50. package/dist/cjs/ion-avatar_3.cjs.entry.js +4 -4
  51. package/dist/cjs/ion-back-button.cjs.entry.js +1 -1
  52. package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +1 -1
  53. package/dist/cjs/ion-button_2.cjs.entry.js +3 -3
  54. package/dist/cjs/ion-datetime_3.cjs.entry.js +1 -1
  55. package/dist/cjs/ion-fab_3.cjs.entry.js +1 -1
  56. package/dist/cjs/ion-input-password-toggle.cjs.entry.js +1 -1
  57. package/dist/cjs/ion-input.cjs.entry.js +4 -4
  58. package/dist/cjs/ion-item-option_3.cjs.entry.js +1 -1
  59. package/dist/cjs/ion-item_8.cjs.entry.js +1 -1
  60. package/dist/cjs/ion-menu_3.cjs.entry.js +1 -1
  61. package/dist/cjs/ion-refresher_2.cjs.entry.js +1 -1
  62. package/dist/cjs/ion-reorder_2.cjs.entry.js +1 -1
  63. package/dist/cjs/ion-searchbar.cjs.entry.js +2 -2
  64. package/dist/cjs/ion-segment_2.cjs.entry.js +1 -1
  65. package/dist/cjs/ion-select-modal.cjs.entry.js +4 -4
  66. package/dist/cjs/ion-select_3.cjs.entry.js +5 -5
  67. package/dist/cjs/ion-tab-bar_2.cjs.entry.js +78 -80
  68. package/dist/cjs/ion-toggle.cjs.entry.js +1 -1
  69. package/dist/cjs/ionic.cjs.js +1 -1
  70. package/dist/cjs/loader.cjs.js +1 -1
  71. package/dist/cjs/scroll-hide-controller-G9HOmmhN.js +345 -0
  72. package/dist/collection/components/action-sheet/action-sheet.ionic.css +2 -5
  73. package/dist/collection/components/action-sheet/action-sheet.ios.css +2 -1
  74. package/dist/collection/components/action-sheet/action-sheet.md.css +2 -1
  75. package/dist/collection/components/alert/alert.ionic.css +2 -5
  76. package/dist/collection/components/alert/alert.ios.css +2 -1
  77. package/dist/collection/components/alert/alert.md.css +2 -1
  78. package/dist/collection/components/avatar/avatar.ionic.css +12 -6
  79. package/dist/collection/components/badge/badge.ionic.css +6 -3
  80. package/dist/collection/components/badge/badge.ios.css +4 -2
  81. package/dist/collection/components/badge/badge.md.css +2 -1
  82. package/dist/collection/components/button/button.ionic.css +4 -2
  83. package/dist/collection/components/buttons/buttons.ionic.css +1 -1
  84. package/dist/collection/components/content/content.css +39 -0
  85. package/dist/collection/components/footer/footer-interface.js +1 -0
  86. package/dist/collection/components/footer/footer.ios.css +19 -4
  87. package/dist/collection/components/footer/footer.js +102 -15
  88. package/dist/collection/components/footer/footer.md.css +28 -0
  89. package/dist/collection/components/header/header-interface.js +1 -0
  90. package/dist/collection/components/header/header.ionic.css +153 -0
  91. package/dist/collection/components/header/header.ios.css +153 -123
  92. package/dist/collection/components/header/header.js +139 -28
  93. package/dist/collection/components/header/header.md.css +176 -1
  94. package/dist/collection/components/header/header.utils.js +6 -13
  95. package/dist/collection/components/input/input.ionic.css +2 -1
  96. package/dist/collection/components/input/input.ios.css +2 -1
  97. package/dist/collection/components/input/input.md.css +2 -1
  98. package/dist/collection/components/item-option/item-option.ionic.css +2 -1
  99. package/dist/collection/components/searchbar/searchbar.ionic.css +6 -2
  100. package/dist/collection/components/segment-button/segment-button.ionic.css +2 -1
  101. package/dist/collection/components/select/select.ionic.css +2 -1
  102. package/dist/collection/components/select-modal/select-modal.ionic.css +2 -5
  103. package/dist/collection/components/select-modal/select-modal.ios.css +2 -1
  104. package/dist/collection/components/select-modal/select-modal.md.css +2 -1
  105. package/dist/collection/components/select-popover/select-popover.ionic.css +2 -5
  106. package/dist/collection/components/select-popover/select-popover.ios.css +2 -1
  107. package/dist/collection/components/select-popover/select-popover.md.css +2 -1
  108. package/dist/collection/components/tab-bar/tab-bar.ionic.css +25 -3
  109. package/dist/collection/components/tab-bar/tab-bar.ios.css +15 -0
  110. package/dist/collection/components/tab-bar/tab-bar.js +94 -88
  111. package/dist/collection/components/tab-bar/tab-bar.md.css +15 -0
  112. package/dist/collection/components/tab-button/tab-button.ionic.css +2 -1
  113. package/dist/collection/components/title/title.md.css +7 -0
  114. package/dist/collection/utils/scroll-hide-controller.js +178 -0
  115. package/dist/docs.json +144 -32
  116. package/dist/esm/{index-1y3VhUSy.js → index-D2tu5BUg.js} +1 -1
  117. package/dist/esm/ion-accordion_2.entry.js +1 -1
  118. package/dist/esm/ion-action-sheet.entry.js +3 -3
  119. package/dist/esm/ion-alert.entry.js +3 -3
  120. package/dist/esm/ion-app_8.entry.js +194 -65
  121. package/dist/esm/ion-avatar_3.entry.js +4 -4
  122. package/dist/esm/ion-back-button.entry.js +1 -1
  123. package/dist/esm/ion-breadcrumb_2.entry.js +1 -1
  124. package/dist/esm/ion-button_2.entry.js +3 -3
  125. package/dist/esm/ion-datetime_3.entry.js +1 -1
  126. package/dist/esm/ion-fab_3.entry.js +1 -1
  127. package/dist/esm/ion-input-password-toggle.entry.js +1 -1
  128. package/dist/esm/ion-input.entry.js +4 -4
  129. package/dist/esm/ion-item-option_3.entry.js +1 -1
  130. package/dist/esm/ion-item_8.entry.js +1 -1
  131. package/dist/esm/ion-menu_3.entry.js +1 -1
  132. package/dist/esm/ion-refresher_2.entry.js +1 -1
  133. package/dist/esm/ion-reorder_2.entry.js +1 -1
  134. package/dist/esm/ion-searchbar.entry.js +2 -2
  135. package/dist/esm/ion-segment_2.entry.js +1 -1
  136. package/dist/esm/ion-select-modal.entry.js +4 -4
  137. package/dist/esm/ion-select_3.entry.js +5 -5
  138. package/dist/esm/ion-tab-bar_2.entry.js +79 -81
  139. package/dist/esm/ion-toggle.entry.js +1 -1
  140. package/dist/esm/ionic.js +1 -1
  141. package/dist/esm/loader.js +1 -1
  142. package/dist/esm/scroll-hide-controller-CUNW7EpD.js +342 -0
  143. package/dist/html.html-data.json +36 -4
  144. package/dist/ionic/ionic.esm.js +1 -1
  145. package/dist/ionic/p-07bd8446.entry.js +4 -0
  146. package/dist/ionic/p-103e1d9f.entry.js +4 -0
  147. package/dist/ionic/{p-eeb7b373.entry.js → p-18bc4f2d.entry.js} +1 -1
  148. package/dist/ionic/p-248265c2.entry.js +4 -0
  149. package/dist/ionic/{p-fb457fdd.entry.js → p-3bc5b5e9.entry.js} +1 -1
  150. package/dist/ionic/{p-42a882b7.entry.js → p-43b00c5b.entry.js} +1 -1
  151. package/dist/ionic/{p-d0f253fc.entry.js → p-56224b93.entry.js} +1 -1
  152. package/dist/ionic/p-5732396e.entry.js +4 -0
  153. package/dist/ionic/{p-b3d04a86.entry.js → p-58d8877d.entry.js} +1 -1
  154. package/dist/ionic/{p-9e9be378.entry.js → p-5d079dc1.entry.js} +1 -1
  155. package/dist/ionic/{p-d0dfc9a3.entry.js → p-5e9665dd.entry.js} +1 -1
  156. package/dist/ionic/{p-7b2fe639.entry.js → p-5fee5cc1.entry.js} +1 -1
  157. package/dist/ionic/p-64734604.entry.js +4 -0
  158. package/dist/ionic/p-69feeff9.entry.js +4 -0
  159. package/dist/ionic/p-83acfa2d.entry.js +4 -0
  160. package/dist/ionic/{p-f692219d.entry.js → p-849b1759.entry.js} +1 -1
  161. package/dist/ionic/{p-a09c7a4c.entry.js → p-86f040e0.entry.js} +1 -1
  162. package/dist/ionic/p-8cb23f27.entry.js +4 -0
  163. package/dist/ionic/p-C1I_d964.js +4 -0
  164. package/dist/ionic/p-b97778f5.entry.js +4 -0
  165. package/dist/ionic/p-be9db7e8.entry.js +4 -0
  166. package/dist/ionic/{p-2fba8f15.entry.js → p-c04429f2.entry.js} +1 -1
  167. package/dist/ionic/p-c25a2a9b.entry.js +4 -0
  168. package/dist/ionic/{p-a797625e.entry.js → p-d272ff4f.entry.js} +1 -1
  169. package/dist/types/components/footer/footer-interface.d.ts +1 -0
  170. package/dist/types/components/footer/footer.d.ts +16 -0
  171. package/dist/types/components/header/header-interface.d.ts +1 -0
  172. package/dist/types/components/header/header.d.ts +17 -0
  173. package/dist/types/components/header/header.utils.d.ts +4 -5
  174. package/dist/types/components/tab-bar/tab-bar-interface.d.ts +1 -0
  175. package/dist/types/components/tab-bar/tab-bar.d.ts +17 -14
  176. package/dist/types/components.d.ts +37 -13
  177. package/dist/types/utils/scroll-hide-controller.d.ts +56 -0
  178. package/hydrate/index.js +477 -175
  179. package/hydrate/index.mjs +477 -175
  180. package/package.json +2 -2
  181. package/components/p-BZwQa9ey.js +0 -4
  182. package/components/p-CJCMdFb9.js +0 -4
  183. package/components/p-Ck_9SoHZ.js +0 -4
  184. package/components/p-CmnPD02Z.js +0 -4
  185. package/components/p-D-Xa9lMG.js +0 -4
  186. package/components/p-DFSqPtzD.js +0 -4
  187. package/components/p-NPsFR8Ng.js +0 -4
  188. package/components/p-U2gyA6Z0.js +0 -4
  189. package/components/p-q8wGOPJB.js +0 -4
  190. package/dist/cjs/keyboard-controller-CefyW9lm.js +0 -169
  191. package/dist/esm/keyboard-controller-BFwRdk2T.js +0 -167
  192. package/dist/ionic/p-0c4d9d7c.entry.js +0 -4
  193. package/dist/ionic/p-40dc9dbd.entry.js +0 -4
  194. package/dist/ionic/p-54419365.entry.js +0 -4
  195. package/dist/ionic/p-6293e9f1.entry.js +0 -4
  196. package/dist/ionic/p-7de397c7.entry.js +0 -4
  197. package/dist/ionic/p-8cf82b85.entry.js +0 -4
  198. package/dist/ionic/p-MqqcZQSB.js +0 -4
  199. package/dist/ionic/p-a6e04ca3.entry.js +0 -4
  200. package/dist/ionic/p-a6fe63f0.entry.js +0 -4
  201. package/dist/ionic/p-b275f17e.entry.js +0 -4
  202. package/dist/ionic/p-c5635175.entry.js +0 -4
  203. package/dist/ionic/p-dc8e0b91.entry.js +0 -4
  204. /package/components/{p-J03hHbbL.js → p-BaPtaYEC.js} +0 -0
  205. /package/dist/ionic/{p-1y3VhUSy.js → p-D2tu5BUg.js} +0 -0
@@ -155,7 +155,8 @@
155
155
 
156
156
  .select-option-start > ion-icon,
157
157
  .select-option-end > ion-icon {
158
- font-size: 24px;
158
+ width: 24px;
159
+ height: 24px;
159
160
  }
160
161
 
161
162
  .select-option-start > ion-img,
@@ -255,27 +255,33 @@
255
255
  }
256
256
 
257
257
  :host(.avatar-xxsmall) ::slotted(ion-icon) {
258
- font-size: var(--token-font-size-300, 0.75rem);
258
+ width: var(--token-scale-300, 12px);
259
+ height: var(--token-scale-300, 12px);
259
260
  }
260
261
 
261
262
  :host(.avatar-xsmall) ::slotted(ion-icon) {
262
- font-size: var(--token-font-size-400, 1rem);
263
+ width: var(--token-scale-400, 16px);
264
+ height: var(--token-scale-400, 16px);
263
265
  }
264
266
 
265
267
  :host(.avatar-small) ::slotted(ion-icon) {
266
- font-size: var(--token-font-size-500, 1.25rem);
268
+ width: var(--token-scale-500, 20px);
269
+ height: var(--token-scale-500, 20px);
267
270
  }
268
271
 
269
272
  :host(.avatar-medium) ::slotted(ion-icon) {
270
- font-size: var(--token-font-size-600, 1.5rem);
273
+ width: var(--token-scale-600, 24px);
274
+ height: var(--token-scale-600, 24px);
271
275
  }
272
276
 
273
277
  :host(.avatar-large) ::slotted(ion-icon) {
274
- font-size: var(--token-font-size-700, 1.75rem);
278
+ width: var(--token-scale-700, 28px);
279
+ height: var(--token-scale-700, 28px);
275
280
  }
276
281
 
277
282
  :host(.avatar-xlarge) ::slotted(ion-icon) {
278
- font-size: var(--token-font-size-800, 2rem);
283
+ width: var(--token-scale-800, 32px);
284
+ height: var(--token-scale-800, 32px);
279
285
  }
280
286
 
281
287
  :host ::slotted(ion-badge.badge-vertical-top:empty) {
@@ -188,7 +188,8 @@
188
188
  }
189
189
 
190
190
  :host(.badge-small) ::slotted(ion-icon) {
191
- font-size: var(--token-font-size-300, 0.75rem);
191
+ width: var(--token-scale-300, 12px);
192
+ height: var(--token-scale-300, 12px);
192
193
  }
193
194
 
194
195
  /* Medium Badge */
@@ -209,7 +210,8 @@
209
210
 
210
211
  :host(.badge-medium) ::slotted(ion-icon),
211
212
  :host(.badge-large) ::slotted(ion-icon) {
212
- font-size: var(--token-font-size-400, 1rem);
213
+ width: var(--token-scale-400, 16px);
214
+ height: var(--token-scale-400, 16px);
213
215
  }
214
216
 
215
217
  :host(:empty) {
@@ -268,5 +270,6 @@
268
270
  height: var(--token-scale-400, 16px);
269
271
  }
270
272
  :host(:not(:empty).in-button) ::slotted(ion-icon) {
271
- font-size: var(--token-font-size-300, 0.75rem);
273
+ width: var(--token-scale-300, 12px);
274
+ height: var(--token-scale-300, 12px);
272
275
  }
@@ -201,7 +201,8 @@
201
201
  line-height: 20px;
202
202
  }
203
203
  :host(:not(:empty).in-button) ::slotted(ion-icon) {
204
- font-size: 12px;
204
+ width: 12px;
205
+ height: 12px;
205
206
  }
206
207
 
207
208
  /**
@@ -285,8 +286,9 @@
285
286
  :host([vertical].in-tab-button) ::slotted(ion-icon) {
286
287
  top: 50%;
287
288
  position: absolute;
289
+ width: 12px;
290
+ height: 12px;
288
291
  transform: translate(-50%, -50%);
289
- font-size: 12px;
290
292
  }
291
293
  :host([vertical].in-tab-button) ::slotted(ion-icon) {
292
294
  inset-inline-start: 50%;
@@ -201,7 +201,8 @@
201
201
  line-height: 20px;
202
202
  }
203
203
  :host(:not(:empty).in-button) ::slotted(ion-icon) {
204
- font-size: 12px;
204
+ width: 12px;
205
+ height: 12px;
205
206
  }
206
207
 
207
208
  /**
@@ -462,13 +462,15 @@ ion-ripple-effect {
462
462
  :host(.button-medium) ::slotted(ion-icon[slot=start]),
463
463
  :host(.button-medium) ::slotted(ion-icon[slot=end]),
464
464
  :host(.button-medium) ::slotted(ion-icon[slot=icon-only]) {
465
- font-size: var(--token-font-size-500, 1.25rem);
465
+ width: var(--token-scale-500, 20px);
466
+ height: var(--token-scale-500, 20px);
466
467
  }
467
468
 
468
469
  :host(.button-large) ::slotted(ion-icon[slot=start]),
469
470
  :host(.button-large) ::slotted(ion-icon[slot=end]),
470
471
  :host(.button-large) ::slotted(ion-icon[slot=icon-only]) {
471
- font-size: var(--token-font-size-600, 1.5rem);
472
+ width: var(--token-scale-600, 24px);
473
+ height: var(--token-scale-600, 24px);
472
474
  }
473
475
 
474
476
  :host(.button-has-icon-only) {
@@ -93,5 +93,5 @@
93
93
  }
94
94
 
95
95
  ::slotted(*) ion-icon[slot=icon-only] {
96
- font-size: var(--token-font-size-500, 1.25rem);
96
+ font-size: var(--token-font-size-600, 1.5rem);
97
97
  }
@@ -281,4 +281,43 @@
281
281
  * still allow the fixed content to appear under the scroll content if specified.
282
282
  */
283
283
  transform: translateZ(0);
284
+ }
285
+
286
+ :host(.content-header-hide-scroll-partner:not(.content-fullscreen)) .inner-scroll {
287
+ transition: transform 300ms cubic-bezier(0, 0, 0.2, 1), height 300ms cubic-bezier(0, 0, 0.2, 1);
288
+ }
289
+
290
+ :host(.content-header-hide-scroll-partner:not(.content-fullscreen).content-header-hide-scroll-hidden) .inner-scroll {
291
+ height: calc(100% + var(--internal-header-hide-height, 0px));
292
+ transform: translateY(calc(-1 * var(--internal-header-hide-height, 0px)));
293
+ transition: transform 200ms cubic-bezier(0.4, 0, 1, 1), height 200ms cubic-bezier(0.4, 0, 1, 1);
294
+ }
295
+
296
+ :host(.content-footer-hide-scroll-partner:not(.content-fullscreen)) .inner-scroll {
297
+ transition: height 200ms cubic-bezier(0.16, 1, 0.3, 1);
298
+ }
299
+
300
+ :host(.content-footer-hide-scroll-partner:not(.content-fullscreen).content-footer-hide-scroll-hidden) .inner-scroll {
301
+ height: calc(100% + var(--internal-footer-hide-height, 0px));
302
+ transition: height 350ms cubic-bezier(0.4, 0, 1, 1);
303
+ }
304
+
305
+ :host(.content-tab-bar-hide-scroll-partner:not(.content-fullscreen)) .inner-scroll {
306
+ transition: height 200ms cubic-bezier(0.16, 1, 0.3, 1);
307
+ }
308
+
309
+ :host(.content-tab-bar-hide-scroll-partner:not(.content-fullscreen).content-tab-bar-hide-scroll-hidden) .inner-scroll {
310
+ height: calc(100% + var(--internal-tab-bar-hide-height, 0px));
311
+ transition: height 350ms cubic-bezier(0.4, 0, 1, 1);
312
+ }
313
+
314
+ @media (prefers-reduced-motion: reduce) {
315
+ :host(.content-header-hide-scroll-partner:not(.content-fullscreen)) .inner-scroll,
316
+ :host(.content-header-hide-scroll-partner:not(.content-fullscreen).content-header-hide-scroll-hidden) .inner-scroll,
317
+ :host(.content-footer-hide-scroll-partner:not(.content-fullscreen)) .inner-scroll,
318
+ :host(.content-footer-hide-scroll-partner:not(.content-fullscreen).content-footer-hide-scroll-hidden) .inner-scroll,
319
+ :host(.content-tab-bar-hide-scroll-partner:not(.content-fullscreen)) .inner-scroll,
320
+ :host(.content-tab-bar-hide-scroll-partner:not(.content-fullscreen).content-tab-bar-hide-scroll-hidden) .inner-scroll {
321
+ transition: none;
322
+ }
284
323
  }
@@ -71,6 +71,25 @@ ion-footer.footer-toolbar-padding ion-toolbar:last-of-type {
71
71
  padding-bottom: var(--ion-safe-area-bottom, 0);
72
72
  }
73
73
 
74
+ .footer-collapse-fade ion-toolbar {
75
+ --opacity-scale: inherit;
76
+ }
77
+
78
+ ion-footer.footer-scroll-effect-hide {
79
+ transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);
80
+ }
81
+
82
+ ion-footer.footer-scroll-effect-hide.footer-scroll-hidden {
83
+ transform: translateY(100%);
84
+ transition: transform 350ms cubic-bezier(0.4, 0, 1, 1);
85
+ }
86
+
87
+ @media (prefers-reduced-motion: reduce) {
88
+ ion-footer.footer-scroll-effect-hide,
89
+ ion-footer.footer-scroll-effect-hide.footer-scroll-hidden {
90
+ transition: none;
91
+ }
92
+ }
74
93
  /**
75
94
  * Convert a pixels given value into rem
76
95
  *
@@ -151,8 +170,4 @@ ion-footer.footer-toolbar-padding ion-toolbar:last-of-type {
151
170
  }
152
171
  .footer-ios.ion-no-border ion-toolbar:first-of-type {
153
172
  --border-width: 0;
154
- }
155
-
156
- .footer-collapse-fade ion-toolbar {
157
- --opacity-scale: inherit;
158
173
  }
@@ -4,6 +4,8 @@
4
4
  import { Host, h } from "@stencil/core";
5
5
  import { findIonContent, getScrollElement, printIonContentErrorMsg } from "../../utils/content/index";
6
6
  import { createKeyboardController } from "../../utils/keyboard/keyboard-controller";
7
+ import { printIonWarning } from "../../utils/logging/index";
8
+ import { createScrollHideController } from "../../utils/scroll-hide-controller";
7
9
  import { config } from "../../global/config";
8
10
  import { getIonTheme } from "../../global/ionic-global";
9
11
  import { handleFooterFade } from "./footer.utils";
@@ -15,6 +17,9 @@ export class Footer {
15
17
  constructor() {
16
18
  this.keyboardCtrl = null;
17
19
  this.keyboardCtrlPromise = null;
20
+ this.scrollHideCtrlPromise = null;
21
+ this.hasWarnedCollapse = false;
22
+ this.fadeSetupId = 0;
18
23
  this.keyboardVisible = false;
19
24
  /**
20
25
  * If `true`, the footer will be translucent.
@@ -25,27 +30,66 @@ export class Footer {
25
30
  * attribute needs to be set on the content.
26
31
  */
27
32
  this.translucent = false;
28
- this.checkCollapsibleFooter = () => {
29
- const theme = getIonTheme(this);
30
- if (theme !== 'ios') {
33
+ this.checkCollapsibleFooter = async () => {
34
+ const { scrollEffect, collapse } = this;
35
+ if (collapse !== undefined && scrollEffect === undefined && !this.hasWarnedCollapse) {
36
+ this.hasWarnedCollapse = true;
37
+ printIonWarning(`[ion-footer] - The \`collapse\` property is deprecated. Use \`scrollEffect\` instead.\nExample: <ion-footer scroll-effect="${collapse}">`, this.el);
38
+ }
39
+ const effect = scrollEffect !== null && scrollEffect !== void 0 ? scrollEffect : collapse;
40
+ // Skip teardown/rebuild if the effect hasn't changed.
41
+ // This prevents keyboard toggles (which trigger re-renders via
42
+ // @State keyboardVisible) from destroying the scroll controller
43
+ // and resetting isHidden.
44
+ if (effect === this.activeEffect) {
31
45
  return;
32
46
  }
33
- const { collapse } = this;
34
- const hasFade = collapse === 'fade';
47
+ const hasHide = effect === 'hide';
48
+ const hasFade = effect === 'fade';
35
49
  this.destroyCollapsibleFooter();
36
- if (hasFade) {
37
- const appRootSelector = config.get('appRootSelector', 'ion-app');
38
- const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
39
- const contentEl = pageEl ? findIonContent(pageEl) : null;
50
+ const appRootSelector = config.get('appRootSelector', 'ion-app');
51
+ const pageEl = this.el.closest(`${appRootSelector}, ion-page, .ion-page, page-inner`);
52
+ const contentEl = pageEl ? findIonContent(pageEl) : null;
53
+ if (hasHide && contentEl) {
54
+ this.activeEffect = effect;
55
+ await this.setupScrollEffectHide(contentEl);
56
+ return;
57
+ }
58
+ // fade via the deprecated `collapse` prop is iOS-only.
59
+ // fade via the new `scrollEffect` prop works in all themes.
60
+ const isModeRestricted = scrollEffect === undefined && getIonTheme(this) !== 'ios';
61
+ if (hasFade && !isModeRestricted) {
40
62
  if (!contentEl) {
41
63
  printIonContentErrorMsg(this.el);
42
64
  return;
43
65
  }
44
66
  this.setupFadeFooter(contentEl);
67
+ this.activeEffect = effect;
68
+ }
69
+ };
70
+ this.setupScrollEffectHide = async (contentEl) => {
71
+ const setupPromise = createScrollHideController(contentEl, {
72
+ el: this.el,
73
+ cssVar: '--internal-footer-hide-height',
74
+ hiddenClass: 'footer-scroll-hidden',
75
+ contentPartnerClass: 'content-footer-hide-scroll-partner',
76
+ contentHiddenClass: 'content-footer-hide-scroll-hidden',
77
+ });
78
+ this.scrollHideCtrlPromise = setupPromise;
79
+ const controller = await setupPromise;
80
+ if (this.scrollHideCtrlPromise === setupPromise) {
81
+ this.scrollHideCtrlPromise = null;
82
+ controller.init();
83
+ this.scrollHideCtrl = controller;
45
84
  }
46
85
  };
47
86
  this.setupFadeFooter = async (contentEl) => {
48
- const scrollEl = (this.scrollEl = await getScrollElement(contentEl));
87
+ const setupId = ++this.fadeSetupId;
88
+ const scrollEl = await getScrollElement(contentEl);
89
+ if (this.fadeSetupId !== setupId) {
90
+ return;
91
+ }
92
+ this.scrollEl = scrollEl;
49
93
  /**
50
94
  * Handle fading of toolbars on scroll
51
95
  */
@@ -90,6 +134,7 @@ export class Footer {
90
134
  }
91
135
  }
92
136
  disconnectedCallback() {
137
+ this.destroyCollapsibleFooter();
93
138
  if (this.keyboardCtrlPromise) {
94
139
  this.keyboardCtrlPromise.then((ctrl) => ctrl.destroy());
95
140
  this.keyboardCtrlPromise = null;
@@ -100,25 +145,38 @@ export class Footer {
100
145
  }
101
146
  }
102
147
  destroyCollapsibleFooter() {
148
+ this.activeEffect = undefined;
149
+ this.fadeSetupId++;
150
+ this.scrollHideCtrlPromise = null;
151
+ if (this.scrollHideCtrl) {
152
+ this.scrollHideCtrl.destroy();
153
+ this.scrollHideCtrl = undefined;
154
+ }
103
155
  if (this.scrollEl && this.contentScrollCallback) {
104
156
  this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
105
157
  this.contentScrollCallback = undefined;
106
158
  }
107
159
  }
108
160
  render() {
109
- const { translucent, collapse } = this;
161
+ const { translucent, scrollEffect, collapse } = this;
110
162
  const theme = getIonTheme(this);
163
+ const effect = scrollEffect !== null && scrollEffect !== void 0 ? scrollEffect : collapse;
164
+ // fade via the deprecated `collapse` prop is iOS-only.
165
+ const isModeRestricted = scrollEffect === undefined && theme !== 'ios';
166
+ const hasHide = effect === 'hide';
167
+ const hasFade = effect === 'fade' && !isModeRestricted;
111
168
  const tabs = this.el.closest('ion-tabs');
112
169
  const tabBar = tabs === null || tabs === void 0 ? void 0 : tabs.querySelector(':scope > ion-tab-bar');
113
- return (h(Host, { key: '4a2989a177b47ee26ffa23e2c9f5418773584796', role: "contentinfo", class: {
170
+ return (h(Host, { key: 'a0777b4a639d22e15374879f018efcf589e756f8', role: "contentinfo", class: {
114
171
  [theme]: true,
115
172
  // Used internally for styling
116
173
  [`footer-${theme}`]: true,
117
174
  [`footer-translucent`]: translucent,
118
175
  [`footer-translucent-${theme}`]: translucent,
119
176
  ['footer-toolbar-padding']: !this.keyboardVisible && (!tabBar || tabBar.slot !== 'bottom'),
120
- [`footer-collapse-${collapse}`]: collapse !== undefined,
121
- } }, theme === 'ios' && translucent && h("div", { key: 'c644963db3e06254014e398ea02189d6127ccf61', class: "footer-background" }), h("slot", { key: '839e33c6c30f5c1c703239a19458ff10da9a5e76' })));
177
+ 'footer-collapse-fade': hasFade,
178
+ 'footer-scroll-effect-hide': hasHide,
179
+ } }, theme === 'ios' && translucent && h("div", { key: 'd78b46870cbf11c95b066d649c04ec398b66e614', class: "footer-background" }), h("slot", { key: '9dc34787cd29597fe1b1198db317602014ac1483' })));
122
180
  }
123
181
  static get is() { return "ion-footer"; }
124
182
  static get originalStyleUrls() {
@@ -137,6 +195,32 @@ export class Footer {
137
195
  }
138
196
  static get properties() {
139
197
  return {
198
+ "scrollEffect": {
199
+ "type": "string",
200
+ "mutable": false,
201
+ "complexType": {
202
+ "original": "FooterScrollEffect",
203
+ "resolved": "\"fade\" | \"hide\" | undefined",
204
+ "references": {
205
+ "FooterScrollEffect": {
206
+ "location": "import",
207
+ "path": "./footer-interface",
208
+ "id": "src/components/footer/footer-interface.ts::FooterScrollEffect",
209
+ "referenceLocation": "FooterScrollEffect"
210
+ }
211
+ }
212
+ },
213
+ "required": false,
214
+ "optional": true,
215
+ "docs": {
216
+ "tags": [],
217
+ "text": "Describes the scroll effect that will be applied to the footer.\n`\"hide\"` slides the footer out of view when scrolling down and back in\nwhen scrolling up.\n`\"fade\"` fades the toolbar background on scroll."
218
+ },
219
+ "getter": false,
220
+ "setter": false,
221
+ "reflect": true,
222
+ "attribute": "scroll-effect"
223
+ },
140
224
  "collapse": {
141
225
  "type": "string",
142
226
  "mutable": false,
@@ -148,7 +232,10 @@ export class Footer {
148
232
  "required": false,
149
233
  "optional": true,
150
234
  "docs": {
151
- "tags": [],
235
+ "tags": [{
236
+ "name": "deprecated",
237
+ "text": "Use `scrollEffect` instead."
238
+ }],
152
239
  "text": "Describes the scroll effect that will be applied to the footer.\nOnly applies when the theme is `\"ios\"`."
153
240
  },
154
241
  "getter": false,
@@ -71,6 +71,25 @@ ion-footer.footer-toolbar-padding ion-toolbar:last-of-type {
71
71
  padding-bottom: var(--ion-safe-area-bottom, 0);
72
72
  }
73
73
 
74
+ .footer-collapse-fade ion-toolbar {
75
+ --opacity-scale: inherit;
76
+ }
77
+
78
+ ion-footer.footer-scroll-effect-hide {
79
+ transition: transform 200ms cubic-bezier(0.16, 1, 0.3, 1);
80
+ }
81
+
82
+ ion-footer.footer-scroll-effect-hide.footer-scroll-hidden {
83
+ transform: translateY(100%);
84
+ transition: transform 350ms cubic-bezier(0.4, 0, 1, 1);
85
+ }
86
+
87
+ @media (prefers-reduced-motion: reduce) {
88
+ ion-footer.footer-scroll-effect-hide,
89
+ ion-footer.footer-scroll-effect-hide.footer-scroll-hidden {
90
+ transition: none;
91
+ }
92
+ }
74
93
  /**
75
94
  * Convert a pixels given value into rem
76
95
  *
@@ -136,6 +155,15 @@ ion-footer.footer-toolbar-padding ion-toolbar:last-of-type {
136
155
  box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
137
156
  }
138
157
 
158
+ /**
159
+ * The fade effect fades the toolbar background via --opacity-scale,
160
+ * but box-shadow is not affected by that variable. Remove it so
161
+ * the shadow doesn't persist when the background is faded out.
162
+ */
163
+ .footer-md.footer-collapse-fade {
164
+ box-shadow: none;
165
+ }
166
+
139
167
  .footer-md.ion-no-border {
140
168
  box-shadow: none;
141
169
  }
@@ -9,6 +9,159 @@ ion-header ion-toolbar:first-of-type {
9
9
  padding-top: var(--ion-safe-area-top, 0);
10
10
  }
11
11
 
12
+ .header-collapse-fade ion-toolbar {
13
+ --opacity-scale: inherit;
14
+ }
15
+
16
+ /**
17
+ * Override styles applied during the page transition to prevent
18
+ * header flickering.
19
+ */
20
+ .header-collapse-fade.header-transitioning ion-toolbar {
21
+ --background: transparent;
22
+ --border-style: none;
23
+ }
24
+
25
+ .header-collapse-condense {
26
+ z-index: 9;
27
+ }
28
+
29
+ .header-collapse-condense ion-toolbar {
30
+ position: sticky;
31
+ top: 0;
32
+ }
33
+
34
+ .header-collapse-condense ion-toolbar:first-of-type {
35
+ /**
36
+ * The toolbar that contains the collapsible
37
+ * large title should not have safe area padding applied.
38
+ */
39
+ padding-top: 0px;
40
+ z-index: 1;
41
+ }
42
+
43
+ /**
44
+ * Large title toolbar should just use the content background
45
+ * since it needs to blend in with the header above it.
46
+ */
47
+ .header-collapse-condense ion-toolbar {
48
+ z-index: 0;
49
+ }
50
+
51
+ .header-collapse-condense ion-toolbar:last-of-type {
52
+ --border-width: 0px;
53
+ }
54
+
55
+ .header-collapse-condense ion-toolbar ion-searchbar {
56
+ padding-top: 0px;
57
+ padding-bottom: 13px;
58
+ }
59
+
60
+ .header-collapse-main {
61
+ --opacity-scale: 1;
62
+ }
63
+
64
+ .header-collapse-main ion-toolbar {
65
+ --opacity-scale: inherit;
66
+ }
67
+
68
+ .header-collapse-main ion-toolbar.in-toolbar ion-title,
69
+ .header-collapse-main ion-toolbar.in-toolbar ion-buttons {
70
+ transition: all 0.2s ease-in-out;
71
+ }
72
+
73
+ /**
74
+ * Large title toolbar should just use the content background
75
+ * since it needs to blend in with the header above it.
76
+ */
77
+ .header-collapse-condense ion-toolbar,
78
+ .header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar {
79
+ --background: var(--ion-background-color, #fff);
80
+ }
81
+
82
+ /**
83
+ * Override styles applied during the page transition to prevent
84
+ * header flickering.
85
+ */
86
+ .header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar {
87
+ --border-style: none;
88
+ --opacity-scale: 1;
89
+ }
90
+
91
+ .header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-title,
92
+ .header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
93
+ opacity: 0;
94
+ pointer-events: none;
95
+ }
96
+
97
+ /**
98
+ * There is a bug in Safari where changing
99
+ * the opacity of an element in a scrollable container
100
+ * while rubber-banding causes the scroll position
101
+ * to jump to the top
102
+ */
103
+ .header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-title,
104
+ .header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
105
+ visibility: hidden;
106
+ }
107
+
108
+ /**
109
+ * The main header is only hidden once the collapsible large
110
+ * title is configured. As a result, if the main header loads
111
+ * before the collapsible large title is configured then the
112
+ * main header will be visible briefly before being hidden
113
+ * by the collapsible large title.
114
+ *
115
+ * The following selector ensures that any main header
116
+ * on a page with a collapsible large title is hidden
117
+ * before the collapsible large title is configured.
118
+ * Once the collapsible large title is configured the main
119
+ * header will have the ".header-collapse-main" class, and
120
+ * this selector will no longer apply.
121
+ *
122
+ * The :has(...) part of the selector ensures a couple things:
123
+ * 1. This will only apply within a page view since the content
124
+ * must be a subsequent-sibling of the header (~ ion-content).
125
+ * 2. This will only apply when that content has an active condense
126
+ * header (the .header-collapse-condense class).
127
+ *
128
+ * We use opacity: 0 to avoid a layout shift.
129
+ * We use the class (not the attribute) because the class is only
130
+ * added when the condense effect is valid (large title present).
131
+ * The attribute alone is not sufficient since it would match even
132
+ * when the effect is guarded (e.g. no large title).
133
+ */
134
+ ion-header:not(.header-collapse-main):has(~ ion-content ion-header.header-collapse-condense) {
135
+ opacity: 0;
136
+ }
137
+
138
+ /**
139
+ * The deprecated collapse="condense" prop is iOS-only.
140
+ * On non-iOS themes, the condense header should be hidden since
141
+ * the JS won't activate it. Uses a class instead of an attribute
142
+ * selector because collapse is not a reflected prop, and framework
143
+ * proxies (Angular/Vue) bind it as a property.
144
+ */
145
+ .header-collapse-condense-hidden {
146
+ display: none;
147
+ }
148
+
149
+ ion-header.header-scroll-effect-hide {
150
+ transition: transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1);
151
+ }
152
+
153
+ ion-header.header-scroll-effect-hide.header-scroll-hidden {
154
+ transform: translateY(-100%);
155
+ transition: transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1);
156
+ opacity: 0;
157
+ }
158
+
159
+ @media (prefers-reduced-motion: reduce) {
160
+ ion-header.header-scroll-effect-hide,
161
+ ion-header.header-scroll-effect-hide.header-scroll-hidden {
162
+ transition: none;
163
+ }
164
+ }
12
165
  /**
13
166
  * A heuristic that applies CSS to tablet
14
167
  * viewports.