@rdlabo/ionic-theme-ios27 1.0.0 → 1.0.1-beta.pr194.sha00da872ba249

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.
@@ -0,0 +1 @@
1
+
package/docs/migration.md CHANGED
@@ -21,25 +21,25 @@ npm install @rdlabo/ionic-theme-ios27
21
21
  Replace unconditional iOS 26 imports in your global Sass stylesheet with two mutually exclusive branches. This example uses class-based dark mode:
22
22
 
23
23
  ```diff
24
- +@use 'sass:meta';
24
+ + @use 'sass:meta';
25
25
  +
26
- -@use '@rdlabo/ionic-theme-ios26/src/styles/default-variables.scss';
27
- -@use '@rdlabo/ionic-theme-ios26/src/styles/ionic-theme-ios26.scss';
28
- -@use '@rdlabo/ionic-theme-ios26/src/styles/ionic-theme-ios26-dark-class.scss';
29
- -@use '@rdlabo/ionic-theme-ios26/src/styles/md-remove-ios-class-effect.scss';
30
- +@supports (overflow-anchor: auto) {
26
+ - @use '@rdlabo/ionic-theme-ios26/src/styles/default-variables.scss';
27
+ - @use '@rdlabo/ionic-theme-ios26/src/styles/ionic-theme-ios26.scss';
28
+ - @use '@rdlabo/ionic-theme-ios26/src/styles/ionic-theme-ios26-dark-class.scss';
29
+ - @use '@rdlabo/ionic-theme-ios26/src/styles/md-remove-ios-class-effect.scss';
30
+ + @supports (overflow-anchor: auto) {
31
31
  + @include meta.load-css('@rdlabo/ionic-theme-ios27/src/styles/default-variables');
32
32
  + @include meta.load-css('@rdlabo/ionic-theme-ios27/src/styles/ionic-theme-ios27');
33
33
  + @include meta.load-css('@rdlabo/ionic-theme-ios27/src/styles/ionic-theme-ios27-dark-class');
34
34
  + @include meta.load-css('@rdlabo/ionic-theme-ios27/src/styles/md-remove-ios-class-effect');
35
- +}
35
+ + }
36
36
  +
37
- +@supports (text-wrap: pretty) and (not (overflow-anchor: auto)) {
37
+ + @supports (text-wrap: pretty) and (not (overflow-anchor: auto)) {
38
38
  + @include meta.load-css('@rdlabo/ionic-theme-ios26/src/styles/default-variables');
39
39
  + @include meta.load-css('@rdlabo/ionic-theme-ios26/src/styles/ionic-theme-ios26');
40
40
  + @include meta.load-css('@rdlabo/ionic-theme-ios26/src/styles/ionic-theme-ios26-dark-class');
41
41
  + @include meta.load-css('@rdlabo/ionic-theme-ios26/src/styles/md-remove-ios-class-effect');
42
- +}
42
+ + }
43
43
  ```
44
44
 
45
45
  Keep Ionic's matching dark palette. For system or always-dark mode, replace both `-dark-class` imports with the matching variant. If you use `md-ion-list-inset`, load the corresponding package's stylesheet inside each branch. Browsers without either feature retain Ionic's default styling.
@@ -49,10 +49,10 @@ Keep Ionic's matching dark palette. For system or always-dark mode, replace both
49
49
  Replace the iOS 26 animation import and gate the iOS 27 animations on the same browser features. Resolve the options before Ionic initializes:
50
50
 
