@rdlabo/capacitor-native-ui 1.2.1 → 2.0.0-beta.pr304.sha56daf151ad80
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.
- package/README.md +38 -26
- package/dist/core.d.ts +2 -2
- package/dist/native/activation.d.ts.map +1 -1
- package/dist/native/activation.js +19 -19
- package/dist/native/activation.js.map +1 -1
- package/dist/native/definitions.d.ts +22 -40
- package/dist/native/definitions.d.ts.map +1 -1
- package/dist/native/html.d.ts.map +1 -1
- package/dist/native/html.js +0 -1
- package/dist/native/html.js.map +1 -1
- package/dist/native/index.d.ts +2 -2
- package/dist/native/index.d.ts.map +1 -1
- package/dist/native/index.js +2 -11
- package/dist/native/index.js.map +1 -1
- package/dist/native/overlays/controller.js +1 -1
- package/dist/native/overlays/controller.js.map +1 -1
- package/dist/native/prehide.js +1 -1
- package/dist/native/prehide.js.map +1 -1
- package/dist/native/runtime.d.ts +1 -1
- package/dist/native/runtime.d.ts.map +1 -1
- package/dist/native/runtime.js +8 -20
- package/dist/native/runtime.js.map +1 -1
- package/dist/native/shared/candidate.d.ts +2 -2
- package/dist/native/shared/candidate.d.ts.map +1 -1
- package/dist/native/shared/candidate.js +2 -2
- package/dist/native/shared/candidate.js.map +1 -1
- package/dist/native/shared/control-options.d.ts +6 -0
- package/dist/native/shared/control-options.d.ts.map +1 -0
- package/dist/native/shared/control-options.js +17 -0
- package/dist/native/shared/control-options.js.map +1 -0
- package/dist/native/shared/toolbar-options.d.ts +6 -2
- package/dist/native/shared/toolbar-options.d.ts.map +1 -1
- package/dist/native/shared/toolbar-options.js +7 -15
- package/dist/native/shared/toolbar-options.js.map +1 -1
- package/dist/native/startup.d.ts.map +1 -1
- package/dist/native/startup.js +0 -16
- package/dist/native/startup.js.map +1 -1
- package/dist/native/vertical-bars-web.d.ts.map +1 -1
- package/dist/native/vertical-bars-web.js +3 -2
- package/dist/native/vertical-bars-web.js.map +1 -1
- package/dist/vertical-bars.d.ts +2 -2
- package/docs/configuration.md +94 -72
- package/docs/framework-independent.md +11 -5
- package/docs/migration.md +62 -84
- package/docs/native-ui-extensions.md +31 -28
- package/docs/native-ui.md +34 -50
- package/docs/setup.md +34 -22
- package/docs/vertical-bars.md +59 -65
- package/ios/Sources/NativeUIPlugin/NativeUIPlugin.swift +1 -1
- package/package.json +1 -1
- package/src/core.ts +1 -2
- package/src/native/activation.ts +13 -22
- package/src/native/definitions.ts +40 -90
- package/src/native/html.ts +0 -5
- package/src/native/index.ts +2 -11
- package/src/native/overlays/controller.ts +1 -1
- package/src/native/prehide.ts +1 -1
- package/src/native/runtime.ts +7 -16
- package/src/native/shared/candidate.ts +4 -4
- package/src/native/shared/control-options.ts +20 -0
- package/src/native/shared/toolbar-options.ts +8 -12
- package/src/native/startup.ts +0 -16
- package/src/native/vertical-bars-web.ts +4 -2
- package/src/vertical-bars.ts +2 -1
- package/docs/native-mini-player.md +0 -47
package/docs/migration.md
CHANGED
|
@@ -4,18 +4,14 @@ title: Migration
|
|
|
4
4
|
|
|
5
5
|
# Migration
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Upgrading from 1.2.1
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
This guide is for applications using `@rdlabo/ionic-theme-ios27` **1.2.1**, including its Native UI Shell Preview and standalone Vertical Control Area.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- **Theme only:** update the theme package. Existing theme imports, CSS/Sass paths and animation imports remain valid; no native startup is needed.
|
|
12
|
+
- **Native UI or Vertical Control Area:** install the native package directly, replace imports and startup settings below, then sync Capacitor and rebuild the native app.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
2. Apply the [API and native naming changes](#native-ui-naming-changes), then translate startup settings using [shared shell configuration](#shared-shell-configuration-and-html-adapters), especially partial `controls` objects.
|
|
15
|
-
3. Update [Web layout ownership](#web-layout-ownership) and the [transition adapter](#native-ui-transition-adapter) if used.
|
|
16
|
-
4. Rebuild Web assets, sync Capacitor, and rebuild the native app. A Web-only update cannot replace the native plugin.
|
|
17
|
-
|
|
18
|
-
Native UI remains Preview. App-local SwiftUI / Compose **extensions are experimental**, including their TypeScript definitions, native registration APIs and placement behavior. The `defineNativeUI` and `extensions` names stay unchanged; native registration names change as listed below. Applications using extensions should keep their Web fallback and verify their reader, native renderer and action forwarding together after updates. See the [extension guide](native-ui-extensions.md).
|
|
14
|
+
Native UI remains Preview. Experimental Extensions are documented in the [current extension guide](native-ui-extensions.md); this guide covers the published 1.2.1 controls and setup.
|
|
19
15
|
|
|
20
16
|
## Native UI package separation
|
|
21
17
|
|
|
@@ -23,11 +19,11 @@ For a new native integration, follow [Native UI setup](setup.md) or, if you alre
|
|
|
23
19
|
|
|
24
20
|
The theme and native controls now live in separate packages. Choose dependencies by the behavior your app uses:
|
|
25
21
|
|
|
26
|
-
| App behavior
|
|
27
|
-
|
|
|
28
|
-
| Theme styles, Ionic Web behavior, and theme animations | `@rdlabo/ionic-theme-ios27`
|
|
29
|
-
| Native UI or standalone Vertical Control Area
|
|
30
|
-
| Theme styling together with native controls
|
|
22
|
+
| App behavior | Package to use directly |
|
|
23
|
+
| ------------------------------------------------------ | ----------------------------- |
|
|
24
|
+
| Theme styles, Ionic Web behavior, and theme animations | `@rdlabo/ionic-theme-ios27` |
|
|
25
|
+
| Native UI or standalone Vertical Control Area | `@rdlabo/capacitor-native-ui` |
|
|
26
|
+
| Theme styling together with native controls | Both packages |
|
|
31
27
|
|
|
32
28
|
The theme owns the appearance and behavior of Ionic's Web elements. Native UI owns projecting supported controls into native iOS views and coordinating their lifecycle with Web navigation. Native UI can be used without the iOS 27 theme; installing it does not apply theme styles. Standard controls on Android and browsers retain Web presentation; Android can render [app-local Compose extensions](native-ui-extensions.md#2b-register-compose-content-on-android).
|
|
33
29
|
|
|
@@ -35,7 +31,7 @@ The theme uses the native package's shared transition/search integration interna
|
|
|
35
31
|
|
|
36
32
|
### 1. Update application dependencies
|
|
37
33
|
|
|
38
|
-
|
|
34
|
+
When using both packages, update them together to keep their versions aligned.
|
|
39
35
|
|
|
40
36
|
For theme-only apps, update the theme package. Keep existing theme imports and CSS/Sass paths; no native startup or plugin setup is needed for theme-only use.
|
|
41
37
|
|
|
@@ -51,22 +47,12 @@ npm install @rdlabo/ionic-theme-ios27 @rdlabo/capacitor-native-ui
|
|
|
51
47
|
|
|
52
48
|
For native controls with your existing Web appearance, follow [Native UI only](setup.md). Install the native package directly and keep your existing Web styles. The plugin no longer requires theme variables to select supported controls; Web layout remains the responsibility of your app or theme. Native startup requires Capacitor 8. The Ionic adapter requires Ionic 8.8.1 or later within Ionic 8 or 9; the `/core` entry does not require Ionic.
|
|
53
49
|
|
|
54
|
-
If you used the intermediate `@ionic-theme/capacitor-native-ui` package name during development, remove it and install `@rdlabo/capacitor-native-ui`. Keep the theme dependency if your app uses its styles or APIs.
|
|
55
|
-
|
|
56
|
-
```sh
|
|
57
|
-
npm uninstall @ionic-theme/capacitor-native-ui
|
|
58
|
-
npm install @rdlabo/capacitor-native-ui
|
|
59
|
-
```
|
|
60
|
-
|
|
61
50
|
### 2. Replace native imports
|
|
62
51
|
|
|
63
|
-
| Previous import
|
|
64
|
-
|
|
|
65
|
-
| `@rdlabo/ionic-theme-ios27/native`
|
|
52
|
+
| Previous import | Replacement |
|
|
53
|
+
| ----------------------------------------- | ------------------------------------------- |
|
|
54
|
+
| `@rdlabo/ionic-theme-ios27/native` | `@rdlabo/capacitor-native-ui` |
|
|
66
55
|
| `@rdlabo/ionic-theme-ios27/vertical-bars` | `@rdlabo/capacitor-native-ui/vertical-bars` |
|
|
67
|
-
| `@ionic-theme/capacitor-native-ui` | `@rdlabo/capacitor-native-ui` |
|
|
68
|
-
| `@ionic-theme/capacitor-native-ui/vertical-bars` | `@rdlabo/capacitor-native-ui/vertical-bars` |
|
|
69
|
-
| `@ionic-theme/capacitor-native-ui/integration` | `@rdlabo/capacitor-native-ui/integration` |
|
|
70
56
|
|
|
71
57
|
Update both value and type imports, including lazy imports, test aliases, and bundler configuration. The old theme `/native` and `/vertical-bars` entries have been removed; there are no compatibility aliases.
|
|
72
58
|
|
|
@@ -75,7 +61,7 @@ Update both value and type imports, including lazy imports, test aliases, and bu
|
|
|
75
61
|
+ import { enableNativeUI } from '@rdlabo/capacitor-native-ui';
|
|
76
62
|
```
|
|
77
63
|
|
|
78
|
-
Keep existing control markup; review the [startup option changes](#
|
|
64
|
+
Keep existing control markup; review the [startup option changes](#startup-options), including partial `controls` defaults. The ordinary `@rdlabo/ionic-theme-ios27` entry, theme CSS/Sass paths, and theme animation imports stay unchanged. For custom navigation animations, see the [transition adapter instructions](#native-ui-transition-adapter) below.
|
|
79
65
|
|
|
80
66
|
### 3. Sync the native project
|
|
81
67
|
|
|
@@ -87,40 +73,35 @@ npx cap sync ios
|
|
|
87
73
|
|
|
88
74
|
The Capacitor plugin is now supplied by the native package. Remove manually linked copies of the old theme Swift package so only the new package supplies the plugin. The Swift package/product and CocoaPods pod are now `RdlaboCapacitorNativeUi`; the Swift module is `NativeUIPlugin`. The Capacitor bridge name is now `NativeUI` on JavaScript, iOS and Android. Run Capacitor sync for each native platform you use and rebuild the native app. An OTA/Web-only update cannot migrate an installed binary containing only the old plugin. Use matching JavaScript and native package versions.
|
|
89
75
|
|
|
90
|
-
|
|
76
|
+
Use Capacitor's generated integration for the npm dependency; applications do not need a checkout of this repository or a manually linked Swift package.
|
|
91
77
|
|
|
92
78
|
### 4. Verify the migration
|
|
93
79
|
|
|
94
|
-
- Check
|
|
95
|
-
- Build
|
|
96
|
-
- Build and launch the iOS app after sync. Check native controls, navigation/back gestures, and any app-local Swift extensions you use.
|
|
80
|
+
- Check that native-enabled apps declare `@rdlabo/capacitor-native-ui` directly, then build and confirm no imports of the removed theme entries remain.
|
|
81
|
+
- Build and launch the iOS app after sync. Check native controls, navigation/back gestures, and restored Web controls after teardown.
|
|
97
82
|
- Check browser and Android Web presentation where supported by your app, and confirm the theme still looks correct.
|
|
98
83
|
- Check that previously disabled control kinds remain disabled after expanding partial Preview settings. Test toolbar grouping, individually selected actions and back navigation in both horizontal and vertical layouts.
|
|
99
|
-
- For experimental extensions, check native registration, props, click forwarding and restoration of the original Web UI when projection is unavailable. Rebuild and sync Android as well if the app uses Compose extensions.
|
|
100
84
|
|
|
101
85
|
## Native UI naming changes
|
|
102
86
|
|
|
103
|
-
The split package uses Native UI names throughout. These are breaking renames; the old names are not aliases. The
|
|
87
|
+
The split package uses Native UI names throughout. These are breaking renames; the old names are not aliases. The previous names below refer to the published 1.2.1 Preview.
|
|
104
88
|
|
|
105
|
-
| Previous name
|
|
106
|
-
|
|
|
107
|
-
| `enableNativeUIShell()`
|
|
89
|
+
| Previous name | New name |
|
|
90
|
+
| -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
91
|
+
| `enableNativeUIShell()` | `enableNativeUI()` |
|
|
108
92
|
| `NativeUIShellOptions`, `NativeUIShellHandle`, `NativeUIShellStatus`, `NativeUIShellSuspension`, `NativeUIShellControls`, `NativeUIShellComponent` | `NativeUIOptions`, `NativeUIHandle`, `NativeUIStatus`, `NativeUISuspension`, `NativeUIControls`, `NativeUIComponent` |
|
|
109
|
-
| `IonicNativeUIShell` (plugin export and bridge registration)
|
|
110
|
-
| `withNativeUIShellTransition()`
|
|
111
|
-
| `IonicNativeUIShellPlugin` (Swift module/native class)
|
|
112
|
-
| `
|
|
113
|
-
| `
|
|
114
|
-
|
|
|
115
|
-
| `.ios-theme-shell-disabled` | `.native-ui-disabled` |
|
|
116
|
-
|
|
117
|
-
Replace the `NativeUIShell` part with `NativeUI` in imports from `/integration` as well (for example `suspendNativeUI` and `setNativeUIIntegration`). App-local Swift extensions now use `import NativeUIPlugin`; Kotlin extensions use `import dev.rdlabo.capacitor.nativeui.NativeUI`.
|
|
93
|
+
| `IonicNativeUIShell` (plugin export and bridge registration) | `NativeUI` |
|
|
94
|
+
| `withNativeUIShellTransition()` | `withNativeUITransition()` (still exported by the theme package) |
|
|
95
|
+
| `IonicNativeUIShellPlugin` (Swift module/native class) | `NativeUIPlugin` |
|
|
96
|
+
| `RdlaboIonicThemeIos27` (SPM package/product) | `RdlaboCapacitorNativeUi` |
|
|
97
|
+
| `data-shell="disabled"` | `data-native-ui="disabled"` |
|
|
98
|
+
| `.ios-theme-shell-disabled` | `.native-ui-disabled` |
|
|
118
99
|
|
|
119
100
|
Runtime-owned attributes/events are internal, not configuration: `data-native-ui-shell` is now `data-native-ui-projected`, other `data-native-ui-shell-*` attributes use `data-native-ui-*`, `nativeUIShell*` events use `nativeUI*`, and `.ios-theme-native-ui-shell-*` classes use `.native-ui-*`. Update application tests or diagnostics that inspect them. **Keep explicit source declarations such as `data-native-ui="button"` unchanged**; the projected marker is separate and is managed by the runtime.
|
|
120
101
|
|
|
121
102
|
## Native UI transition adapter
|
|
122
103
|
|
|
123
|
-
The Ionic transition adapter now belongs to `@rdlabo/ionic-theme-ios27`. Replace
|
|
104
|
+
The Ionic transition adapter now belongs to `@rdlabo/ionic-theme-ios27`. Replace the 1.2.1 import of `withNativeUIShellTransition` from `@rdlabo/ionic-theme-ios27/vertical-bars` with `withNativeUITransition` from the theme root. Native-only applications can use `shell.suspend()` and the returned `resume()` directly.
|
|
124
105
|
|
|
125
106
|
Use `withNativeUITransition()` to keep your existing Ionic navigation animation while coordinating Native UI controls.
|
|
126
107
|
|
|
@@ -143,64 +124,61 @@ Use the adapter only for navigation; leave modal and popover animations unchange
|
|
|
143
124
|
|
|
144
125
|
See [Connect your navigation animation](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/packages/theme-ios27/docs/iphone-duo-with-original-theme.md#3-connect-your-navigation-animation) for the setup and supported scope.
|
|
145
126
|
|
|
146
|
-
##
|
|
127
|
+
## Startup options
|
|
147
128
|
|
|
148
|
-
|
|
129
|
+
In 1.2.1, providing `controls` enabled **only fields set to `true`**. In the new API, omitted fields default to `true`, even in a partial object. Expand your old selection when migrating.
|
|
149
130
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
131
|
+
| 1.2.1 | New configuration |
|
|
132
|
+
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
133
|
+
| No `controls` | No `controls`: all supported kinds remain selected by default. |
|
|
134
|
+
| `controls: {}` | `controls: false` to disable default selection, or `ionic: { auto: false }` to disable Ionic discovery altogether. |
|
|
135
|
+
| `controls.toolbar` | Set `controls.buttonGroup`, `controls.button`, and `controls.backButton` to the old toolbar value. |
|
|
136
|
+
| `controls.tabs`, `.segment`, `.fab` | Same names, but explicitly use `false` for previously omitted fields. |
|
|
137
|
+
| `buttonProjection` | `ionic.verticalBars.buttonProjection` |
|
|
138
|
+
| `buttonDefaultFill: null` | `ionic.verticalBars.buttonDefaultFill: 'glass'` (also the default) |
|
|
139
|
+
| `buttonDefaultFill: 'solid'` | `ionic.verticalBars.buttonDefaultFill: 'solid'` |
|
|
140
|
+
| `verticalBarsOnly: true` | `controls: 'verticalOnly'` for default selection in the rail. For a partial selection, use `'verticalOnly'` on each enabled kind and `false` on the rest. |
|
|
141
|
+
| `enabled: false` | Do not start the runtime, or call the active handle's `destroy()`. |
|
|
158
142
|
|
|
159
|
-
|
|
143
|
+
The old startup option names are removed, without aliases. The standalone `enableVerticalControlArea()` entry remains available and defaults `controls` to `'verticalOnly'`; its appearance settings also move under `ionic.verticalBars`. Use only one startup entry per app.
|
|
144
|
+
|
|
145
|
+
### Preserve a tabs-only configuration
|
|
160
146
|
|
|
161
147
|
```diff
|
|
162
148
|
- import { enableNativeUIShell } from '@rdlabo/ionic-theme-ios27/native';
|
|
163
149
|
+ import { enableNativeUI } from '@rdlabo/capacitor-native-ui';
|
|
164
150
|
|
|
165
151
|
- const shell = await enableNativeUIShell({
|
|
166
|
-
+ const shell = await enableNativeUI({
|
|
167
152
|
- controls: { tabs: true },
|
|
168
153
|
- buttonProjection: 'source',
|
|
169
154
|
- buttonDefaultFill: null,
|
|
170
|
-
+
|
|
171
|
-
+
|
|
155
|
+
+ const shell = await enableNativeUI({
|
|
156
|
+
+ controls: {
|
|
157
|
+
+ buttonGroup: false,
|
|
158
|
+
+ button: false,
|
|
159
|
+
+ backButton: false,
|
|
160
|
+
+ tabs: true,
|
|
161
|
+
+ segment: false,
|
|
162
|
+
+ fab: false,
|
|
163
|
+
+ },
|
|
164
|
+
+ ionic: {
|
|
165
|
+
+ verticalBars: { buttonProjection: 'source', buttonDefaultFill: 'glass' },
|
|
166
|
+
+ },
|
|
172
167
|
});
|
|
173
168
|
```
|
|
174
169
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
### Toolbar selection and grouping by layout
|
|
170
|
+
### Select controls by placement
|
|
178
171
|
|
|
179
|
-
`
|
|
172
|
+
All six control fields accept `boolean | 'horizontalOnly' | 'verticalOnly'`. A scalar `controls` value applies to every field. Horizontal and vertical mean ordinary placement and the rail, not device orientation or model.
|
|
180
173
|
|
|
181
174
|
```ts
|
|
182
|
-
const shell = await enableNativeUI({
|
|
183
|
-
horizontal: false,
|
|
184
|
-
vertical: { buttons: false, button: false, backButton: true },
|
|
185
|
-
});
|
|
175
|
+
const shell = await enableNativeUI({ controls: 'verticalOnly' });
|
|
186
176
|
```
|
|
187
177
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
Do not translate `controls.toolbar` or `ionic.auto.buttons` into `vertical.buttons`: those options govern the entire automatic toolbar category, while `horizontal.buttons` / `vertical.buttons` govern **grouping only**. Within each layout, `button` selects ordinary actions and `backButton` selects back navigation independently. All three fields default to `true`; a layout value of `false` sets all three to `false`.
|
|
191
|
-
|
|
192
|
-
If you used the short-lived development settings at the top level, move `{ buttons, button, backButton }` into `vertical: { buttons, button, backButton }`. Those fields were not part of the published 1.2.0/1.2.1 API and are not compatibility aliases. Existing `buttonProjection` / `buttonDefaultFill` are separate appearance settings, mapped above.
|
|
178
|
+
These are selection defaults, not a hard projection scope. Explicit `data-native-ui` sources and local `data-horizontal-bars="true"` / `data-vertical-bars="true"` can opt in even when a matching default is `false`. Remove the explicit marker or use `data-native-ui="disabled"` to leave an individual source on the Web. `ionic.auto: false` disables automatic Ionic discovery, including local layout opt-ins, but leaves explicit source declarations enabled.
|
|
193
179
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
See [all settings and defaults](configuration.md) and [plain HTML setup](framework-independent.md). Standard HTML buttons use the same Swift controls as Ionic; they do not require an application-specific Swift extension.
|
|
180
|
+
`buttonGroup` controls grouping only. It does not select children: `buttonGroup: true, button: false` projects no ordinary action without explicit selection. `backButton` controls back navigation independently, including inside an `ion-buttons` container. See [all settings](configuration.md) for the complete selection matrix and [toolbar grouping](native-ui.md#toolbar-selection-and-grouping) for local overrides.
|
|
197
181
|
|
|
198
182
|
## Web layout ownership
|
|
199
183
|
|
|
200
184
|
Import `setVerticalBarsLayout` and `applyFoldStateClasses` from `@rdlabo/ionic-theme-ios27` for theme CSS. Replace `setVerticalControlAreaPlacement({ edge, nativeEdge, inset })` with `setVerticalBarsLayout({ edge, inset })`. Native UI now reads availability from its own device metrics; `nativeEdge` is ignored by the deprecated compatibility helper. Normal startup, disabled rails and teardown do not remove theme classes or alter reserved Web spacing. An unavailable native rail keeps the application’s Web rail layout; applications wanting a horizontal layout must select it themselves. Native-only applications can continue to use their own layout CSS.
|
|
201
|
-
|
|
202
|
-
## Automatic Ionic controls
|
|
203
|
-
|
|
204
|
-
Use `ionic.auto` for new configuration. It accepts `true` (default), `false`, or `{ buttons, tabs, segment, fab }`. Unlike legacy `controls`, it affects only automatic Ionic projection; explicit `data-native-ui` sources and registered extensions remain enabled. `verticalBars` independently controls rail projection. See [selective projection](configuration.md#select-controls-explicitly-in-a-customized-ionic-app) for an existing Ionic app that opts in individual buttons.
|
|
205
|
-
|
|
206
|
-
The legacy `controls` option is marked `@deprecated` and remains available. When `ionic.auto` is omitted, legacy kind settings are used, but omitted kinds now default to `true`; expand partial Preview configurations as shown above. If both are supplied, `ionic.auto` takes precedence for automatic kinds. Move the legacy `popover` option to `verticalBars.popover`.
|
|
@@ -6,10 +6,10 @@ title: App-local Native UI extensions (experimental)
|
|
|
6
6
|
|
|
7
7
|
> **Experimental:** The extension API, native registration interfaces and behavior may change in future releases. This applies to both SwiftUI and Kotlin/Compose extensions, including `element` and `tab-accessory` placement.
|
|
8
8
|
|
|
9
|
-
> This guide targets the upcoming package split. Until the first native package release, use the [candidate archive installation](../README.md#try-the-unreleased-packages) in place of registry install commands.
|
|
10
|
-
|
|
11
9
|
An extension projects your existing Web UI into a SwiftUI View on iOS or Jetpack Compose content on Android. Keep both definitions in your application: no npm package, separate library, or Capacitor plugin is required. The Web element remains the source of truth and the fallback UI.
|
|
12
10
|
|
|
11
|
+
Extensions use the same [projection model](../README.md#how-projection-works) as built-in controls. Define the DOM data and actions to expose, then provide their native presentation.
|
|
12
|
+
|
|
13
13
|
## Before you start
|
|
14
14
|
|
|
15
15
|
Start with an existing Capacitor 8 app and install the plugin if you have not already:
|
|
@@ -63,7 +63,8 @@ source.querySelector('button')!.addEventListener('click', () => {
|
|
|
63
63
|
source.querySelector('[data-count-label]')!.textContent = `Count: ${count}`;
|
|
64
64
|
});
|
|
65
65
|
```
|
|
66
|
-
|
|
66
|
+
|
|
67
|
+
The shell observes DOM changes and sends the new props to the native content. State rendered into DOM attributes or text is observed automatically. For properties or external state read by the reader that do not mutate the DOM, call `shell.markForCheck()` after changing them.
|
|
67
68
|
|
|
68
69
|
The reader is synchronous and read-only. Return `null` when the source should stay on the Web. Props are a JSON object (finite numbers, strings, booleans, null, arrays and objects), limited to 64K characters. Action names map to the source itself or its descendants; missing, hidden and disabled targets cannot be activated. Up to 30 actions are supported per source.
|
|
69
70
|
|
|
@@ -221,14 +222,14 @@ For source-specific fallback reasons, temporarily enable [`debug: true`](configu
|
|
|
221
222
|
|
|
222
223
|
## Content and placement are independent
|
|
223
224
|
|
|
224
|
-
| `placement`
|
|
225
|
-
|
|
|
225
|
+
| `placement` | Behavior |
|
|
226
|
+
| ---------------------- | ------------------------------------------------------------------------------------- |
|
|
226
227
|
| Omitted or `'element'` | Hosts native content in the source element's Web frame on iOS 26+ or Android API 24+. |
|
|
227
|
-
| `'tab-accessory'`
|
|
228
|
+
| `'tab-accessory'` | Attaches the View to a projected tab bar's system SwiftUI tab accessory on iOS 26.1+. |
|
|
228
229
|
|
|
229
230
|
For `tab-accessory`, place the source inside its owning `ion-tabs`. The shell resolves that tabs element's `ion-tab-bar`; applications do not pass native controller references. Currently only the **Vertical Bars SwiftUI tab host** supports this placement. Ordinary UIKit tab bars, missing native tabs, iOS 26.0, or multiple competing accessories keep the source on the Web. The shell does not approximate a system accessory with a floating overlay. Keep an equivalent Web layout (for example, a fixed footer); the source retains its layout space while hidden.
|
|
230
231
|
|
|
231
|
-
`enableVerticalControlArea(
|
|
232
|
+
Extensions are independent of `controls` and `ionic.auto`, including with `enableVerticalControlArea()`. The application controls their presentation: return `null` from the reader when a source should stay on the Web, then call `markForCheck()` when that condition changes. Accessories still require their supported native tab host.
|
|
232
233
|
|
|
233
234
|
## Read source geometry and presentation state
|
|
234
235
|
|
|
@@ -246,16 +247,16 @@ try NativeUI.register("app.counter") {
|
|
|
246
247
|
|
|
247
248
|
The existing `(props, actions)` closure remains supported. Both forms use the same registration names and duplicate-name checks.
|
|
248
249
|
|
|
249
|
-
| Context property
|
|
250
|
-
|
|
|
251
|
-
| `sourceID`
|
|
252
|
-
| `sourceFrame`
|
|
253
|
-
| `sourceFrameInWebView` | The source rectangle converted to UIKit points in the WebView's local coordinate system; not screen coordinates.
|
|
254
|
-
| `viewportWidth`
|
|
255
|
-
| `pointsPerCSSPixel`
|
|
256
|
-
| `placement`
|
|
257
|
-
| `colorScheme`
|
|
258
|
-
| `layoutDirection`
|
|
250
|
+
| Context property | Meaning |
|
|
251
|
+
| ---------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
252
|
+
| `sourceID` | Opaque source identity for its current lifetime; not the HTML `id`. |
|
|
253
|
+
| `sourceFrame` | DOM `getBoundingClientRect()` in CSS pixels relative to the Web viewport, including `x`, `y`, `width`, and `height`. |
|
|
254
|
+
| `sourceFrameInWebView` | The source rectangle converted to UIKit points in the WebView's local coordinate system; not screen coordinates. |
|
|
255
|
+
| `viewportWidth` | CSS viewport width used for that snapshot's coordinate conversion. |
|
|
256
|
+
| `pointsPerCSSPixel` | UIKit points per CSS pixel; not device pixel density. |
|
|
257
|
+
| `placement` | `.element` or `.tabAccessory`. |
|
|
258
|
+
| `colorScheme` | `.light` or `.dark`, also applied to the SwiftUI environment. |
|
|
259
|
+
| `layoutDirection` | `.leftToRight` or `.rightToLeft`, also applied to the SwiftUI environment. |
|
|
259
260
|
|
|
260
261
|
The closure receives a fresh context when the shell applies an updated snapshot, including source movement, resizing, and appearance changes. Use the current context rather than caching its geometry in `@State`. Updates cross the Web/native bridge; they are not a synchronous DOM measurement from Swift.
|
|
261
262
|
|
|
@@ -272,16 +273,16 @@ Do not apply `sourceFrame.x` or `y` as another SwiftUI offset: the shell already
|
|
|
272
273
|
|
|
273
274
|
## Use the shared projection capabilities
|
|
274
275
|
|
|
275
|
-
| Capability
|
|
276
|
-
|
|
|
277
|
-
| Position and size
|
|
278
|
-
| Dark mode and RTL
|
|
279
|
-
| Reduce Motion and accessibility
|
|
280
|
-
| DOM-backed application state
|
|
281
|
-
| Enabled/visible action targets
|
|
282
|
-
| Invoke the original Web action
|
|
283
|
-
| Temporary Web fallback and teardown | Managed automatically for unsupported content, overlays, navigation suspension, and source removal.
|
|
284
|
-
| Application-controlled suspension
|
|
276
|
+
| Capability | How an extension uses it |
|
|
277
|
+
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
278
|
+
| Position and size | Automatic host placement plus `NativeUIContext`; actual local bounds through `GeometryReader`. |
|
|
279
|
+
| Dark mode and RTL | `context` or SwiftUI `@Environment(\.colorScheme)` and `@Environment(\.layoutDirection)`. |
|
|
280
|
+
| Reduce Motion and accessibility | SwiftUI environment values such as `@Environment(\.accessibilityReduceMotion)` and native accessibility modifiers. Give custom controls accessible names. |
|
|
281
|
+
| DOM-backed application state | Return JSON `props` from `read(element)`; DOM changes trigger synchronization. For changes without a DOM mutation, call `shell.markForCheck()`. |
|
|
282
|
+
| Enabled/visible action targets | `actions.availableNames` or `actions.isAvailable("increment")`; unavailable DOM targets are omitted. |
|
|
283
|
+
| Invoke the original Web action | `try await actions.activate("increment")`; completion and failure follow the contract below. |
|
|
284
|
+
| Temporary Web fallback and teardown | Managed automatically for unsupported content, overlays, navigation suspension, and source removal. |
|
|
285
|
+
| Application-controlled suspension | Use the shell handle's `suspend()`, the returned token's `resume()`, and `destroy()` from JavaScript. |
|
|
285
286
|
|
|
286
287
|
For example, disable a native button when its original action is unavailable:
|
|
287
288
|
|
|
@@ -362,4 +363,6 @@ Element placement requires the source to fit fully inside the viewport and its a
|
|
|
362
363
|
|
|
363
364
|
The [demo reader](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/demo/src/native-ui/counter.ts) and [demo SwiftUI View](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/demo/ios/App/App/NativeUICounter.swift) show both placements using app-local files. Open the Native UI demo page to compare native projection with its Web fallback.
|
|
364
365
|
|
|
365
|
-
|
|
366
|
+
## Example: mini-player
|
|
367
|
+
|
|
368
|
+
The demo mini-player shows the same pattern with track metadata and playback actions: a [DOM reader and Web fallback](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/demo/src/native-ui/mini-player.ts) paired with an [app-local SwiftUI View](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/demo/ios/App/App/NativeMiniPlayer.swift). The Web app owns playback state and modal presentation; native `open` and `toggle` actions activate its original buttons. This is a UI example, not an audio engine. Adapt the files after completing the extension setup above.
|
package/docs/native-ui.md
CHANGED
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
title: Native UI (Preview)
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
For application-specific SwiftUI or Compose content, see [experimental App-local Native UI extensions](native-ui-extensions.md).
|
|
6
|
-
|
|
7
5
|
# Native UI (Preview)
|
|
8
6
|
|
|
9
7
|
Native UI is a **preview**. The earlier Native UI Shell was bundled with theme versions 1.2.0 and 1.2.1; this guide describes the split package and its renamed API. See [migration](migration.md#native-ui-naming-changes). Its API and supported controls may change before stable status. Stable status is planned after the official release of Xcode 27.1.
|
|
10
8
|
|
|
11
9
|
Native UI gives an Ionic app native navigation and action controls around its Web content. The optional Capacitor iOS plugin renders supported fixed Ionic controls with UIKit or SwiftUI and the system's Liquid Glass material. Page content, scrolling, application state and routing remain in Ionic's WebView.
|
|
12
10
|
|
|
13
|
-
Use this page as the supported-control and API reference. For first-time installation and a working example, start with [Ionic setup](setup.md) or [HTML setup](framework-independent.md).
|
|
11
|
+
Read [how projection works](../README.md#how-projection-works) for the shared DOM and native presentation model. Use this page as the supported-control and API reference. For first-time installation and a working example, start with [Ionic setup](setup.md) or [HTML setup](framework-independent.md).
|
|
14
12
|
|
|
15
13
|
## Enable Native UI
|
|
16
14
|
|
|
@@ -47,38 +45,23 @@ Native appearance follows the applied class, system or always-dark theme CSS. Sy
|
|
|
47
45
|
|
|
48
46
|
## Toolbar selection and grouping
|
|
49
47
|
|
|
50
|
-
|
|
48
|
+
Use `controls` to choose selection and grouping by placement:
|
|
51
49
|
|
|
52
50
|
```ts
|
|
53
51
|
const shell = await enableNativeUI({
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
controls: {
|
|
53
|
+
buttonGroup: 'verticalOnly',
|
|
54
|
+
button: true,
|
|
55
|
+
backButton: true,
|
|
56
|
+
},
|
|
56
57
|
});
|
|
57
58
|
```
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
| Value | Meaning |
|
|
62
|
-
| --- | --- |
|
|
63
|
-
| `true` or omitted | All three options default to `true`. |
|
|
64
|
-
| `false` | All three options are `false`; local attributes may still opt in. |
|
|
65
|
-
| Object | Set individual options; omitted fields default to `true`. |
|
|
60
|
+
Here, ordinary toolbar actions project individually and eligible rail actions can group. All six control fields accept `true`, `false`, `'horizontalOnly'`, or `'verticalOnly'`; omitted fields are `true`. For all automatic controls only in the rail, use `controls: 'verticalOnly'`. See [selection defaults](configuration.md#selection-defaults) for the complete table.
|
|
66
61
|
|
|
67
|
-
|
|
62
|
+
`button` selects ordinary actions inside or outside a group, including menu buttons. `buttonGroup` only groups already selected actions. With `buttonGroup: true, button: false`, no ordinary action projects without explicit selection. `backButton` independently selects back navigation, including back buttons inside `ion-buttons`; back buttons never join ordinary groups.
|
|
68
63
|
|
|
69
|
-
|
|
70
|
-
const shell = await enableNativeUI({ horizontal: false, vertical: true });
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
This selects by active layout, not by the Duo model, and does not disable tabs,
|
|
74
|
-
segments or FABs. These settings refine automatic Ionic toolbar projection;
|
|
75
|
-
`ionic.auto` remains its master switch. Explicit `data-native-ui` sources are independent.
|
|
76
|
-
|
|
77
|
-
`button` selects ordinary actions whether grouped
|
|
78
|
-
in the source or standalone; `buttons` only enables grouping of selected actions.
|
|
79
|
-
With `buttons: true, button: false`, no ordinary action projects unless explicitly
|
|
80
|
-
selected. `backButton` independently controls back navigation, including back
|
|
81
|
-
buttons inside `ion-buttons`.
|
|
64
|
+
`ionic.auto` enables or disables automatic Ionic discovery. Explicit `data-native-ui` sources and extensions remain independent of both `controls` and `ionic.auto`.
|
|
82
65
|
|
|
83
66
|
Restart the runtime to change these startup options.
|
|
84
67
|
|
|
@@ -100,7 +83,7 @@ The vertical attribute allows grouping but does not select the text-only childre
|
|
|
100
83
|
add `data-vertical-bars="true"` to each button to select them explicitly.
|
|
101
84
|
|
|
102
85
|
These settings do not remove CSS or change the source layout. If the app removes
|
|
103
|
-
the source group's glass styling, `
|
|
86
|
+
the source group's glass styling, `controls: { buttonGroup: 'verticalOnly' }` also prevents a
|
|
104
87
|
shared native group surface. Existing component-mode, fixed-toolbar,
|
|
105
88
|
fill/color and shell opt-out requirements still apply. A horizontal clear button
|
|
106
89
|
inside `ion-buttons` can project individually when grouping is disabled or the
|
|
@@ -109,8 +92,7 @@ Horizontal local overrides are re-evaluated live; vertical placement retains its
|
|
|
109
92
|
per-page-visit rules. `data-projection="source|system"` remains a separate native
|
|
110
93
|
vertical appearance setting.
|
|
111
94
|
|
|
112
|
-
`enableVerticalControlArea()`
|
|
113
|
-
when horizontal projection is needed, and run only one of the two runtimes.
|
|
95
|
+
The standalone `enableVerticalControlArea()` defaults `controls` to `'verticalOnly'`. Explicit sources and extensions remain independent. Use one startup entry per application.
|
|
114
96
|
|
|
115
97
|
## Supported markup
|
|
116
98
|
|
|
@@ -118,7 +100,7 @@ The table below describes the ordinary Native UI. Vertical Bars uses the separat
|
|
|
118
100
|
|
|
119
101
|
| Ionic component | Supported appearance and placement | Native rendering |
|
|
120
102
|
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
|
121
|
-
| `ion-button` | `fill="default"`, or clear inside an ungrouped `ion-buttons`, in a fixed header/footer toolbar
|
|
103
|
+
| `ion-button` | `fill="default"`, or clear inside an ungrouped `ion-buttons`, in a fixed header/footer toolbar | Glass `UIButton` |
|
|
122
104
|
| `ion-buttons` | Fixed toolbar, two or more direct clear `ion-button` / `ion-menu-button` children sharing the theme glass | One `UIGlassEffect` surface with independent native buttons |
|
|
123
105
|
| `ion-back-button` | Standard icon and color in a fixed header/footer toolbar | Glass `UIButton`, using the resolved Ionic label/icon |
|
|
124
106
|
| `ion-menu-button` | Fixed toolbar, inside the theme glass `ion-buttons` | Glass `UIButton`; original Ionic menu toggle |
|
|
@@ -138,13 +120,15 @@ Only the exact value `disabled` opts out; an empty or unknown value does not opt
|
|
|
138
120
|
</ion-toolbar>
|
|
139
121
|
```
|
|
140
122
|
|
|
141
|
-
|
|
123
|
+
In ordinary placement, an explicit `data-native-ui="disabled"` or `.native-ui-disabled` opt-out inside a shared surface keeps that surface and its children on the Web, including button groups, tab bars, segments and FAB lists. This is different from disabling grouping with `buttonGroup`. Opting out of the search FAB or any part of the search footer disables native search integration; the tab bar can still render natively if it remains eligible.
|
|
142
124
|
|
|
143
125
|
Placement is required even when the appearance is glass. In the ordinary Native UI, buttons, back buttons, menu-button groups and segments need a toolbar directly inside `ion-header` or `ion-footer`, with no `ion-content` ancestor around the control. Buttons directly inside a header/footer, standalone toolbars, and toolbars or headers nested in scrolling content stay on the Web. FABs without `slot="fixed"` also stay on the Web. Moving a projected control to an excluded location restores its Web rendering; moving it back re-evaluates eligibility. When `.ios-theme-vertical-bars` is enabled, a standard `ion-back-button` can instead be projected to the Vertical Control Area from outside a fixed toolbar, including routed content or a persistent app shell. The application chooses where to enable this mode and which Ionic component mode to use; Vertical Bars projection does not require `ios` mode classes. Collapsed headers, opted-out controls and departed pages are excluded. Full-width foreground modals can participate in Vertical Bars as described below; other overlay surfaces keep their own layout.
|
|
144
126
|
|
|
145
127
|
Native tabs accept equal-width items with Ionic's default `layout="icon-top"`. The native bar uses a local compact horizontal and regular vertical size class to preserve the Web's stacked icon/label arrangement on iPad and in landscape. This does not change the app's size class. Label size and weight follow the Web snapshot. Other explicit Ionic layouts (`icon-start`, `icon-end`, `icon-bottom`, `icon-hide`, `label-hide`) and unequal item widths keep the entire tab bar on the Web. Start, center and end placement follow the original `ion-tab-bar`, including RTL. Directional `ion-icon` artwork preserves its rendered RTL flip.
|
|
146
128
|
|
|
147
|
-
Outside Vertical Bars, standalone clear, solid and outline buttons
|
|
129
|
+
Outside Vertical Bars, clear buttons can project individually inside `ion-buttons`; standalone clear, solid and outline buttons remain on the Web. With grouping enabled, two or more eligible clear buttons share one native surface while retaining separate actions. Menu buttons can also join that group; a single menu button uses its parent group as the surface. If grouping is disabled or the group contains mixed fills or unsupported children, eligible actions can still project individually. Back buttons never join the group.
|
|
130
|
+
|
|
131
|
+
Custom button colors, custom back icons/colors, collapsing headers, toolbars inside scrolling content, modal content, scrollable/expanded segments and segment-view integration remain on the Web. Complex slots and unsupported SVG features also fall back to Web. The plugin does not translate arbitrary application CSS into UIKit styles.
|
|
148
132
|
|
|
149
133
|
Native glass samples the Web content actually drawn behind it. Existing toolbar backgrounds and header blur still affect that content. For content to scroll beneath a header, use Ionic's normal translucent-header/fullscreen-content layout; the plugin does not move page content or override an application-owned opaque toolbar background.
|
|
150
134
|
|
|
@@ -204,15 +188,15 @@ Tab switches skip the Web/native crossfade so a retiring UIKit snapshot cannot l
|
|
|
204
188
|
|
|
205
189
|
Standard Ionic overlays suspend ordinary native projection until dismissal. Vertical Bars use a separate policy:
|
|
206
190
|
|
|
207
|
-
| Surface or condition
|
|
208
|
-
|
|
|
209
|
-
| Web toast, ordinary popover or legacy picker overlay
|
|
210
|
-
| Popover opened from a Vertical Bars button, rendered on Web
|
|
211
|
-
| Alert, action sheet or loading
|
|
212
|
-
| Menu
|
|
213
|
-
| Full-width foreground modal
|
|
214
|
-
| Modal that cannot use Vertical Bars
|
|
215
|
-
| Explicit suspension, unavailable native layout, hidden document or unsupported keyboard/viewport geometry | Preserve the existing fallback behavior.
|
|
191
|
+
| Surface or condition | Vertical Bars behavior |
|
|
192
|
+
| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
193
|
+
| Web toast, ordinary popover or legacy picker overlay | Keep the native rail visible, updated and interactive. |
|
|
194
|
+
| Popover opened from a Vertical Bars button, rendered on Web | Return the rail to Web projection until dismissal, including native rejection or preparation failure. |
|
|
195
|
+
| Alert, action sheet or loading | Restore Web rendering so the overlay and its dimming backdrop cover the controls correctly. |
|
|
196
|
+
| Menu | Keep the existing native rail behavior. |
|
|
197
|
+
| Full-width foreground modal | Project the modal's controls instead of the covered page's controls. |
|
|
198
|
+
| Modal that cannot use Vertical Bars | Restore Web rendering. |
|
|
199
|
+
| Explicit suspension, unavailable native layout, hidden document or unsupported keyboard/viewport geometry | Preserve the existing fallback behavior. |
|
|
216
200
|
|
|
217
201
|
Native projection resumes only after every overlay requiring Web rendering closes. The opt-in native Vertical Bars popover described below keeps its own SwiftUI presentation and input handling. Unsupported searchable-tab configurations use the existing Web animation and share this ownership with Web glass gestures. CSS motion of supported containing surfaces also causes temporary Web rendering.
|
|
218
202
|
|
|
@@ -220,7 +204,7 @@ During retirement, the source is restored and allowed to paint before its native
|
|
|
220
204
|
|
|
221
205
|
If a bridge update fails or times out, the runtime stops and restores Web rendering. It does not automatically reconnect. `getStatus()` reports `stopped` and the reason; to retry deliberately, call `destroy()` on that handle and then `enableNativeUI()` again.
|
|
222
206
|
|
|
223
|
-
Failures or timeouts in required startup bridge calls return a Web fallback handle. Optional WebView metrics may fail without disabling native controls.
|
|
207
|
+
Failures or timeouts in required startup bridge calls return a Web fallback handle. Optional WebView metrics may fail without disabling native controls. `destroy()` waits for teardown; repeated calls share its completion. A new activation requested while teardown is running waits for it, including when the application calls `destroy()` without awaiting it. Await these promises when the next application operation depends on cleanup, and handle any rejection.
|
|
224
208
|
|
|
225
209
|
For diagnostics or application teardown:
|
|
226
210
|
|
|
@@ -233,7 +217,7 @@ await shell.destroy(); // restore DOM, remove native controls and release listen
|
|
|
233
217
|
Projection is enabled by calling the startup API. Partial settings override defaults:
|
|
234
218
|
|
|
235
219
|
```ts
|
|
236
|
-
const shell = await enableNativeUI({
|
|
220
|
+
const shell = await enableNativeUI({ controls: { tabs: false } }); // automatic Ionic projection except tabs
|
|
237
221
|
await shell.disableVerticalControlArea(); // retain ordinary native controls
|
|
238
222
|
await shell.enableVerticalControlArea();
|
|
239
223
|
await shell.destroy(); // stop all projection
|
|
@@ -243,13 +227,13 @@ See [all configuration options](configuration.md) for defaults, rail-only usage
|
|
|
243
227
|
|
|
244
228
|
### Popovers anchored to Vertical Bars
|
|
245
229
|
|
|
246
|
-
**Native popover presentation is Vertical Bars only.** It requires an accepted native Vertical Bars `ion-button` anchor; enabling `verticalBars.popover` does not make ordinary toolbar or body popovers native. This feature also works with the standalone Vertical Bars runtime, without enabling the full Native UI.
|
|
230
|
+
**Native popover presentation is Vertical Bars only.** It requires an accepted native Vertical Bars `ion-button` anchor; enabling `ionic.verticalBars.popover` does not make ordinary toolbar or body popovers native. This feature also works with the standalone Vertical Bars runtime, without enabling the full Native UI.
|
|
247
231
|
|
|
248
|
-
Enable `verticalBars.popover` to present popovers from accepted native Vertical Bars `ion-button` controls. Automatic Ionic button projection is enabled by default; when `ionic.auto` is `false`, mark individual anchors with `data-native-ui="button"`:
|
|
232
|
+
Enable `ionic.verticalBars.popover` to present popovers from accepted native Vertical Bars `ion-button` controls. Automatic Ionic button projection is enabled by default; when `ionic.auto` is `false`, mark individual anchors with `data-native-ui="button"`:
|
|
249
233
|
|
|
250
234
|
```ts
|
|
251
235
|
await enableNativeUI({
|
|
252
|
-
verticalBars: { popover: true },
|
|
236
|
+
ionic: { verticalBars: { popover: true } },
|
|
253
237
|
});
|
|
254
238
|
```
|
|
255
239
|
|
|
@@ -284,15 +268,15 @@ The native material and control appearance follow the running iOS version; an iO
|
|
|
284
268
|
|
|
285
269
|
## Support iPhone Duo (preview)
|
|
286
270
|
|
|
287
|
-
iPhone Duo support, including standalone vertical bars without Native UI, is available as a **preview**
|
|
271
|
+
iPhone Duo support, including standalone vertical bars without Native UI, is available as a **preview** alongside Native UI. Its APIs and supported behavior may change.
|
|
288
272
|
|
|
289
|
-
The standalone Vertical Control Area entry point (`@rdlabo/capacitor-native-ui/vertical-bars`) works with application-supplied Web layout. The theme package offers an [optional rail stylesheet](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/packages/theme-ios27/docs/vertical-bars-layout.md), `@rdlabo/ionic-theme-ios27/dist/css/vertical-bars.css`, which can be used without loading the full iOS 27 appearance. Call `enableNativeUI({
|
|
273
|
+
The standalone Vertical Control Area entry point (`@rdlabo/capacitor-native-ui/vertical-bars`) works with application-supplied Web layout. The theme package offers an [optional rail stylesheet](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/packages/theme-ios27/docs/vertical-bars-layout.md), `@rdlabo/ionic-theme-ios27/dist/css/vertical-bars.css`, which can be used without loading the full iOS 27 appearance. Call `enableNativeUI({ controls: 'verticalOnly' })` for this use case; its default selection targets controls placed in the vertical area. Apps already calling `enableNativeUI()` should keep that single runtime rather than starting both. See [iPhone Duo support](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/packages/theme-ios27/docs/iphone-duo.md) for the complete setup, including hinge posture and the split-pane layout for apps that do not use this shell at all.
|
|
290
274
|
|
|
291
275
|
Vertical Bars uses a SwiftUI `TabView` and toolbar in the system rail. Ionic remains the source of labels, icons, selected/disabled state and actions. See [Vertical Bars](vertical-bars.md) for rail layout, native fallback and supported overlays.
|
|
292
276
|
|
|
293
277
|
In Vertical Bars, automatic selection of fixed-toolbar `ion-button` actions requires an `ion-icon` or SVG with `slot="icon-only"`; `data-vertical-bars="true"` can explicitly select other supported buttons. All fills and Ionic colors are eligible; submit buttons follow the same placement rule. Add `.ios-theme-horizontal-only` to a button or its `ion-buttons` group to keep it horizontal. See [Toolbar actions](vertical-bars.md#toolbar-actions) for placement and exclusion rules.
|
|
294
278
|
|
|
295
|
-
**Native button appearance:**
|
|
279
|
+
**Native button appearance:** Native vertical buttons default to `buttonProjection: 'system'`. Use `source` to project Ionic fill and colors, with `data-projection="source|system"` or the equivalent `ios-theme-projection-source` / `ios-theme-projection-system` classes for local exceptions. These settings affect native vertical `ion-button` and `ion-menu-button` actions only. Horizontal controls and Web clones keep their existing behavior. See [Choose button appearance](vertical-bars.md#choose-button-appearance) for priority and fill rules.
|
|
296
280
|
|
|
297
281
|
For standalone setup while keeping your existing theme, see [iPhone Duo with your existing theme](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/packages/theme-ios27/docs/iphone-duo-with-original-theme.md).
|
|
298
282
|
|