@rdlabo/capacitor-native-ui 2.0.0-1 → 2.0.0-3
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 +6 -4
- package/docs/framework-independent.md +23 -9
- package/docs/ionic-vertical-bars.md +63 -44
- package/docs/migration.md +4 -4
- package/docs/native-ui-extensions.md +1 -1
- package/docs/native-ui.md +4 -4
- package/docs/setup.md +4 -2
- package/docs/vertical-bars.md +15 -26
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -34,19 +34,21 @@ Projection changes presentation; it does not translate arbitrary HTML or CSS int
|
|
|
34
34
|
|
|
35
35
|
## Install from npm
|
|
36
36
|
|
|
37
|
-
Install in your
|
|
37
|
+
We use [Capacitor Foldable](https://github.com/erkamyaman/capacitor-foldable), an excellent community plugin by Erkam Yaman, as our standard device-layout integration. It exposes fold state, hinge geometry, bar placement and change events to your application, giving you control over how the layout responds. Foldable handles device reporting; the theme provides Web layout helpers and Native UI projects controls. Install it alongside the package you use, then connect its events in your app.
|
|
38
|
+
|
|
39
|
+
Install Native UI and Foldable together in your Capacitor application:
|
|
38
40
|
|
|
39
41
|
```sh
|
|
40
|
-
npm install @rdlabo/capacitor-native-ui
|
|
42
|
+
npm install @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
41
43
|
```
|
|
42
44
|
|
|
43
45
|
If you also use the iOS 27 theme, install or update both packages together:
|
|
44
46
|
|
|
45
47
|
```sh
|
|
46
|
-
npm install @rdlabo/capacitor-native-ui @rdlabo/ionic-theme-ios27
|
|
48
|
+
npm install @rdlabo/capacitor-native-ui @rdlabo/ionic-theme-ios27 @erkamyaman/capacitor-foldable
|
|
47
49
|
```
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
The theme and Native UI share the same release version; Foldable is versioned independently. Declare Native UI as a direct dependency so Capacitor can discover the plugin. The setup commands install Foldable as a separate application dependency. Installing these packages does not activate native controls; application startup chooses projection and connects device layout.
|
|
50
52
|
|
|
51
53
|
Continue with [Ionic setup](docs/setup.md), [HTML setup](docs/framework-independent.md), or [extensions](docs/native-ui-extensions.md). After configuring startup, build your application's Web assets, run `npx cap sync` and rebuild the native app. No repository checkout or archive download is needed.
|
|
52
54
|
|
|
@@ -6,16 +6,18 @@ Use a Capacitor 8 app with an iOS project, Xcode 26+, and an iOS 26+ device or s
|
|
|
6
6
|
|
|
7
7
|
Start with [how projection works](../README.md#how-projection-works): the HTML element remains the source while native controls or Web proxies provide its presentation.
|
|
8
8
|
|
|
9
|
-
**Want only Vertical Bars?** Follow
|
|
9
|
+
**Want only Vertical Bars?** Follow the [device placement setup](#device-placement-for-vertical-bars), alongside steps 1–4 below. Reuse the step 3 runtime without a fixed placement preference. Remove explicit markers from buttons you want to leave on the Web. You do not need Ionic, `@rdlabo/ionic-theme-ios27`, or `vertical-bars.css`.
|
|
10
10
|
|
|
11
11
|
For Vertical Bars in an app using `ion-tabs`, `ion-toolbar` or other Ionic components with a custom theme, use the [Ionic Vertical Bars setup](ionic-vertical-bars.md#try-it-in-your-existing-ionic-app) instead. The framework (Angular, React or Vue) alone does not determine which adapter to use.
|
|
12
12
|
|
|
13
13
|
## 1. Install the plugin
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
[Capacitor Foldable](https://github.com/erkamyaman/capacitor-foldable) is our standard integration for device state. Its placement and posture APIs let your app control how the layout adapts; installing it is followed by connecting its initial values and change events.
|
|
16
|
+
|
|
17
|
+
Keep your existing Capacitor installation and add Native UI and Foldable together:
|
|
16
18
|
|
|
17
19
|
```sh
|
|
18
|
-
npm install @rdlabo/capacitor-native-ui
|
|
20
|
+
npm install @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
19
21
|
```
|
|
20
22
|
|
|
21
23
|
The `/core` entry requires `@capacitor/core` but no Ionic dependencies. If this is currently a browser-only application, configure its Capacitor 8 iOS project before running native controls.
|
|
@@ -70,15 +72,29 @@ For a custom HTML theme, declare `color-scheme: light` or `color-scheme: dark` i
|
|
|
70
72
|
|
|
71
73
|
## 4. Build and run on iOS
|
|
72
74
|
|
|
73
|
-
Build your Web app, run `npx cap sync ios`, and launch the iOS project from Xcode. With the step 3 configuration, Add renders
|
|
75
|
+
Build your Web app, run `npx cap sync ios`, and launch the iOS project from Xcode. With the step 3 configuration, Add renders at its source position and invokes its original click handler. Back requests the device-reported native rail when available; connect the device placement below to keep Web spacing in sync. In a browser, the same button remains an ordinary Web button. Unmarked HTML remains unchanged.
|
|
74
76
|
|
|
75
77
|
If a button stays on the Web on supported iOS, check that it is visible within the configured root, has an accessible name, and that the direct plugin dependency was synced and the iOS app rebuilt.
|
|
76
78
|
|
|
77
79
|
In an app that also uses Ionic, set `ionic: { auto: false }` to project only explicit sources and registered extensions. See [selective Ionic projection](configuration.md#select-controls-explicitly-in-a-customized-ionic-app).
|
|
78
80
|
|
|
79
|
-
##
|
|
81
|
+
## Device placement for Vertical Bars
|
|
82
|
+
|
|
83
|
+
Foldable is already included in the standard installation in step 1. Connect it to your application layout as follows.
|
|
84
|
+
|
|
85
|
+
Reuse the runtime from step 3 **without `verticalBars.placement`**. Native UI then follows the device-reported edge; a fixed `edge: 'trailing'` would constrain it and can reject a device's leading rail.
|
|
86
|
+
|
|
87
|
+
Follow [Foldable integration](vertical-bars.md#with-application-owned-css-or-without-ionic):
|
|
80
88
|
|
|
81
|
-
|
|
89
|
+
1. Subscribe to `barPlacementChange`, then read `getBarPlacement()` for the initial edge and inset.
|
|
90
|
+
2. Apply the edge and inset to your application's CSS. On a null edge, restore ordinary spacing and call `shell.disableVerticalControlArea()`; when an edge returns, call `shell.enableVerticalControlArea()`. Serialize these changes with layout updates.
|
|
91
|
+
3. At teardown, remove the listener and destroy the runtime owned by this application.
|
|
92
|
+
|
|
93
|
+
Keep the explicit source markers from step 2; they declare the controls and their requested placement. To project only Back, remove `data-native-ui="button"` from Add. `controls` does not disable explicit declarations. Without a Web rail host, unavailable native rail controls stay at their original Web positions. The theme package is not required.
|
|
94
|
+
|
|
95
|
+
## Optional browser rail preview
|
|
96
|
+
|
|
97
|
+
For a browser-only layout preview, temporarily use this fixed Web rail instead of the startup call in step 3 and the device subscription. Do not copy the fixed placement into the standard device setup. Call once after the source root and host are mounted, and call `await shell.destroy()` when their owner is disposed:
|
|
82
98
|
|
|
83
99
|
```ts
|
|
84
100
|
import { enableNativeUI } from '@rdlabo/capacitor-native-ui/core';
|
|
@@ -96,12 +112,10 @@ const shell = await enableNativeUI({
|
|
|
96
112
|
|
|
97
113
|
The plugin uses device-reported rail availability and resolves leading/trailing through the document direction. A placement preference never forces an unsupported system rail. Native rejection restores Web presentation. With `webHost`, explicitly rail-marked HTML controls have Web proxies when native projection is unavailable. Without it, their originals remain visible. The application styles and positions the host and reserves any content spacing. The host must be outside the source root.
|
|
98
114
|
|
|
99
|
-
Explicit markup chooses placement: Back goes to the rail and Add
|
|
115
|
+
Explicit markup chooses placement: Back goes to the preview rail and Add stays at its original position. Disabling rail projection restores original rail controls and removes Web proxies without destroying ordinary native projection. Before building for a device, restore the step 3 runtime and the Foldable subscription above.
|
|
100
116
|
|
|
101
117
|
Currently the HTML adapter supports buttons and back buttons. Arbitrary HTML tabs, segments, searchbars and FAB structures are not translated. Ionic adapters continue to support their existing controls. Custom element extensions work with the same scoped root; the existing `tab-accessory` extension placement still requires an Ionic tab-bar owner.
|
|
102
118
|
|
|
103
|
-
For device-driven spacing and placement, see [Use with Capacitor Foldable](vertical-bars.md#use-with-capacitor-foldable). Read its initial placement and subscribe to changes, applying the edge and inset to your own CSS; the theme package is not required.
|
|
104
|
-
|
|
105
119
|
## Example
|
|
106
120
|
|
|
107
121
|
The [plain HTML example](https://github.com/rdlabo-dev/ionic-theme-ios27/tree/main/examples/native-ui-html) demonstrates Add, routerless Home/Details/Back navigation, optional Web rail projection and cleanup. It uses no Ionic or theme CSS.
|
|
@@ -10,11 +10,11 @@ Read [how projection works](../README.md#how-projection-works) for the relations
|
|
|
10
10
|
|
|
11
11
|
## Choose your setup
|
|
12
12
|
|
|
13
|
-
| Your app | Start here
|
|
14
|
-
| ------------------------------------------------------------------------------ |
|
|
15
|
-
| Ionic components with your own theme, Ionic's default styles, or another theme | [Ionic setup below](#try-it-in-your-existing-ionic-app)
|
|
16
|
-
| No Ionic components (plain HTML, React, Vue, Angular, etc.) | [HTML setup](framework-independent.md), then its [
|
|
17
|
-
| Already using the iOS 27 theme and Native UI | [Connect device placement](
|
|
13
|
+
| Your app | Start here | What you add |
|
|
14
|
+
| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
15
|
+
| Ionic components with your own theme, Ionic's default styles, or another theme | [Ionic setup below](#try-it-in-your-existing-ionic-app) | Foldable device placement, standalone rail CSS and the Ionic Native UI adapter. Keep your existing theme. |
|
|
16
|
+
| No Ionic components (plain HTML, React, Vue, Angular, etc.) | [HTML setup](framework-independent.md), then its [device rail setup](framework-independent.md#device-placement-for-vertical-bars) | `@rdlabo/capacitor-native-ui/core` and Foldable. Your app supplies the rail layout; no theme package. |
|
|
17
|
+
| Already using the iOS 27 theme and Native UI | [Connect device placement](vertical-bars.md#use-with-capacitor-foldable) | Reuse your existing runtime. Do not start another one. |
|
|
18
18
|
|
|
19
19
|
**Without Ionic, follow the HTML guide instead of the steps below.** You do not need `@rdlabo/ionic-theme-ios27`, `vertical-bars.css`, `ion-app`, or Ionic navigation animations. Explicitly marked HTML buttons and back buttons are supported; arbitrary HTML tabs are not automatically converted. A browser preview requires an application-styled `webHost`; native rail presentation also requires supported iOS hardware and software.
|
|
20
20
|
|
|
@@ -26,10 +26,10 @@ iPhone Duo support and Vertical Bars are stable starting with version 2.0.0.
|
|
|
26
26
|
|
|
27
27
|
### 1. Install and load the standalone stylesheet
|
|
28
28
|
|
|
29
|
-
Start with your existing Ionic app (Ionic `>=8.8.1 <10`, Capacitor 8).
|
|
29
|
+
Start with your existing Ionic app (Ionic `>=8.8.1 <10`, Capacitor 8.5 or later). Existing Foldable installations must meet the [placement API requirement](vertical-bars.md#use-with-capacitor-foldable): version 8.3.3 or later within version 8. Install Native UI, the layout stylesheet package and the required device-state plugin together:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
npm install @rdlabo/ionic-theme-ios27 @rdlabo/capacitor-native-ui
|
|
32
|
+
npm install @rdlabo/ionic-theme-ios27 @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
Keep your existing theme imports. Add this to your global Sass file:
|
|
@@ -38,21 +38,11 @@ Keep your existing theme imports. Add this to your global Sass file:
|
|
|
38
38
|
@use '@rdlabo/ionic-theme-ios27/dist/css/vertical-bars.css';
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
The full iOS 27 theme stylesheets are not required.
|
|
41
|
+
The full iOS 27 theme stylesheets are not required. Keep this stylesheet instead of Foldable's `ionic-tabs.css`; loading both would reposition the same tabs.
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
We adopt [Capacitor Foldable](https://github.com/erkamyaman/capacitor-foldable) as the standard device integration because it exposes placement, posture and their changes while leaving layout decisions to your app. Pass its logical rail edge and measured inset to the theme's layout helper. Native UI checks native rail availability independently.
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
```html
|
|
48
|
-
<ion-app class="ios-theme-vertical-bars">
|
|
49
|
-
<!-- Keep your existing pages, tabs, and toolbar controls here. -->
|
|
50
|
-
</ion-app>
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
The preview reserves `80px` on the physical right. To preview the left side, also add `ios-theme-vertical-bars-left`.
|
|
54
|
-
|
|
55
|
-
### 3. Connect your navigation animation
|
|
45
|
+
### 2. Connect your navigation animation
|
|
56
46
|
|
|
57
47
|
Configure `navAnimation` before Ionic initializes. Starting the rail runtime does not register this option. The adapter waits for native control retirement and coordinates swipe progress and cancellation while keeping your existing animation.
|
|
58
48
|
|
|
@@ -106,27 +96,60 @@ The adapter returns the original `Animation`, preserving its effects, duration,
|
|
|
106
96
|
|
|
107
97
|
The adapter keeps the builder's animation targets, including any horizontal back-button effect. If you need the iOS 27 transition with that effect excluded in vertical layouts, use `iosTransitionAnimation` from `@rdlabo/ionic-theme-ios27` as your `navAnimation` instead. It already includes the adapter, so no wrapper is needed.
|
|
108
98
|
|
|
109
|
-
###
|
|
99
|
+
### 3. Connect device placement and start the controls
|
|
110
100
|
|
|
111
|
-
|
|
101
|
+
After `ion-app` is mounted, subscribe to placement changes, read the initial placement, and start one runtime. Keep your existing `ion-app` markup; the helper applies or removes the layout classes from device state:
|
|
112
102
|
|
|
113
103
|
```ts
|
|
104
|
+
import { Foldable, type BarPlacement } from '@erkamyaman/capacitor-foldable';
|
|
105
|
+
import { setVerticalBarsLayout } from '@rdlabo/ionic-theme-ios27';
|
|
114
106
|
import { enableNativeUI } from '@rdlabo/capacitor-native-ui';
|
|
115
107
|
|
|
108
|
+
const applyPlacement = ({ verticalBarEdge, inset }: BarPlacement) => setVerticalBarsLayout({ edge: verticalBarEdge, inset });
|
|
109
|
+
const listener = await Foldable.addListener('barPlacementChange', applyPlacement);
|
|
110
|
+
applyPlacement(await Foldable.getBarPlacement());
|
|
116
111
|
const rail = await enableNativeUI({ controls: 'verticalOnly' });
|
|
117
112
|
```
|
|
118
113
|
|
|
119
|
-
|
|
114
|
+
| Device placement | Web layout |
|
|
115
|
+
| -------------------------------------- | -------------------------------------------------------------------------- |
|
|
116
|
+
| `leading` or `trailing` | Reserves the reported inset at that logical edge. The helper resolves RTL. |
|
|
117
|
+
| `null`, including the browser fallback | Restores the ordinary layout; no side rail is forced. |
|
|
118
|
+
|
|
119
|
+
When the application owner is disposed, remove its listener and destroy the runtime it owns:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
await listener.remove();
|
|
123
|
+
await rail.destroy();
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
If Native UI is already active, keep that runtime and add only the placement subscription. Do not start a second runtime. For shared configuration and application-owned CSS, see [Foldable integration](vertical-bars.md#use-with-capacitor-foldable).
|
|
127
|
+
|
|
128
|
+
### Initial layout timing
|
|
129
|
+
|
|
130
|
+
Run step 3 from your application root as soon as `ion-app` is mounted; do not wait for a routed page's data requests. `setVerticalBarsLayout()` needs that element to exist and does not save placement supplied before mounting. Keep startup and cleanup with the same application owner, as described in [the framework lifecycle examples](setup.md#place-startup-in-your-frameworks-app-root).
|
|
131
|
+
|
|
132
|
+
Native startup, device placement and control rendering are asynchronous. Resolving `enableNativeUI()` gives you the runtime handle, not a guarantee that controls have already been projected. Starting promptly avoids application-added waiting, but the initial Web layout may still be visible before native projection.
|
|
120
133
|
|
|
121
|
-
|
|
134
|
+
### 4. Build, sync and run on iPhone Duo
|
|
122
135
|
|
|
123
|
-
|
|
136
|
+
Build your application's Web assets, then sync the native project:
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
npx cap sync ios
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Build with Xcode 27.1 or newer and run on iPhone Duo with iOS 27.1 or later. Keep your existing SPM or CocoaPods integration; see [Native UI setup](setup.md#4-build-sync-and-run).
|
|
143
|
+
|
|
144
|
+
**What you should see when the device reports a rail:** your existing tab bar and eligible fixed-toolbar actions move to the side. Content keeps its theme and reserves the measured inset. Supported iOS rails use SwiftUI; unavailable native presentation retains the Web rail. Devices reporting a null edge keep their ordinary layout. Use the [optional browser preview](#optional-browser-preview) to simulate a rail without a device report.
|
|
145
|
+
|
|
146
|
+
Keep your existing click handlers, routing and form associations. By default, actions need an `ion-icon` or SVG with `slot="icon-only"` in a fixed toolbar. All fills (`default`, `clear`, `solid`, `outline`) follow this rule, including submit buttons. Other actions remain horizontal. Use `.ios-theme-horizontal-only` on an `ion-buttons` group or individual `ion-button` to keep an action horizontal.
|
|
124
147
|
|
|
125
148
|
### Optional: choose native button appearance
|
|
126
149
|
|
|
127
150
|
See [Choose button appearance](vertical-bars.md#choose-button-appearance) for appearance settings and local overrides.
|
|
128
151
|
|
|
129
|
-
The default is `system`: SwiftUI styles vertical buttons and tints their icons. If your existing theme should supply their fill and colors, replace the
|
|
152
|
+
The default is `system`: SwiftUI styles vertical buttons and tints their icons. If your existing theme should supply their fill and colors, replace only the `enableNativeUI` call in step 3 with the following; keep the Foldable subscription:
|
|
130
153
|
|
|
131
154
|
```ts
|
|
132
155
|
const rail = await enableNativeUI({
|
|
@@ -137,36 +160,32 @@ const rail = await enableNativeUI({
|
|
|
137
160
|
|
|
138
161
|
The `solid` default suits ordinary Ionic buttons. Buttons inside `ion-buttons` still default to clear; set `fill="solid"` explicitly to project their background. For one-off exceptions, use the [local projection settings](vertical-bars.md#override-individual-buttons-or-groups). These settings affect native vertical buttons only; Web clones keep their existing appearance.
|
|
139
162
|
|
|
140
|
-
### If the
|
|
163
|
+
### If the rail does not appear
|
|
141
164
|
|
|
142
|
-
| What you see | What to check
|
|
143
|
-
| ------------------------------------------- |
|
|
144
|
-
|
|
|
145
|
-
|
|
|
146
|
-
|
|
|
165
|
+
| What you see | What to check |
|
|
166
|
+
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
167
|
+
| Ordinary layout | Check Foldable's reported edge. A null edge intentionally keeps ordinary layout. |
|
|
168
|
+
| Reported edge but no side spacing | Load `vertical-bars.css` and apply the initial placement and `barPlacementChange` events after `ion-app` mounts. |
|
|
169
|
+
| Space appears, but controls stay horizontal | Start the runtime once. Use existing tabs or supported `slot="icon-only"` actions in a fixed header/footer toolbar. |
|
|
170
|
+
| One action stays horizontal | Check its icon slot, fixed placement and exclusions. See [control requirements](vertical-bars.md#toolbar-actions). |
|
|
147
171
|
|
|
148
|
-
##
|
|
172
|
+
## Optional browser preview
|
|
149
173
|
|
|
150
|
-
|
|
174
|
+
For local layout testing without a device report, temporarily omit the Foldable subscription from step 3 and apply a simulated placement after `ion-app` mounts:
|
|
151
175
|
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
npx cap sync ios
|
|
176
|
+
```ts
|
|
177
|
+
setVerticalBarsLayout({ edge: 'trailing', inset: 80 });
|
|
155
178
|
```
|
|
156
179
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
Replace the browser-only startup with the [device placement setup](../../theme-ios27/docs/iphone-duo.md#project-controls-into-the-rail). That setup sends initial values and `barPlacementChange` events to `setVerticalBarsLayout({ edge: verticalBarEdge, inset })`, with subscriptions and cleanup kept in your application.
|
|
160
|
-
|
|
161
|
-
Pass Foldable's reported logical edge and measured inset to `setVerticalBarsLayout`. The helper resolves RTL. A null edge restores the ordinary Web layout; Native UI detects native rail availability independently.
|
|
180
|
+
Keep the same stylesheet and single Native UI runtime. Use `leading` to preview the other logical edge, or `null` to restore ordinary layout. The helper manages `ios-theme-vertical-bars` and its physical-left variant; manual classes are not part of device setup. See [layout classes](../../theme-ios27/docs/vertical-bars-layout.md#reserve-the-vertical-rail) for CSS-only previews.
|
|
162
181
|
|
|
163
|
-
|
|
182
|
+
Web rail tabs display icons and reveal labels while pressing and dragging. Browser previews verify Web layout and actions, not native SwiftUI appearance. Restore the Foldable subscription for the device build.
|
|
164
183
|
|
|
165
184
|
## Use hinge posture without projecting controls
|
|
166
185
|
|
|
167
186
|
If your existing theme needs only a posture-driven split pane or a layout switch, do not start a projection runtime or add `.ios-theme-vertical-bars`. Pass `Foldable.getFoldState()` results and `foldStateChange` events to `applyFoldStateClasses(root, fold)`, removing the listener when finished. There is no separate start/stop monitoring call.
|
|
168
187
|
|
|
169
|
-
See [Read the device layout](../../theme-ios27/docs/
|
|
188
|
+
See [Read the device layout](../../theme-ios27/docs/vertical-bars-layout.md#read-the-device-layout) for the subscription example, null values, and monitoring lifetime. See [Adapt the split pane](../../theme-ios27/docs/vertical-bars-layout.md#adapt-the-split-pane) for the opt-in width rules and half-open state.
|
|
170
189
|
|
|
171
190
|
## Shared layout rules and API
|
|
172
191
|
|
package/docs/migration.md
CHANGED
|
@@ -31,18 +31,18 @@ The theme uses the native package's shared transition/search integration interna
|
|
|
31
31
|
|
|
32
32
|
### 1. Update application dependencies
|
|
33
33
|
|
|
34
|
-
When using
|
|
34
|
+
When using the theme and Native UI together, update them to the same version. The commands below also install [Capacitor Foldable](https://github.com/erkamyaman/capacitor-foldable) as a separate application dependency for placement and posture reporting. Foldable has its own release versions.
|
|
35
35
|
|
|
36
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.
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
|
-
npm install @rdlabo/ionic-theme-ios27
|
|
39
|
+
npm install @rdlabo/ionic-theme-ios27 @erkamyaman/capacitor-foldable
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
For apps using both the theme and native controls, install both as direct application dependencies:
|
|
43
43
|
|
|
44
44
|
```sh
|
|
45
|
-
npm install @rdlabo/ionic-theme-ios27 @rdlabo/capacitor-native-ui
|
|
45
|
+
npm install @rdlabo/ionic-theme-ios27 @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
46
46
|
```
|
|
47
47
|
|
|
48
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.
|
|
@@ -122,7 +122,7 @@ Merge this option into your existing Ionic configuration before initialization.
|
|
|
122
122
|
|
|
123
123
|
Use the adapter only for navigation; leave modal and popover animations unchanged. Your builder must create a fresh `Animation` for each navigation because Ionic destroys it afterward. Keep lifecycle events for control registration and transitions without animation. If the custom builder animates a horizontal back button separately, exclude that effect while `.ios-theme-vertical-bars` is active.
|
|
124
124
|
|
|
125
|
-
See [Connect your navigation animation](ionic-vertical-bars.md#
|
|
125
|
+
See [Connect your navigation animation](ionic-vertical-bars.md#2-connect-your-navigation-animation) for the setup and supported scope.
|
|
126
126
|
|
|
127
127
|
## Startup options
|
|
128
128
|
|
|
@@ -15,7 +15,7 @@ Extensions use the same [projection model](../README.md#how-projection-works) as
|
|
|
15
15
|
Start with an existing Capacitor 8 app and install the plugin if you have not already:
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
npm install @rdlabo/capacitor-native-ui
|
|
18
|
+
npm install @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Choose the native platform you want to support:
|
package/docs/native-ui.md
CHANGED
|
@@ -17,7 +17,7 @@ Already using the iOS theme? Follow [Add Native UI to your theme](https://github
|
|
|
17
17
|
Install the native package as a direct application dependency so Capacitor can discover it:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
npm install @rdlabo/capacitor-native-ui
|
|
20
|
+
npm install @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
21
21
|
npx cap sync ios
|
|
22
22
|
```
|
|
23
23
|
|
|
@@ -301,7 +301,7 @@ Custom host animation or transition declarations on the FAB, list or button keep
|
|
|
301
301
|
|
|
302
302
|
## Transitions and recovery
|
|
303
303
|
|
|
304
|
-
The built-in `iosTransitionAnimation` waits for native retirement before starting the Web animation. Interactive progress and completion/cancellation are queued while that retirement is in progress. Stationary shared tabs are retained. First render and transitions without an animation builder are covered by the startup runtime and Ionic lifecycle events. Default Ionic and custom navigation builders can use the same integration through `withNativeUITransition()`, exported by `@rdlabo/ionic-theme-ios27`. See [Connect your navigation animation](ionic-vertical-bars.md#
|
|
304
|
+
The built-in `iosTransitionAnimation` waits for native retirement before starting the Web animation. Interactive progress and completion/cancellation are queued while that retirement is in progress. Stationary shared tabs are retained. First render and transitions without an animation builder are covered by the startup runtime and Ionic lifecycle events. Default Ionic and custom navigation builders can use the same integration through `withNativeUITransition()`, exported by `@rdlabo/ionic-theme-ios27`. See [Connect your navigation animation](ionic-vertical-bars.md#2-connect-your-navigation-animation) for the setup.
|
|
305
305
|
|
|
306
306
|
Ordinary native/Web handoffs share a 180ms opacity crossfade, including Vertical Bars in both directions. Outgoing visuals cannot receive input or accessibility focus. Reduce Motion and modal presentation use immediate handoffs; search controllers keep their UIKit-managed transition.
|
|
307
307
|
|
|
@@ -323,7 +323,7 @@ Native projection resumes only after every overlay requiring Web rendering close
|
|
|
323
323
|
|
|
324
324
|
During retirement, the source is restored and allowed to paint before its native cover is removed. During acquisition, the source is hidden only after a successful, current native response. Delayed responses are revalidated per control: existing eligible controls retain their native cover while content updates catch up. Only removed or ineligible sources return to Web; newly acquired sources require an exact acknowledgement. Ordinary page mutations never call the global clear operation. UIKit tab instances and items are retained, and equal frames/selections are not reapplied. Duplicate/stale activations are discarded. WebKit and UIKit still render separately: the implementation avoids an intentional blank frame, but does not provide an OS-level atomic compositing guarantee. Validate custom transitions and overlays on the app's supported simulators before rollout; unknown overlay systems are outside the automatic integration contract.
|
|
325
325
|
|
|
326
|
-
If a bridge update fails or times out,
|
|
326
|
+
If a bridge update fails or times out, native projection stops and Web rendering is restored. It does not automatically reconnect. `getStatus().reason` reports the failure; while the Web fallback remains active, the public handle reports `state: 'web'`, not `stopped`. To retry deliberately, call `destroy()` on that handle and then `enableNativeUI()` again.
|
|
327
327
|
|
|
328
328
|
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.
|
|
329
329
|
|
|
@@ -405,7 +405,7 @@ The native material and control appearance follow the running iOS version; an iO
|
|
|
405
405
|
|
|
406
406
|
iPhone Duo support, including standalone Vertical Bars, is stable starting with version 2.0.0.
|
|
407
407
|
|
|
408
|
-
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 [
|
|
408
|
+
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 [Device layout and split panes](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/packages/theme-ios27/docs/vertical-bars-layout.md) for the complete setup, including hinge posture and the split-pane layout for apps that do not use this shell at all.
|
|
409
409
|
|
|
410
410
|
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.
|
|
411
411
|
|
package/docs/setup.md
CHANGED
|
@@ -21,10 +21,12 @@ If the app does not yet use Capacitor, create and configure its Capacitor iOS pr
|
|
|
21
21
|
|
|
22
22
|
## 1. Install the plugin
|
|
23
23
|
|
|
24
|
+
[Capacitor Foldable](https://github.com/erkamyaman/capacitor-foldable) is our standard integration for device state. Its placement and posture APIs let your app control how the layout adapts; installing it is followed by connecting its initial values and change events.
|
|
25
|
+
|
|
24
26
|
Keep your Capacitor packages on version 8. Add these direct application dependencies:
|
|
25
27
|
|
|
26
28
|
```sh
|
|
27
|
-
npm install @rdlabo/capacitor-native-ui
|
|
29
|
+
npm install @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
28
30
|
```
|
|
29
31
|
|
|
30
32
|
The Ionic adapter uses `@ionic/core`, which your Ionic app already supplies. Do not remove your existing Web styles: they style page content and fallback controls.
|
|
@@ -140,7 +142,7 @@ These hooks manage the app's lifetime, not individual page transitions. Configur
|
|
|
140
142
|
For optional Ionic animation coordination, install `@rdlabo/ionic-theme-ios27` and update Native UI together so their versions match. Configure navigation before Ionic initializes. Its adapter can retain Ionic's default transitions without loading theme CSS:
|
|
141
143
|
|
|
142
144
|
```sh
|
|
143
|
-
npm install @rdlabo/ionic-theme-ios27 @rdlabo/capacitor-native-ui
|
|
145
|
+
npm install @rdlabo/ionic-theme-ios27 @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
144
146
|
```
|
|
145
147
|
|
|
146
148
|
```ts
|
package/docs/vertical-bars.md
CHANGED
|
@@ -9,10 +9,10 @@ Vertical Bars moves eligible Ionic controls or explicitly marked HTML buttons in
|
|
|
9
9
|
Choose your setup before using this reference:
|
|
10
10
|
|
|
11
11
|
- **Ionic with a custom or default theme:** [Ionic rail setup](ionic-vertical-bars.md#try-it-in-your-existing-ionic-app).
|
|
12
|
-
- **No Ionic:** [HTML setup](framework-independent.md) and its [
|
|
13
|
-
- **Existing iOS 27 theme and Native UI:** [Connect device placement](
|
|
12
|
+
- **No Ionic:** [HTML setup](framework-independent.md) and its [device rail setup](framework-independent.md#device-placement-for-vertical-bars). Use `/core` and your own layout; the Ionic setup below does not apply.
|
|
13
|
+
- **Existing iOS 27 theme and Native UI:** [Connect device placement](#use-with-capacitor-foldable) using your existing runtime.
|
|
14
14
|
|
|
15
|
-
This page covers device-plugin integration, control eligibility, native appearance and runtime options. For posture-driven Ionic split panes, see [
|
|
15
|
+
This page covers device-plugin integration, control eligibility, native appearance and runtime options. For posture-driven Ionic split panes, see [Device layout and split panes](../../theme-ios27/docs/vertical-bars-layout.md).
|
|
16
16
|
|
|
17
17
|
Vertical Bars and iPhone Duo support are stable starting with version 2.0.0.
|
|
18
18
|
|
|
@@ -20,23 +20,15 @@ See [shared configuration](configuration.md) for all defaults and live `rail.ena
|
|
|
20
20
|
|
|
21
21
|
## Enable Vertical Bars
|
|
22
22
|
|
|
23
|
-
Install the
|
|
23
|
+
Install Native UI and the required Foldable device-state plugin as direct application dependencies:
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
|
-
npm install @rdlabo/capacitor-native-ui
|
|
26
|
+
npm install @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
For
|
|
29
|
+
For Ionic, follow the [standard setup](ionic-vertical-bars.md): load your rail CSS, configure navigation, then connect Foldable's initial placement and `barPlacementChange` events before starting one runtime. The [integration below](#use-with-capacitor-foldable) also covers existing runtimes and application-owned CSS. Build your Web assets, run `npx cap sync ios`, and rebuild the native app.
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
```ts
|
|
34
|
-
import { enableNativeUI } from '@rdlabo/capacitor-native-ui';
|
|
35
|
-
|
|
36
|
-
const rail = await enableNativeUI({ controls: 'verticalOnly' });
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Configure your Web rail layout and [apply device placement](#use-with-capacitor-foldable) for an iPhone Duo. The application owns placement and cleanup: call `await rail.destroy()` when its owner is disposed. If you already use `enableNativeUI()`, keep that runtime; it includes Vertical Bars. Do not start both.
|
|
31
|
+
A runtime alone does not reserve Web space. Keep the device subscription for the standard setup; manual placement belongs to the [optional browser preview](ionic-vertical-bars.md#optional-browser-preview). If Native UI is already active, reuse it rather than starting another runtime.
|
|
40
32
|
|
|
41
33
|
The `/vertical-bars` entry point requires `@capacitor/core`, including in browser builds. Using only the theme’s rail CSS needs no native runtime. For native setup and navigation transitions, follow the [existing-theme guide](ionic-vertical-bars.md).
|
|
42
34
|
|
|
@@ -50,7 +42,9 @@ The [theme's optional rail stylesheet](https://github.com/rdlabo-dev/ionic-theme
|
|
|
50
42
|
|
|
51
43
|
## Use with Capacitor Foldable
|
|
52
44
|
|
|
53
|
-
|
|
45
|
+
[`@erkamyaman/capacitor-foldable`](https://github.com/erkamyaman/capacitor-foldable) is required in the standard Vertical Bars setup. Install it with Native UI as shown above, and connect its device placement to your Web layout. Native UI does not subscribe to Foldable automatically.
|
|
46
|
+
|
|
47
|
+
The placement examples require Foldable **8.3.3 or later within version 8**, which includes `BarPlacement.inset`. If your app already uses an older version, update it with `npm install @erkamyaman/capacitor-foldable@^8.3.3`, then sync and rebuild the native app.
|
|
54
48
|
|
|
55
49
|
| Owner | Responsibility |
|
|
56
50
|
| -------------------- | ------------------------------------------------------------------------------------------- |
|
|
@@ -58,24 +52,19 @@ Use [`@erkamyaman/capacitor-foldable`](https://github.com/erkamyaman/capacitor-f
|
|
|
58
52
|
| Application or theme | Reserve Web space and choose the layout using the reported logical edge and measured inset. |
|
|
59
53
|
| Native UI | Check native rail availability independently and project eligible source controls. |
|
|
60
54
|
|
|
61
|
-
```sh
|
|
62
|
-
npm install @erkamyaman/capacitor-foldable
|
|
63
|
-
npx cap sync ios
|
|
64
|
-
```
|
|
65
|
-
|
|
66
55
|
### With the theme's Ionic rail layout
|
|
67
56
|
|
|
68
|
-
After loading [the rail stylesheet](../../theme-ios27/docs/vertical-bars-layout.md) and mounting `ion-app`, start the runtime once
|
|
57
|
+
After loading [the rail stylesheet](../../theme-ios27/docs/vertical-bars-layout.md) and mounting `ion-app`, connect device placement and start the runtime once:
|
|
69
58
|
|
|
70
59
|
```ts
|
|
71
60
|
import { Foldable, type BarPlacement } from '@erkamyaman/capacitor-foldable';
|
|
72
61
|
import { setVerticalBarsLayout } from '@rdlabo/ionic-theme-ios27';
|
|
73
62
|
import { enableNativeUI } from '@rdlabo/capacitor-native-ui';
|
|
74
63
|
|
|
75
|
-
const rail = await enableNativeUI({ controls: 'verticalOnly' });
|
|
76
64
|
const applyPlacement = ({ verticalBarEdge, inset }: BarPlacement) => setVerticalBarsLayout({ edge: verticalBarEdge, inset });
|
|
77
65
|
const listener = await Foldable.addListener('barPlacementChange', applyPlacement);
|
|
78
66
|
applyPlacement(await Foldable.getBarPlacement());
|
|
67
|
+
const rail = await enableNativeUI({ controls: 'verticalOnly' });
|
|
79
68
|
```
|
|
80
69
|
|
|
81
70
|
If a runtime is already active, keep it and add only the placement subscription. `setVerticalBarsLayout` resolves logical edges for RTL; a null edge restores the ordinary Web layout. Use the measured inset instead of a fixed width. Keep the theme's rail stylesheet; Foldable's `ionic-tabs.css` is not needed for this integration.
|
|
@@ -89,11 +78,11 @@ await rail.destroy();
|
|
|
89
78
|
|
|
90
79
|
### With application-owned CSS or without Ionic
|
|
91
80
|
|
|
92
|
-
Use the same `getBarPlacement()` / `barPlacementChange` subscription, but apply the edge and inset to your own CSS instead of calling `setVerticalBarsLayout`. A null edge means your layout should restore its ordinary spacing. For Ionic, retain the rail layout classes described above; for plain HTML, use the `/core` entry and [
|
|
81
|
+
Use the same `getBarPlacement()` / `barPlacementChange` subscription, but apply the edge and inset to your own CSS instead of calling `setVerticalBarsLayout`. A null edge means your layout should restore its ordinary spacing. For Ionic, retain the rail layout classes described above; for plain HTML, use the `/core` entry and [device rail setup](framework-independent.md#device-placement-for-vertical-bars). Neither Foldable nor Native UI supplies the application's CSS. Explicit HTML rail markers remain active independently of CSS; to return those sources to their original placement on a null edge, call `disableVerticalControlArea()`, then `enableVerticalControlArea()` when a rail edge returns. Serialize these changes with your layout updates.
|
|
93
82
|
|
|
94
|
-
Keep Web layout updates separate from native availability: do not pass Foldable's edge through the deprecated `nativeEdge` option. Native UI reads that capability itself.
|
|
83
|
+
Keep Web layout updates separate from native availability: do not pass Foldable's edge through the deprecated `nativeEdge` option. Native UI reads that capability itself. Only an optional browser layout preview substitutes simulated placement for this subscription.
|
|
95
84
|
|
|
96
|
-
For hinge-driven content layout, read `getFoldState()` and subscribe to `foldStateChange` separately. Hinge posture does not select controls or enable the rail; see the theme's [posture subscription and split-pane example](../../theme-ios27/docs/
|
|
85
|
+
For hinge-driven content layout, read `getFoldState()` and subscribe to `foldStateChange` separately. Hinge posture does not select controls or enable the rail; see the theme's [posture subscription and split-pane example](../../theme-ios27/docs/vertical-bars-layout.md#read-the-device-layout).
|
|
97
86
|
|
|
98
87
|
## Native rendering
|
|
99
88
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.0.0-
|
|
2
|
+
"version": "2.0.0-3",
|
|
3
3
|
"author": "Masahiko Sakakibara <sakakibara@rdlabo.jp>",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
@@ -86,6 +86,6 @@
|
|
|
86
86
|
}
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@rdlabo/ionic-theme-utils": "0.1.
|
|
89
|
+
"@rdlabo/ionic-theme-utils": "0.1.5"
|
|
90
90
|
}
|
|
91
91
|
}
|