51
51
  ```diff
52
- -import { iosTransitionAnimation, popoverEnterAnimation, popoverLeaveAnimation } from '@rdlabo/ionic-theme-ios26';
53
- +import { iosTransitionAnimation, popoverEnterAnimation, popoverLeaveAnimation } from '@rdlabo/ionic-theme-ios27';
52
+ - import { iosTransitionAnimation, popoverEnterAnimation, popoverLeaveAnimation } from '@rdlabo/ionic-theme-ios26';
53
+ + import { iosTransitionAnimation, popoverEnterAnimation, popoverLeaveAnimation } from '@rdlabo/ionic-theme-ios27';
54
54
  +
55
- +function loadIOSAnimations() {
55
+ + function loadIOSAnimations() {
56
56
  + if (typeof CSS === 'undefined') return {};
57
57
  + if (!CSS.supports('overflow-anchor: auto') && !CSS.supports('text-wrap: pretty')) return {};
58
58
  +
@@ -61,7 +61,7 @@ Replace the iOS 26 animation import and gate the iOS 27 animations on the same b
61
61
  + popoverEnter: popoverEnterAnimation,
62
62
  + popoverLeave: popoverLeaveAnimation,
63
63
  + };
64
- +}
64
+ + }
65
65
 
66
66
  provideIonicAngular({
67
67
  - navAnimation: isPlatform('ios') ? iosTransitionAnimation : undefined,
@@ -83,8 +83,8 @@ Rename theme variables and opt-out classes used by your app. For example:
83
83
  + --ios-theme-content-box-shadow-rgb: 0, 0, 0;
84
84
  }
85
85
 
86
- -<ion-button class="ios26-disabled">Standard Ionic button</ion-button>
87
- +<ion-button class="ios-theme-disabled">Standard Ionic button</ion-button>
86
+ - <ion-button class="ios26-disabled">Standard Ionic button</ion-button>
87
+ + <ion-button class="ios-theme-disabled">Standard Ionic button</ion-button>
88
88
  ```
89
89
 
90
90
  The old names remain as deprecated fallbacks. Check the resulting screens in light and dark modes on the browsers you support.
@@ -94,14 +94,14 @@ The old names remain as deprecated fallbacks. Check the resulting screens in lig
94
94
  To switch entirely to iOS 27, remove the iOS 26 package and replace its stylesheet and animation imports. The stylesheet changes are:
95
95
 
96
96
  ```diff
97
- -@use '@rdlabo/ionic-theme-ios26/src/styles/default-variables.scss';
98
- -@use '@rdlabo/ionic-theme-ios26/src/styles/ionic-theme-ios26.scss';
99
- -@use '@rdlabo/ionic-theme-ios26/src/styles/ionic-theme-ios26-dark-class.scss';
100
- -@use '@rdlabo/ionic-theme-ios26/src/styles/md-remove-ios-class-effect.scss';
101
- +@use '@rdlabo/ionic-theme-ios27/src/styles/default-variables.scss';
102
- +@use '@rdlabo/ionic-theme-ios27/src/styles/ionic-theme-ios27.scss';
103
- +@use '@rdlabo/ionic-theme-ios27/src/styles/ionic-theme-ios27-dark-class.scss';
104
- +@use '@rdlabo/ionic-theme-ios27/src/styles/md-remove-ios-class-effect.scss';
97
+ - @use '@rdlabo/ionic-theme-ios26/src/styles/default-variables.scss';
98
+ - @use '@rdlabo/ionic-theme-ios26/src/styles/ionic-theme-ios26.scss';
99
+ - @use '@rdlabo/ionic-theme-ios26/src/styles/ionic-theme-ios26-dark-class.scss';
100
+ - @use '@rdlabo/ionic-theme-ios26/src/styles/md-remove-ios-class-effect.scss';
101
+ + @use '@rdlabo/ionic-theme-ios27/src/styles/default-variables.scss';
102
+ + @use '@rdlabo/ionic-theme-ios27/src/styles/ionic-theme-ios27.scss';
103
+ + @use '@rdlabo/ionic-theme-ios27/src/styles/ionic-theme-ios27-dark-class.scss';
104
+ + @use '@rdlabo/ionic-theme-ios27/src/styles/md-remove-ios-class-effect.scss';
105
105
  ```
106
106
 
107
107
  Change the animation import from `@rdlabo/ionic-theme-ios26` to `@rdlabo/ionic-theme-ios27`; the existing `isPlatform('ios')` configuration can stay. See the README's [iOS 27-only setup](https://docs.rdlabo.dev/projects/ionic-theme-ios27#use-only-the-ios-27-theme). Unconditional imports apply the new styles on every browser using Ionic iOS mode.
@@ -247,6 +247,17 @@ On iOS, [`Components`](../ios/Sources/IonicNativeUIShellPlugin/Components) owns
247
247
 
248
248
  ## Demo and verification
