@rdlabo/ionic-theme-ios27 0.1.0-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.
Files changed (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +241 -0
  3. package/dist/css/components/ion-action-sheet.css +1 -0
  4. package/dist/css/components/ion-alert.css +1 -0
  5. package/dist/css/components/ion-button.css +1 -0
  6. package/dist/css/components/ion-card.css +1 -0
  7. package/dist/css/components/ion-content.css +1 -0
  8. package/dist/css/components/ion-datetime.css +1 -0
  9. package/dist/css/components/ion-fab.css +1 -0
  10. package/dist/css/components/ion-inputs.css +1 -0
  11. package/dist/css/components/ion-list.css +1 -0
  12. package/dist/css/components/ion-loading.css +1 -0
  13. package/dist/css/components/ion-menu.css +1 -0
  14. package/dist/css/components/ion-modal.css +1 -0
  15. package/dist/css/components/ion-picker.css +1 -0
  16. package/dist/css/components/ion-popover.css +1 -0
  17. package/dist/css/components/ion-range.css +1 -0
  18. package/dist/css/components/ion-searchbar.css +1 -0
  19. package/dist/css/components/ion-segment.css +1 -0
  20. package/dist/css/components/ion-tabs.css +1 -0
  21. package/dist/css/components/ion-toast.css +1 -0
  22. package/dist/css/components/ion-toggle.css +1 -0
  23. package/dist/css/components/ion-toolbar.css +1 -0
  24. package/dist/css/default-variables.css +1 -0
  25. package/dist/css/ionic-theme-ios26-dark-always.css +1 -0
  26. package/dist/css/ionic-theme-ios26-dark-class.css +1 -0
  27. package/dist/css/ionic-theme-ios26-dark-system.css +1 -0
  28. package/dist/css/ionic-theme-ios26.css +1 -0
  29. package/dist/css/md-ion-list-inset.css +1 -0
  30. package/dist/css/md-remove-ios-class-effect.css +1 -0
  31. package/dist/css/utils/api.css +1 -0
  32. package/dist/css/utils/dark/ion-button.css +1 -0
  33. package/dist/css/utils/dark/ion-fab.css +1 -0
  34. package/dist/css/utils/dark/ion-segment.css +1 -0
  35. package/dist/css/utils/dark/ion-tabs.css +1 -0
  36. package/dist/css/utils/searchable.css +1 -0
  37. package/dist/css/utils/structured-list.css +1 -0
  38. package/dist/css/utils/theme-dark.css +1 -0
  39. package/dist/css/utils/translucent.css +1 -0
  40. package/dist/docs.json +234 -0
  41. package/dist/focus-controller/index.d.ts +6 -0
  42. package/dist/focus-controller/index.d.ts.map +1 -0
  43. package/dist/focus-controller/index.js +62 -0
  44. package/dist/focus-controller /index.d.ts +6 -0
  45. package/dist/focus-controller /index.d.ts.map +1 -0
  46. package/dist/focus-controller /index.js +62 -0
  47. package/dist/index.d.ts +9 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +30 -0
  50. package/dist/popover/animations/ios.enter.d.ts +4 -0
  51. package/dist/popover/animations/ios.enter.d.ts.map +1 -0
  52. package/dist/popover/animations/ios.enter.js +97 -0
  53. package/dist/popover/animations/ios.leave.d.ts +3 -0
  54. package/dist/popover/animations/ios.leave.d.ts.map +1 -0
  55. package/dist/popover/animations/ios.leave.js +60 -0
  56. package/dist/popover/popover-interface.d.ts +38 -0
  57. package/dist/popover/popover-interface.d.ts.map +1 -0
  58. package/dist/popover/popover-interface.js +1 -0
  59. package/dist/popover/utils.d.ts +37 -0
  60. package/dist/popover/utils.d.ts.map +1 -0
  61. package/dist/popover/utils.js +377 -0
  62. package/dist/sheets-of-glass/animations.d.ts +8 -0
  63. package/dist/sheets-of-glass/animations.d.ts.map +1 -0
  64. package/dist/sheets-of-glass/animations.js +97 -0
  65. package/dist/sheets-of-glass/index.d.ts +3 -0
  66. package/dist/sheets-of-glass/index.d.ts.map +1 -0
  67. package/dist/sheets-of-glass/index.js +174 -0
  68. package/dist/sheets-of-glass/interfaces.d.ts +16 -0
  69. package/dist/sheets-of-glass/interfaces.d.ts.map +1 -0
  70. package/dist/sheets-of-glass/interfaces.js +1 -0
  71. package/dist/tab-bar-searchable/animations/enter.d.ts +8 -0
  72. package/dist/tab-bar-searchable/animations/enter.d.ts.map +1 -0
  73. package/dist/tab-bar-searchable/animations/enter.js +73 -0
  74. package/dist/tab-bar-searchable/animations/leave.d.ts +8 -0
  75. package/dist/tab-bar-searchable/animations/leave.d.ts.map +1 -0
  76. package/dist/tab-bar-searchable/animations/leave.js +66 -0
  77. package/dist/tab-bar-searchable/index.d.ts +4 -0
  78. package/dist/tab-bar-searchable/index.d.ts.map +1 -0
  79. package/dist/tab-bar-searchable/index.js +75 -0
  80. package/dist/tab-bar-searchable/interfaces.d.ts +41 -0
  81. package/dist/tab-bar-searchable/interfaces.d.ts.map +1 -0
  82. package/dist/tab-bar-searchable/interfaces.js +5 -0
  83. package/dist/tab-bar-searchable/utils.d.ts +12 -0
  84. package/dist/tab-bar-searchable/utils.d.ts.map +1 -0
  85. package/dist/tab-bar-searchable/utils.js +60 -0
  86. package/dist/transition/index.d.ts +19 -0
  87. package/dist/transition/index.d.ts.map +1 -0
  88. package/dist/transition/index.js +219 -0
  89. package/dist/transition/ios.transition.d.ts +5 -0
  90. package/dist/transition/ios.transition.d.ts.map +1 -0
  91. package/dist/transition/ios.transition.js +609 -0
  92. package/dist/utils.d.ts +17 -0
  93. package/dist/utils.d.ts.map +1 -0
  94. package/dist/utils.js +69 -0
  95. package/docs/e2e-testing.md +51 -0
  96. package/docs/eslint.md +73 -0
  97. package/docs/experimental-animation.md +85 -0
  98. package/docs/features.md +88 -0
  99. package/docs/feedback.md +65 -0
  100. package/docs/ios-18.md +16 -0
  101. package/docs/migration.md +94 -0
  102. package/docs/special-markup.md +145 -0
  103. package/docs/using-ion-item-group.md +47 -0
  104. package/package.json +63 -0
  105. package/src/focus-controller/index.ts +123 -0
  106. package/src/index.ts +33 -0
  107. package/src/popover/animations/ios.enter.ts +144 -0
  108. package/src/popover/animations/ios.leave.ts +76 -0
  109. package/src/popover/popover-interface.ts +44 -0
  110. package/src/popover/utils.ts +696 -0
  111. package/src/sheets-of-glass/animations.ts +120 -0
  112. package/src/sheets-of-glass/index.ts +214 -0
  113. package/src/sheets-of-glass/interfaces.ts +17 -0
  114. package/src/styles/components/ion-action-sheet.scss +85 -0
  115. package/src/styles/components/ion-alert.scss +66 -0
  116. package/src/styles/components/ion-button.scss +443 -0
  117. package/src/styles/components/ion-card.scss +7 -0
  118. package/src/styles/components/ion-content.scss +22 -0
  119. package/src/styles/components/ion-datetime.scss +9 -0
  120. package/src/styles/components/ion-fab.scss +104 -0
  121. package/src/styles/components/ion-inputs.scss +82 -0
  122. package/src/styles/components/ion-list.scss +44 -0
  123. package/src/styles/components/ion-loading.scss +11 -0
  124. package/src/styles/components/ion-menu.scss +110 -0
  125. package/src/styles/components/ion-modal.scss +42 -0
  126. package/src/styles/components/ion-picker.scss +4 -0
  127. package/src/styles/components/ion-popover.scss +33 -0
  128. package/src/styles/components/ion-range.scss +90 -0
  129. package/src/styles/components/ion-searchbar.scss +68 -0
  130. package/src/styles/components/ion-segment.scss +150 -0
  131. package/src/styles/components/ion-tabs.scss +118 -0
  132. package/src/styles/components/ion-toast.scss +35 -0
  133. package/src/styles/components/ion-toggle.scss +65 -0
  134. package/src/styles/components/ion-toolbar.scss +76 -0
  135. package/src/styles/default-variables.scss +38 -0
  136. package/src/styles/ionic-theme-ios26-dark-always.scss +6 -0
  137. package/src/styles/ionic-theme-ios26-dark-class.scss +6 -0
  138. package/src/styles/ionic-theme-ios26-dark-system.scss +8 -0
  139. package/src/styles/ionic-theme-ios26.scss +23 -0
  140. package/src/styles/md-ion-list-inset.scss +22 -0
  141. package/src/styles/md-remove-ios-class-effect.scss +14 -0
  142. package/src/styles/utils/api.scss +146 -0
  143. package/src/styles/utils/dark/ion-button.scss +58 -0
  144. package/src/styles/utils/dark/ion-fab.scss +18 -0
  145. package/src/styles/utils/dark/ion-segment.scss +12 -0
  146. package/src/styles/utils/dark/ion-tabs.scss +21 -0
  147. package/src/styles/utils/searchable.scss +0 -0
  148. package/src/styles/utils/structured-list.scss +170 -0
  149. package/src/styles/utils/theme-dark.scss +25 -0
  150. package/src/styles/utils/translucent.scss +95 -0
  151. package/src/tab-bar-searchable/animations/enter.ts +92 -0
  152. package/src/tab-bar-searchable/animations/leave.ts +89 -0
  153. package/src/tab-bar-searchable/index.ts +141 -0
  154. package/src/tab-bar-searchable/interfaces.ts +28 -0
  155. package/src/tab-bar-searchable/utils.ts +75 -0
  156. package/src/transition/index.ts +369 -0
  157. package/src/transition/ios.transition.ts +966 -0
  158. package/src/utils.ts +91 -0
@@ -0,0 +1,120 @@
1
+ import type { Animation, AnimationKeyFrames } from '@ionic/core';
2
+ import { AnimationPosition, EffectScales } from './interfaces';
3
+ import { createAnimation, GestureDetail } from '@ionic/core';
4
+ import { getStep } from '../utils';
5
+
6
+ export const getScaleAnimation = (effectElement: Element): Animation => {
7
+ return createAnimation().addElement(effectElement.shadowRoot!.querySelector<HTMLElement>('[part="native"]')!).easing('ease-out');
8
+ };
9
+
10
+ export const createPreMoveAnimation = (
11
+ effectElement: Element,
12
+ tabSelectedElement: Element,
13
+ currentTouchedElement: Element,
14
+ animationPosition: AnimationPosition,
15
+ ): Animation => {
16
+ const diff = Math.max(
17
+ Math.abs(tabSelectedElement.getBoundingClientRect().left - currentTouchedElement.getBoundingClientRect().left),
18
+ 140,
19
+ );
20
+ return createAnimation()
21
+ .duration(diff * 2.1)
22
+ .easing('ease-out')
23
+ .addElement(effectElement)
24
+ .beforeStyles({
25
+ width: `${tabSelectedElement.clientWidth}px`,
26
+ height: `${tabSelectedElement.clientHeight}px`,
27
+ display: 'block',
28
+ opacity: '1',
29
+ transform: 'none',
30
+ })
31
+ .keyframes([
32
+ {
33
+ offset: 0,
34
+ transform: `translate3d(${tabSelectedElement.getBoundingClientRect().left}px, ${animationPosition.positionY}px, 0)`,
35
+ },
36
+ {
37
+ offset: 1,
38
+ transform: `translate3d(${currentTouchedElement.getBoundingClientRect().left}px, ${animationPosition.positionY}px, 0)`,
39
+ },
40
+ ]);
41
+ };
42
+
43
+ export const createMoveAnimation = (
44
+ effectElement: Element,
45
+ detail: GestureDetail,
46
+ tabSelectedElement: Element,
47
+ animationPosition: AnimationPosition,
48
+ ): Animation => {
49
+ return createAnimation()
50
+ .duration(500)
51
+ .addElement(effectElement)
52
+ .beforeStyles({
53
+ width: `${tabSelectedElement.clientWidth}px`,
54
+ height: `${tabSelectedElement.clientHeight}px`,
55
+ display: 'block',
56
+ opacity: '1',
57
+ transform: 'none',
58
+ })
59
+ .fromTo(
60
+ 'transform',
61
+ `translate3d(${animationPosition.minPositionX}px, ${animationPosition.positionY}px, 0)`,
62
+ `translate3d(${animationPosition.maxPositionX}px, ${animationPosition.positionY}px, 0)`,
63
+ )
64
+ .progressStep(getStep(detail.currentX, animationPosition));
65
+ };
66
+
67
+ export const getMoveAnimationKeyframe = (type: 'moveRight' | 'moveLeft' | 'slowly', scales: EffectScales): AnimationKeyFrames => {
68
+ return {
69
+ moveRight: [
70
+ {
71
+ offset: 0,
72
+ transform: scales.large,
73
+ },
74
+ {
75
+ offset: 0.4,
76
+ transform: scales.small,
77
+ },
78
+ {
79
+ offset: 0.75,
80
+ transform: scales.xlarge,
81
+ },
82
+ {
83
+ offset: 1,
84
+ transform: scales.large,
85
+ },
86
+ ],
87
+ moveLeft: [
88
+ {
89
+ offset: 0,
90
+ transform: scales.large,
91
+ },
92
+ {
93
+ offset: 0.1,
94
+ transform: scales.xlarge,
95
+ },
96
+ {
97
+ offset: 0.6,
98
+ transform: scales.small,
99
+ },
100
+ {
101
+ offset: 1,
102
+ transform: scales.large,
103
+ },
104
+ ],
105
+ slowly: [
106
+ {
107
+ offset: 0,
108
+ transform: scales.large,
109
+ },
110
+ {
111
+ offset: 0.4,
112
+ transform: scales.medium,
113
+ },
114
+ {
115
+ offset: 1,
116
+ transform: scales.large,
117
+ },
118
+ ],
119
+ }[type];
120
+ };
@@ -0,0 +1,214 @@
1
+ import { AnimationPosition, EffectScales, registeredEffect } from './interfaces';
2
+ import { createAnimation, createGesture } from '@ionic/core';
3
+ import type { Animation, Gesture, GestureDetail } from '@ionic/core';
4
+ import { changeSelectedElement, cloneElement, getStep } from '../utils';
5
+ import { createMoveAnimation, createPreMoveAnimation, getMoveAnimationKeyframe, getScaleAnimation } from './animations';
6
+
7
+ const GESTURE_NAME = 'ios26-enable-gesture';
8
+ const ANIMATED_NAME = 'ios26-animated';
9
+
10
+ export const registerEffect = (
11
+ targetElement: HTMLElement,
12
+ effectTagName: string,
13
+ selectedClassName: string,
14
+ scales: EffectScales,
15
+ ): registeredEffect | undefined => {
16
+ if (!targetElement.classList.contains('ios')) {
17
+ return undefined;
18
+ }
19
+
20
+ let gesture!: Gesture;
21
+ let moveAnimation: Animation | undefined;
22
+ let currentTouchedElement: HTMLElement | undefined;
23
+ let clearActivatedTimer: ReturnType<typeof setTimeout> | undefined;
24
+ let animationPosition: AnimationPosition | undefined = undefined;
25
+ let scaleAnimationPromise: Promise<void> | undefined;
26
+ let startAnimationPromise: Promise<void> | undefined;
27
+ let maxVelocity = 0;
28
+ const effectElement = cloneElement(effectTagName);
29
+
30
+ /**
31
+ * These event listeners fix a bug where gestures don't complete properly.
32
+ * They terminate the gesture using native events as a fallback.
33
+ */
34
+ const onPointerDown = (event: PointerEvent) => {
35
+ clearActivated();
36
+ gesture.destroy();
37
+ createAnimationGesture();
38
+ const onPointerUp = async (e: PointerEvent) => {
39
+ clearActivatedTimer = setTimeout(async () => {
40
+ await onEndGesture();
41
+ gesture.destroy();
42
+ createAnimationGesture();
43
+ });
44
+ document.removeEventListener('pointerup', onPointerUp);
45
+ };
46
+ document.addEventListener('pointerup', onPointerUp);
47
+ };
48
+ targetElement.addEventListener('pointerdown', onPointerDown);
49
+
50
+ const createAnimationGesture = () => {
51
+ targetElement.classList.add(GESTURE_NAME);
52
+ gesture = createGesture({
53
+ el: targetElement,
54
+ threshold: 0,
55
+ gestureName: `${GESTURE_NAME}_${effectTagName}_${crypto.randomUUID()}`,
56
+ onStart: (event) => onStartGesture(event),
57
+ onMove: (event) => onMoveGesture(event),
58
+ onEnd: () => {
59
+ onEndGesture().then();
60
+ },
61
+ });
62
+ gesture.enable(true);
63
+ };
64
+ createAnimationGesture();
65
+
66
+ const clearActivated = (isEndGesture: boolean = false) => {
67
+ if (!currentTouchedElement) {
68
+ return;
69
+ }
70
+ if (!isEndGesture && !currentTouchedElement.classList.contains(selectedClassName)) {
71
+ currentTouchedElement!.click();
72
+ currentTouchedElement.classList.add(selectedClassName);
73
+ }
74
+ currentTouchedElement.classList.remove('ion-activated');
75
+ currentTouchedElement = undefined;
76
+ effectElement.style.display = 'none';
77
+ maxVelocity = 0;
78
+ targetElement.classList.remove(ANIMATED_NAME);
79
+ };
80
+
81
+ const onStartGesture = (detail: GestureDetail): boolean | undefined => {
82
+ currentTouchedElement = ((detail.event.target as HTMLElement).closest(effectTagName) as HTMLElement) || undefined;
83
+ const tabSelectedElement = targetElement.querySelector(`${effectTagName}.${selectedClassName}`);
84
+ if (currentTouchedElement === undefined || tabSelectedElement === null) {
85
+ return false;
86
+ }
87
+ animationPosition = {
88
+ minPositionX: targetElement.getBoundingClientRect().left,
89
+ maxPositionX: targetElement.getBoundingClientRect().right - tabSelectedElement.clientWidth,
90
+ width: tabSelectedElement.clientWidth,
91
+ positionY: tabSelectedElement.getBoundingClientRect().top,
92
+ };
93
+ targetElement.classList.add(ANIMATED_NAME);
94
+ changeSelectedElement(targetElement, currentTouchedElement, effectTagName, selectedClassName);
95
+
96
+ const startAnimation = (() => {
97
+ if (tabSelectedElement === currentTouchedElement) {
98
+ return new Promise<void>((resolve) => resolve());
99
+ } else {
100
+ const preMoveAnimation = createPreMoveAnimation(effectElement, tabSelectedElement, currentTouchedElement, animationPosition!);
101
+ return preMoveAnimation.play().finally(() => preMoveAnimation.destroy());
102
+ }
103
+ })();
104
+ startAnimationPromise = startAnimation;
105
+ startAnimation.then(() => {
106
+ if (!currentTouchedElement) {
107
+ return;
108
+ }
109
+ moveAnimation = createMoveAnimation(effectElement, detail, tabSelectedElement, animationPosition!);
110
+ moveAnimation.progressStart(
111
+ true,
112
+ getStep(currentTouchedElement.getBoundingClientRect().left + currentTouchedElement.clientWidth / 2, animationPosition!),
113
+ );
114
+ });
115
+ getScaleAnimation(effectElement).duration(200).to('opacity', 1).to('transform', scales.large).play();
116
+ return true;
117
+ };
118
+
119
+ const onMoveGesture = (detail: GestureDetail): boolean | undefined => {
120
+ if (currentTouchedElement === undefined || !moveAnimation) {
121
+ return false; // Skip Animation
122
+ }
123
+ if (scaleAnimationPromise === undefined) {
124
+ if (Math.abs(detail.velocityX) > maxVelocity) {
125
+ maxVelocity = Math.abs(detail.velocityX);
126
+ }
127
+ if (Math.abs(detail.velocityX) > 0.2) {
128
+ scaleAnimationPromise = getScaleAnimation(effectElement)
129
+ .duration(720)
130
+ .keyframes(getMoveAnimationKeyframe('slowly', scales))
131
+ .play()
132
+ .finally(() => (scaleAnimationPromise = undefined));
133
+ }
134
+ if (maxVelocity > 0.2 && Math.abs(detail.velocityX) < 0.15 && Math.abs(detail.startX - detail.currentX) > 100) {
135
+ scaleAnimationPromise = getScaleAnimation(effectElement)
136
+ .duration(720)
137
+ .keyframes(getMoveAnimationKeyframe(detail.velocityX > 0 ? 'moveRight' : 'moveLeft', scales))
138
+ .play()
139
+ .finally(() => (scaleAnimationPromise = undefined));
140
+ maxVelocity = 0;
141
+ }
142
+ }
143
+
144
+ const currentX = detail.currentX;
145
+ const previousY = targetElement.getBoundingClientRect().top + targetElement.getBoundingClientRect().height / 2;
146
+ const nextEl = (targetElement.getRootNode() as Document | ShadowRoot).elementFromPoint(currentX, previousY);
147
+ const latestTouchedElement = (nextEl?.closest(effectTagName) as HTMLElement) || undefined;
148
+
149
+ if (latestTouchedElement && currentTouchedElement !== latestTouchedElement) {
150
+ currentTouchedElement = latestTouchedElement;
151
+ changeSelectedElement(targetElement, currentTouchedElement, effectTagName, selectedClassName);
152
+ }
153
+ moveAnimation.progressStep(getStep(detail.currentX, animationPosition!));
154
+ return true;
155
+ };
156
+
157
+ const onEndGesture = async (): Promise<boolean | undefined> => {
158
+ // タイマーをクリア(正常にonEndGestureが実行された場合)
159
+ if (clearActivatedTimer !== undefined) {
160
+ clearTimeout(clearActivatedTimer);
161
+ clearActivatedTimer = undefined;
162
+ }
163
+
164
+ if (currentTouchedElement && !currentTouchedElement.classList.contains(selectedClassName)) {
165
+ currentTouchedElement.click();
166
+ currentTouchedElement.classList.add(selectedClassName);
167
+ }
168
+
169
+ if (startAnimationPromise) {
170
+ await startAnimationPromise;
171
+ }
172
+
173
+ if (currentTouchedElement === undefined || !moveAnimation) {
174
+ return false;
175
+ }
176
+
177
+ setTimeout(() => {
178
+ if (!currentTouchedElement) {
179
+ return;
180
+ }
181
+ const targetX = currentTouchedElement.getBoundingClientRect().left + currentTouchedElement.clientWidth / 2;
182
+ const step = getStep(targetX, animationPosition!);
183
+ moveAnimation!.progressStep(step);
184
+ });
185
+ await getScaleAnimation(effectElement).duration(120).to('transform', `scale(1, 0.92)`).play();
186
+ moveAnimation!.destroy();
187
+
188
+ clearActivated(true);
189
+ return true;
190
+ };
191
+
192
+ return {
193
+ destroy: () => {
194
+ // Remove event listeners
195
+ targetElement.removeEventListener('pointerdown', onPointerDown);
196
+
197
+ // Clear any pending timer
198
+ if (clearActivatedTimer !== undefined) {
199
+ clearTimeout(clearActivatedTimer);
200
+ clearActivatedTimer = undefined;
201
+ }
202
+
203
+ // Clear activated state
204
+ clearActivated();
205
+
206
+ // Destroy gesture
207
+ if (gesture) {
208
+ gesture.destroy();
209
+ }
210
+ // Remove gesture class
211
+ targetElement.classList.remove(GESTURE_NAME);
212
+ },
213
+ };
214
+ };
@@ -0,0 +1,17 @@
1
+ export interface EffectScales {
2
+ small: string;
3
+ medium: string;
4
+ large: string;
5
+ xlarge: string;
6
+ }
7
+
8
+ export interface registeredEffect {
9
+ destroy: () => void;
10
+ }
11
+
12
+ export interface AnimationPosition {
13
+ minPositionX: number;
14
+ maxPositionX: number;
15
+ width: number;
16
+ positionY: number;
17
+ }
@@ -0,0 +1,85 @@
1
+ @use '../utils/api';
2
+
3
+ ion-action-sheet.ios:not(.ios26-disabled) {
4
+ --backdrop-opacity: 0.2;
5
+ --color: var(--ion-color-step-600, var(--ion-text-color-step-400, #666666));
6
+
7
+ .action-sheet-wrapper {
8
+ padding-bottom: 0;
9
+ bottom: var(--ios26-floating-safe-area-bottom);
10
+ }
11
+
12
+ .action-sheet-container {
13
+ @include api.glass-background-overlay;
14
+ transition: transform 200ms ease;
15
+ &:has(.ion-activated) {
16
+ transform: scale(1.016);
17
+ @include api.glass-background-overlay-activated;
18
+ }
19
+ margin: 0 12px;
20
+ border-radius: 32px;
21
+
22
+ .action-sheet-title,
23
+ .action-sheet-has-sub-title {
24
+ background: none;
25
+ }
26
+ .action-sheet-title {
27
+ padding-top: 8px;
28
+ }
29
+ .action-sheet-has-sub-title {
30
+ }
31
+
32
+ .action-sheet-group {
33
+ background: transparent;
34
+
35
+ button {
36
+ @include api.glass-background-overlay-button-variable;
37
+ &::after {
38
+ content: none;
39
+ }
40
+ &:not(.action-sheet-destructive):not(.action-sheet-selected) {
41
+ --button-color: var(--ion-text-color, #000);
42
+ --button-color-hover: var(--ion-text-color, #000);
43
+ --button-color-activated: var(--ion-text-color, #000);
44
+ }
45
+ &.action-sheet-destructive {
46
+ --button-color: var(--ion-color-danger, #c5000f);
47
+ --button-color-hover: var(--ion-color-danger, #c5000f);
48
+ }
49
+ font-weight: 550;
50
+ &.action-sheet-cancel {
51
+ margin-top: 12px;
52
+ font-weight: 550;
53
+ }
54
+ border-radius: 32px;
55
+ padding: 0 14px;
56
+ min-height: 52px;
57
+ span.action-sheet-button-inner {
58
+ font-size: 1rem;
59
+ ion-icon {
60
+ font-size: 1.2rem;
61
+ }
62
+ }
63
+
64
+ &:not(:last-child) {
65
+ margin-bottom: 8px;
66
+ }
67
+ }
68
+ }
69
+ }
70
+ }
71
+
72
+ /**
73
+ * For ion-select[interface=action-sheet].
74
+ * ios26, action-sheet should not has 'cancel'.
75
+ * It is recommend to use Popover.
76
+ */
77
+ ion-action-sheet.ios.select-action-sheet:not(.ios26-disabled) {
78
+ .action-sheet-container {
79
+ .action-sheet-group {
80
+ button.action-sheet-cancel {
81
+ display: none;
82
+ }
83
+ }
84
+ }
85
+ }
@@ -0,0 +1,66 @@
1
+ @use '../utils/api';
2
+
3
+ ion-alert.ios:not(.ios26-disabled) {
4
+ --min-width: 280px;
5
+ --backdrop-opacity: 0.2;
6
+
7
+ // --max-width: clamp(270px, 16.875rem, 324px);
8
+ --max-width: 322px;
9
+
10
+ transition: transform 200ms ease;
11
+ &:has(.ion-activated) {
12
+ transform: scale(1.016);
13
+ }
14
+
15
+ .alert-wrapper {
16
+ @include api.glass-background-overlay;
17
+ &:has(.ion-activated) {
18
+ @include api.glass-background-overlay-activated;
19
+ }
20
+ border-radius: 32px;
21
+
22
+ .alert-head,
23
+ .alert-message {
24
+ text-align: left;
25
+ margin-left: 14px;
26
+ margin-right: 14px;
27
+ }
28
+
29
+ .alert-message {
30
+ font-size: 0.98rem;
31
+ line-height: 1.2rem;
32
+ color: var(--ion-color-step-600, var(--ion-text-color-step-400, #666666));
33
+ }
34
+
35
+ .alert-radio-group {
36
+ padding: 0;
37
+ margin-bottom: 12px;
38
+ button {
39
+ padding: 0 8px;
40
+ }
41
+ }
42
+
43
+ .alert-button-group {
44
+ padding: 0 8px 12px;
45
+ gap: 8px 0;
46
+ .alert-button {
47
+ @include api.glass-background-overlay-button;
48
+ border: none;
49
+ border-radius: 32px;
50
+ margin: 0 6px;
51
+ min-width: calc(50% - 12px);
52
+ // height: max(44px, 2.75rem);
53
+ height: 48px;
54
+
55
+ &:not(.alert-button-role-destructive) {
56
+ color: var(--ion-text-color, #000);
57
+ }
58
+ font-weight: 550;
59
+ }
60
+ }
61
+
62
+ button.action-sheet-cancel {
63
+ margin-top: 12px;
64
+ }
65
+ }
66
+ }