249
249
 
250
- See the [demo and verification guide](../demo/native-ui-shell.md) for browser tests, Simulator tests and an independent SPM consumer built from the npm package.
250
+ The demo includes a `native-ui-shell` page for exercising fixed controls. From the repository root, build the library and run the browser tests:
251
+
252
+ ```sh
253
+ npm ci
254
+ npm run build
255
+ cd demo
256
+ npm ci
257
+ npx --no-install playwright install chromium
258
+ npx --no-install playwright test e2e/native-ui-shell.spec.ts e2e/native-ui-shell-edge.spec.ts
259
+ ```
260
+
261
+ For native interaction and placement tests, use Xcode 26 or later, XcodeGen and a booted iOS 26+ Simulator. From the repository root, run `sh scripts/verify-native-ui-shell.sh SIMULATOR_UDID`. This also builds an independent Swift Package Manager consumer from the npm package. Run `sh scripts/verify-native-search.sh SIMULATOR_UDID` for searchable-tab integration, or add `edge` to that command for placement, navigation and keyboard edge cases. The scripts print the location of their local test artifacts.
251
262
 
252
263
  Search controllers retain their UIKit-managed transition and are excluded from the ordinary control acquisition crossfade.
@@ -92,6 +92,15 @@ This is an introductory group. Place regular list items in a separate `ion-item-
92
92
 
93
93
  ## Full-width segments
94
94
 
95
+ Add `.segment-style-glass` to give a segment the same glass surface and selected indicator treatment as the tab bar. The class preserves the segment's existing dimensions and text colors, supports scrollable segments, and respects Ionic's public `--background` property.
96
+
97
+ ```html
98
+ <ion-segment class="segment-style-glass" value="available">
99
+ <ion-segment-button value="available">Available</ion-segment-button>
100
+ <ion-segment-button value="away">Away</ion-segment-button>
101
+ </ion-segment>
102
+ ```
103
+
95
104
  For colored segments, use Ionic's `color` property (for example, `color="primary"` or `color="secondary"`). The selected surface uses the palette's base color and the selected label uses its contrast color. The optional moving glass inherits the same surface color; custom Ionic palettes work without additional registration.
96
105
 
97
106
  Add `.segment-expand` when segment buttons should divide the available width evenly. The class also changes the Liquid Glass effect sizing when `registerSegmentEffect` is used.
@@ -7,6 +7,9 @@
7
7
  "main": "./dist/index.js",
8
8
  "module": "./dist/index.js",
9
9
  "types": "./dist/index.d.ts",
10
+ "bin": {
11
+ "rdlabo-copy-structured-list": "./scripts/copy-structured-list.mjs"
12
+ },
10
13
  "exports": {
11
14
  ".": {
12
15
  "types": "./dist/index.d.ts",
@@ -19,6 +22,7 @@
19
22
  "files": [
20
23
  "dist",
21
24
  "src",
25
+ "scripts/copy-structured-list.mjs",
22
26
  "package.json",
23
27
  "README.md",
24
28
  "LICENSE"
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { copyFile, mkdir } from 'node:fs/promises';
4
+ import { dirname, resolve } from 'node:path';
5
+ import process from 'node:process';
6
+ import { URL } from 'node:url';
7
+
8
+ const destination = process.argv[2];
9
+
10
+ if (!destination) {
11
+ throw new Error('Usage: rdlabo-copy-structured-list <destination>');
12
+ }
13
+
14
+ const destinationPath = resolve(destination);
15
+
16
+ await mkdir(dirname(destinationPath), { recursive: true });
17
+ await copyFile(new URL('../src/styles/structured-list.scss', import.meta.url), destinationPath);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rdlabo/ionic-theme-ios27",
3
3
  "private": false,
4
- "version": "1.0.0",
4
+ "version": "1.0.1-beta.pr194.sha00da872ba249",
5
5
  "description": "iOS27 Theme for Ionic Framework",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -28,7 +28,8 @@
28
28
  ],
29
29
  "scripts": {
30
30
  "build": "npm run docgen && npm run build:css && npm run build:ts",
31
- "build:css": "rm -rf dist/css && sass src/styles:dist/css --style=compressed --no-source-map --pkg-importer=node",
31
+ "prebuild:css": "rdlabo-copy-structured-list src/styles/utils/structured-list.scss",
32
+ "build:css": "rm -rf dist/css && sass src/styles:dist/css --style=compressed --no-source-map",
32
33
  "build:ts": "tsc",
33
34
  "docgen": "docgen --project tsconfig.docgen.json --api NativeUIShellHandle --output-readme docs/native-ui-shell.md",
34
35
  "build:demo": "npm run build && cd demo && npm install && npm run build -- --configuration=production",
@@ -55,7 +56,7 @@
55
56
  },
56
57
  "homepage": "https://docs.rdlabo.dev/projects/ionic-theme-ios27",
57
58
  "dependencies": {
58
- "@rdlabo/ionic-theme-utils": "git+https://github.com/rdlabo-dev/ionic-theme-utils.git#66eb2fccca10646ebfccdfb3b6c2f3b4c9b00bf6"
59
+ "@rdlabo/ionic-theme-utils": "git+https://github.com/rdlabo-dev/ionic-theme-utils.git#e82be4389d9209750229f5fee990046b5b1217da"
59
60
  },
60
61
  "bundleDependencies": [
61
62
  "@rdlabo/ionic-theme-utils"
@@ -1,4 +1,4 @@
1
- @use 'pkg:@rdlabo/ionic-theme-utils/styles/structured-list';
1
+ @use '../utils/structured-list';
2
2
 
3
3
  ion-list.ios:not(.ios-theme-disabled, .ios26-disabled) {
4
4
  --ion-border-color: var(--ion-color-step-100, var(--ion-background-color-step-100, #e8e8e8));
@@ -1,4 +1,5 @@
1
1
  @use '../utils/api';
2
+ @use '../utils/glass';
2
3
 
3
4
  ion-segment.ios:not(.ios-theme-disabled, .ios26-disabled) {
4
5
  --border-radius: 16px;
@@ -12,6 +13,24 @@ ion-segment.ios:not(.ios-theme-disabled, .ios26-disabled) {
12
13
  }
13
14
  border-radius: var(--border-radius);
14
15
 
16
+ // Use the tab bar material without changing the segment's layout or size.
17
+ &.segment-style-glass {
18
+ --background: rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.53);
19
+ box-sizing: border-box;
20
+ position: relative;
21
+ z-index: 0;
22
+ background: var(--background);
23
+ backdrop-filter: blur(6px) saturate(180%) brightness(1.05);
24
+ @include glass.light-rim;
25
+
26
+ ion-segment-button {
27
+ --indicator-color: rgba(
28
+ var(--ios-theme-button-color-selected-rgb, var(--ios26-button-color-selected-rgb, var(--ios27-button-color-selected-default-rgb))),
29
+ 0.095
30
+ );
31
+ }
32
+ }
33
+
15
34
  // UIKit uses a larger control in navigation bars, but not in content.
16
35
  &.in-toolbar:not(.segment-expand) {
17
36
  --border-radius: 24px;
@@ -55,6 +55,17 @@ ion-toolbar.ios:not(.ios-theme-disabled, .ios26-disabled).toolbar-searchbar {
55
55
  *[slot='end'] {
56
56
  align-self: center;
57
57
  }
58
+ ion-searchbar.ios:not(.ios-theme-disabled, .ios26-disabled) {
59
+ .searchbar-input-container {
60
+ margin-block: 0;
61
+ margin-inline: 4px;
62
+ }
63
+ &:is(.searchbar-should-show-cancel, :has(.searchbar-cancel-button:active):not(.searchbar-disabled)) {
64
+ .searchbar-input-container {
65
+ margin-inline-end: 11px;
66
+ }
67
+ }
68
+ }
58
69
  &:has(ion-buttons[slot='start']) {
59
70
  ion-buttons[slot='start'] {
60
71
  margin-inline-end: 6px;
@@ -1,4 +1,4 @@
1
- @use 'pkg:@rdlabo/ionic-theme-utils/styles/structured-list';
1
+ @use './utils/structured-list';
2
2
 
3
3
  ion-list.md {
4
4
  @include structured-list.support-text;
@@ -1,4 +1,4 @@
1
- @use 'pkg:@rdlabo/ionic-theme-utils/styles/structured-list';
1
+ @use '../structured-list';
2
2
 
3
3
  @mixin ion-list {
4
4
  ion-list.ios:not(.ios-theme-disabled, .ios26-disabled) {
@@ -1,4 +1,5 @@
1
1
  @use '../api';
2
+ @use '../glass';
2
3
 
3
4
  @mixin ion-segment {
4
5
  ion-segment.ios:not(.ios-theme-disabled, .ios26-disabled) {
@@ -8,6 +9,25 @@
8
9
  .ios27-segment-edge {
9
10
  @include api.glass-lens-dark;
10
11
  }
12
+ &.segment-style-glass {
13
+ --background: color-mix(
14
+ in srgb,
15
+ color-mix(
16
+ in srgb,
17
+ rgb(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb))) 92%,
18
+ rgb(var(--ion-text-color-rgb, 255, 255, 255))
19
+ )
20
+ 40%,
21
+ transparent
22
+ );
23
+ background: var(--background);
24
+ backdrop-filter: blur(6px) saturate(150%) brightness(1.23);
25
+ @include glass.dark-rim;
26
+
27
+ ion-segment-button {
28
+ --indicator-color: rgba(var(--ios-theme-button-color-selected-rgb, var(--ios26-button-color-selected-rgb, 0, 0, 0)), 0.72);
29
+ }
30
+ }
11
31
  }
12
32
  :where(ion-segment.ios:not(.ios-theme-disabled, .ios26-disabled)) {
13
33
  --background: rgba(var(--ion-color-medium-rgb, 152, 154, 162), 0.19);
@@ -0,0 +1,310 @@
1
+ $groups: ion-item-group, ion-reorder-group, ion-accordion-group, ion-radio-group;
2
+
3
+ @function _disabled-suffix($disabled-selector) {
4
+ @if $disabled-selector {
5
+ @return ':not(#{$disabled-selector})';
6
+ }
7
+
8
+ @return '';
9
+ }
10
+
11
+ // Derive neutral list colors from the application's Ionic medium palette.
12
+ @mixin colors($supporting-opacity, $detail-opacity) {
13
+ ion-item {
14
+ --detail-icon-color: rgb(var(--ion-color-medium-rgb));
15
+ --detail-icon-opacity: #{$detail-opacity};
16
+ }
17
+
18
+ &.list-inset {
19
+ ion-list-header ion-label:not(.ion-color) {
20
+ color: rgba(var(--ion-color-medium-rgb), $supporting-opacity);
21
+ }
22
+
23
+ ion-list-header ion-note:not(.ion-color),
24
+ > ion-note:not(.ion-color) {
25
+ --color: rgba(var(--ion-color-medium-rgb), #{$supporting-opacity});
26
+ }
27
+ }
28
+ }
29
+
30
+ @mixin support-text($disabled-selector: null) {
31
+ $d: _disabled-suffix($disabled-selector);
32
+
33
+ ion-item#{$d} {
34
+ &:has(ion-input.input-fill-outline),
35
+ &:has(ion-textarea.textarea-fill-outline),
36
+ &:has(ion-select:is([helpertext]:not([helpertext='']), [errortext]:not([errortext='']))),
37
+ &:has(ion-input .input-bottom > :is(.helper-text:not(:empty), .error-text:not(:empty), .counter:not(:empty))),
38
+ &:has(ion-textarea .textarea-bottom > :is(.helper-text:not(:empty), .error-text:not(:empty), .counter:not(:empty))) {
39
+ --inner-border-width: 0;
40
+ --inner-padding-bottom: 4px;
41
+ }
42
+
43
+ ion-input#{$d} .input-bottom:not(:has(> :is(.helper-text:not(:empty), .error-text:not(:empty), .counter:not(:empty)))),
44
+ ion-textarea#{$d} .textarea-bottom:not(:has(> :is(.helper-text:not(:empty), .error-text:not(:empty), .counter:not(:empty)))) {
45
+ display: none;
46
+ }
47
+ }
48
+ }
49
+
50
+ @mixin layout($outer-note-inset, $group-border-radius, $variant: classic, $disabled-selector: null) {
51
+ $d: _disabled-suffix($disabled-selector);
52
+ $is-ios27: $variant == ios27;
53
+
54
+ background: transparent;
55
+
56
+ ion-list-header#{$d} {
57
+ display: flex;
58
+ align-items: center;
59
+
60
+ ion-label#{$d} {
61
+ @if $is-ios27 {
62
+ font-size: 1rem;
63
+ line-height: 1.29rem;
64
+ font-weight: 600;
65
+ } @else {
66
+ font-size: 0.9rem;
67
+ }
68
+ margin: 8px 4px 4px;
69
+
70
+ &:not(.ion-color) {
71
+ color: var(--ion-color-medium-tint);
72
+ }
73
+ }
74
+
75
+ ion-button#{$d} {
76
+ margin-top: 8px;
77
+ }
78
+
79
+ ion-note#{$d} {
80
+ @if $is-ios27 {
81
+ font-size: 0.76rem;
82
+ line-height: 1.06rem;
83
+ font-weight: 400;
84
+ margin-block: 8px 4px;
85
+ margin-inline: 0 16px;
86
+
87
+ &:not(.ion-color) {
88
+ --color: var(--ion-color-medium-tint);
89
+ }
90
+ } @else {
91
+ font-size: 0.9rem;
92
+ margin-block: 8px 4px;
93
+ margin-inline: 0 16px;
94
+ }
95
+ }
96
+ }
97
+
98
+ @if $is-ios27 {
99
+ ion-item-group.item-group-header#{$d} {
100
+ border-radius: $group-border-radius;
101
+
102
+ > ion-item#{$d} {
103
+ --inner-padding-end: 0;
104
+ --inner-border-width: 0;
105
+
106
+ &::part(native) {
107
+ padding-inline: 0;
108
+ }
109
+ }
110
+
111
+ & > ion-item#{$d} > ion-label#{$d} {
112
+ width: 100%;
113
+ margin: 0;
114
+ text-align: start;
115
+ white-space: normal;
116
+ padding: 16px 20px;
117
+
118
+ /**
119
+ * ion-header.header-collapse-condenseを使って、スクロールによってHeaderを変化させるトリック
120
+ */
121
+ ion-header.header-collapse-condense > ion-toolbar {
122
+ --min-height: 0;
123
+ visibility: hidden;
124
+ }
125
+
126
+ ion-icon#{$d} {
127
+ font-size: 2.82rem;
128
+ border-radius: 20%;
129
+ padding: 6px;
130
+ vertical-align: top;
131
+
132
+ &:not(.ion-color) {
133
+ color: #ffffff;
134
+ }
135
+ }
136
+
137
+ h2 {
138
+ font-size: 1.29rem;
139
+ font-weight: 700;
140
+ line-height: 1.53rem;
141
+ margin: 20px 0 8px;
142
+ }
143
+
144
+ ion-text#{$d} {
145
+ display: block;
146
+ font-size: 1rem;
147
+ line-height: 1.29rem;
148
+
149
+ &:not(.ion-color) {
150
+ color: var(--ion-color-step-500, var(--ion-text-color-step-500, #808080));
151
+ }
152
+ }
153
+ }
154
+ }
155
+ } @else {
156
+ ion-item-group.item-group-header#{$d} {
157
+ & > ion-item#{$d} > ion-label#{$d} {
158
+ width: 100%;
159
+ text-align: center;
160
+ padding: 32px 16px 16px;
161
+ transform: translateX(5px);
162
+
163
+ &:dir(rtl) {
164
+ transform: translateX(-5px);
165
+ }
166
+
167
+ /**
168
+ * ion-header.header-collapse-condenseを使って、スクロールによってHeaderを変化させるトリック
169
+ */
170
+ ion-header.header-collapse-condense > ion-toolbar {
171
+ --min-height: 0;
172
+ visibility: hidden;
173
+ }
174
+
175
+ ion-icon#{$d} {
176
+ font-size: 2.8rem;
177
+ border-radius: 20%;
178
+ padding: 6px;
179
+
180
+ &:not(.ion-color) {
181
+ color: #ffffff;
182
+ }
183
+ }
184
+
185
+ h2 {
186
+ font-size: 1.2rem;
187
+ font-weight: bold;
188
+ margin-top: 8px;
189
+ }
190
+
191
+ ion-text#{$d} {
192
+ font-size: 0.9rem;
193
+ }
194
+ }
195
+ }
196
+ }
197
+
198
+ > :is(#{$groups})#{$d} {
199
+ display: block;
200
+ border-radius: $group-border-radius;
201
+ overflow: hidden;
202
+
203
+ &:has(> .radio-group-top) {
204
+ display: flex;
205
+ flex-direction: column;
206
+ border-radius: 0;
207
+ overflow: visible;
208
+
209
+ > .radio-group-top {
210
+ order: 1;
211
+ font-size: 0.9rem;
212
+ padding-block-start: 8px;
213
+ }
214
+
215
+ > ion-item#{$d}:first-of-type {
216
+ --border-radius: #{$group-border-radius} #{$group-border-radius} 0 0;
217
+ }
218
+
219
+ > ion-item#{$d}:last-of-type {
220
+ --border-radius: 0 0 #{$group-border-radius} #{$group-border-radius};
221
+ }
222
+ }
223
+
224
+ &:not(:first-of-type) {
225
+ margin-top: 16px;
226
+ }
227
+
228
+ ion-item#{$d} {
229
+ &:has(> ion-label:not([slot])):has(> ion-note:not([slot])) {
230
+ &::part(container) {
231
+ flex-direction: column;
232
+ justify-content: center;
233
+ padding-top: 14px;
234
+ padding-bottom: 14px;
235
+ min-height: 64px;
236
+ }
237
+ & > ion-label#{$d},
238
+ & > ion-note#{$d} {
239
+ width: auto;
240
+ align-self: flex-start;
241
+ }
242
+ & > ion-label#{$d} {
243
+ margin: 0;
244
+ font-weight: 500;
245
+ @if $is-ios27 {
246
+ font-size: 1rem;
247
+ line-height: 1.29rem;
248
+ } @else {
249
+ font-size: 1.15rem;
250
+ line-height: 0.9rem;
251
+ }
252
+ }
253
+ & > ion-note#{$d} {
254
+ @if $is-ios27 {
255
+ font-size: 0.88rem;
256
+ line-height: 1.18rem;
257
+ } @else {
258
+ font-size: 0.85rem;
259
+ }
260
+ }
261
+ }
262
+
263
+ ion-text[slot='end']#{$d} {
264
+ padding-inline-start: 8px;
265
+ }
266
+
267
+ &.item-disabled {
268
+ --detail-icon-opacity: 0.1;
269
+ opacity: 1;
270
+
271
+ & > * {
272
+ opacity: 0.4;
273
+ }
274
+ }
275
+
276
+ ion-button[slot='end']#{$d} {
277
+ &.ion-align-self-end {
278
+ transform: translateY(-7px);
279
+ }
280
+ ion-icon[slot='icon-only']#{$d} {
281
+ font-size: 1.2rem;
282
+ transform: translateY(4px);
283
+ }
284
+ }
285
+ }
286
+ }
287
+
288
+ & > ion-note#{$d} {
289
+ margin-block: 8px;
290
+ margin-inline: calc(var(--ion-safe-area-left, 0) + $outer-note-inset) calc(var(--ion-safe-area-right, 0) + $outer-note-inset);
291
+
292
+ &:dir(rtl) {
293
+ margin-inline: calc(var(--ion-safe-area-right, 0) + $outer-note-inset) calc(var(--ion-safe-area-left, 0) + $outer-note-inset);
294
+ }
295
+
296
+ @if $is-ios27 {
297
+ font-size: 0.76rem;
298
+ line-height: 1.06rem;
299
+ font-weight: 400;
300
+ display: block;
301
+ &:not(.ion-color) {
302
+ --color: var(--ion-color-medium-tint);
303
+ }
304
+ } @else {
305
+ --color: var(--ion-color-medium-tint);
306
+ font-size: 0.9rem;
307
+ display: block;
308
+ }
309
+ }
310
+ }