@rdlabo/ionic-theme-ios27 2.0.0-1 → 2.0.0-2
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 +5 -4
- package/docs/adaptive-themes.md +2 -2
- package/docs/add-native-ui.md +3 -3
- package/docs/migration.md +21 -1
- package/docs/setup.md +5 -3
- package/docs/special-markup.md +1 -1
- package/docs/vertical-bars-layout.md +71 -1
- package/package.json +2 -2
- package/docs/iphone-duo.md +0 -177
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Ionic Theme iOS27
|
|
2
2
|
|
|
3
|
-
Install with `npm install @rdlabo/ionic-theme-ios27`. For 1.x, use the [v1.2.1 guide](https://github.com/rdlabo-dev/ionic-theme-ios27/tree/ios27-v1.2.1).
|
|
3
|
+
Install with `npm install @rdlabo/ionic-theme-ios27 @erkamyaman/capacitor-foldable`. For 1.x, use the [v1.2.1 guide](https://github.com/rdlabo-dev/ionic-theme-ios27/tree/ios27-v1.2.1).
|
|
4
4
|
A theme for Ionic apps that brings iOS 27 Liquid Glass and motion to the Web. Capacitor iOS apps can also opt into a preview Native UI for supported controls.
|
|
5
5
|
|
|
6
6
|
**[Ionic 9 demo](https://ionic-theme-ios27.rdlabo.dev/) · [Ionic 8 demo](https://ionic8-theme-ios27.rdlabo.dev/) · [Setup guide](docs/setup.md)**
|
|
@@ -27,7 +27,9 @@ A theme for Ionic apps that brings iOS 27 Liquid Glass and motion to the Web. Ca
|
|
|
27
27
|
|
|
28
28
|
## Get started
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
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.
|
|
31
|
+
|
|
32
|
+
Use the [four-step setup guide](docs/setup.md) to install the theme, load styles, configure animations, and preview your first screen. It supports Ionic 8.8.1 or later within Ionic 8 or 9, including Angular, React, and Vue. A native Capacitor project is not required for browser use.
|
|
31
33
|
|
|
32
34
|
The theme styles toolbars, tabs, lists, buttons, search, and overlays, with light and dark appearances. It does not activate native controls. Once the Web theme is working, you can optionally [add Native UI](docs/add-native-ui.md).
|
|
33
35
|
|
|
@@ -38,5 +40,4 @@ The theme styles toolbars, tabs, lists, buttons, search, and overlays, with ligh
|
|
|
38
40
|
- [Using ion-item-group](docs/using-ion-item-group.md): inset list markup.
|
|
39
41
|
- [Animation](docs/animation.md): tab, segment, and search effects.
|
|
40
42
|
- [ESLint](docs/eslint.md): catch unsupported list structure.
|
|
41
|
-
- [Vertical Bars layout](docs/vertical-bars-layout.md): spacing, RTL, and
|
|
42
|
-
- [iPhone Duo device layout](docs/iphone-duo.md): connect device placement and hinge posture.
|
|
43
|
+
- [Vertical Bars layout](docs/vertical-bars-layout.md): spacing, RTL, device placement, posture, and split panes.
|
package/docs/adaptive-themes.md
CHANGED
|
@@ -7,7 +7,7 @@ Use this optional setup when you want browser capabilities to select iOS styles,
|
|
|
7
7
|
Install both themes in an existing Ionic 8 or 9 app (`@ionic/core` 8.8.1 or later):
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install @rdlabo/ionic-theme-ios26 @rdlabo/ionic-theme-ios27
|
|
10
|
+
npm install @rdlabo/ionic-theme-ios26 @rdlabo/ionic-theme-ios27 @erkamyaman/capacitor-foldable
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## 2. Load styles
|
|
@@ -106,7 +106,7 @@ Use this markup to preview the inset grouped list look. For the list structure t
|
|
|
106
106
|
Install all three themes to use iOS 27 on supported Safari versions, fall back to iOS 26 on the preceding Safari generation, and use MD3 whenever Ionic runs in Material Design mode. All three themes require `@ionic/core` 8.8.1 or later:
|
|
107
107
|
|
|
108
108
|
```bash
|
|
109
|
-
npm install @rdlabo/ionic-theme-ios26 @rdlabo/ionic-theme-ios27 @rdlabo/ionic-theme-md3
|
|
109
|
+
npm install @rdlabo/ionic-theme-ios26 @rdlabo/ionic-theme-ios27 @rdlabo/ionic-theme-md3 @erkamyaman/capacitor-foldable
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
Keep the two iOS themes behind the same browser feature checks used in step 2 above, then load MD3 unconditionally. Using `meta.load-css()` throughout also keeps the MD3 styles after the conditional iOS styles in the generated CSS:
|
package/docs/add-native-ui.md
CHANGED
|
@@ -10,10 +10,10 @@ Read [how projection works](../../capacitor-native-ui/README.md#how-projection-w
|
|
|
10
10
|
|
|
11
11
|
This guide assumes a Capacitor 8 application with an iOS project. Web-only theme users can continue without Capacitor; adding native iOS controls requires setting up that native project first. See [Native UI requirements](../../capacitor-native-ui/README.md#requirements) for supported Ionic, iOS, and Xcode versions.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Update the theme and Native UI together to keep their versions aligned, and install Foldable as a separate application dependency:
|
|
14
14
|
|
|
15
15
|
```sh
|
|
16
|
-
npm install @rdlabo/ionic-theme-ios27 @rdlabo/capacitor-native-ui
|
|
16
|
+
npm install @rdlabo/ionic-theme-ios27 @rdlabo/capacitor-native-ui @erkamyaman/capacitor-foldable
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Keep your existing theme stylesheets. Capacitor's default plugin discovery requires a direct dependency; the copy installed through the theme alone does not register the native plugin.
|
|
@@ -46,7 +46,7 @@ Run the app on a supported iOS device or simulator. Eligible fixed controls shou
|
|
|
46
46
|
|
|
47
47
|
## Optional: Vertical Bars
|
|
48
48
|
|
|
49
|
-
For a side rail,
|
|
49
|
+
For a side rail, follow the [standard Vertical Bars setup](../../capacitor-native-ui/docs/ionic-vertical-bars.md): load the layout stylesheet and connect the installed Foldable plugin’s initial placement and events. The Shell includes the rail runtime; no additional startup call is needed. To automatically select rail controls, use `enableNativeUI({ controls: 'verticalOnly' })` instead of the default startup call. See [configuration options](../../capacitor-native-ui/docs/configuration.md).
|
|
50
50
|
|
|
51
51
|
## Upgrading an existing native integration
|
|
52
52
|
|
package/docs/migration.md
CHANGED
|
@@ -15,6 +15,26 @@ Theme styles and ordinary theme API imports remain supported. If you previously
|
|
|
15
15
|
|
|
16
16
|
Add the native package as a direct application dependency, update imports, rebuild Web assets, and run `npx cap sync ios`. Follow the [Native UI migration guide](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/packages/capacitor-native-ui/docs/migration.md) for 1.2.1 startup settings and native project changes. Theme-only apps do not need native startup or plugin setup.
|
|
17
17
|
|
|
18
|
+
## Device layout in 2.0
|
|
19
|
+
|
|
20
|
+
Install Foldable alongside the theme as part of the standard setup:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npm install @rdlabo/ionic-theme-ios27 @erkamyaman/capacitor-foldable
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Replace the former device-layout APIs with Foldable subscriptions:
|
|
27
|
+
|
|
28
|
+
| Previous API | Replacement |
|
|
29
|
+
| ------------------------------------ | ----------------------------------------------------------------------------------- |
|
|
30
|
+
| `DeviceLayout`, `HingeStatus` | `BarPlacement`, `FoldState` and `HingeStatus` from `@erkamyaman/capacitor-foldable` |
|
|
31
|
+
| `getDeviceLayout()` | `Foldable.getBarPlacement()` and `Foldable.getFoldState()` |
|
|
32
|
+
| `deviceLayoutChange` | `barPlacementChange` and `foldStateChange` listeners |
|
|
33
|
+
| Start/stop device-layout monitoring | Subscribe with `addListener()`; remove each listener at teardown |
|
|
34
|
+
| One-shot WebView corner-radius reads | Native UI's `getWebViewMetrics()` |
|
|
35
|
+
|
|
36
|
+
Apply placement with `setVerticalBarsLayout` and posture with `applyFoldStateClasses`, both imported from the theme. Read the initial state as well as subscribing to changes. See [device layout and split panes](vertical-bars-layout.md#read-the-device-layout) and [rail projection](../../capacitor-native-ui/docs/vertical-bars.md#use-with-capacitor-foldable) for the current setup. Installing the packages alone does not subscribe to device events or activate projection.
|
|
37
|
+
|
|
18
38
|
## From the iOS 26 theme
|
|
19
39
|
|
|
20
40
|
For an app using `@rdlabo/ionic-theme-ios26`, the recommended migration keeps that package and adds `@rdlabo/ionic-theme-ios27`. The [adaptive theme setup](adaptive-themes.md) selects iOS 27 or iOS 26 styles by browser capability and leaves Ionic's default iOS appearance on older browsers.
|
|
@@ -24,7 +44,7 @@ For an app using `@rdlabo/ionic-theme-ios26`, the recommended migration keeps th
|
|
|
24
44
|
Keep the iOS 26 package and add iOS 27. The new theme requires `@ionic/core` 8.8.1 or later (Ionic 8 or 9).
|
|
25
45
|
|
|
26
46
|
```bash
|
|
27
|
-
npm install @rdlabo/ionic-theme-ios27
|
|
47
|
+
npm install @rdlabo/ionic-theme-ios27 @erkamyaman/capacitor-foldable
|
|
28
48
|
```
|
|
29
49
|
|
|
30
50
|
### 2. Make the styles adaptive
|
package/docs/setup.md
CHANGED
|
@@ -4,14 +4,16 @@ Give an existing Ionic app the iOS 27 appearance in four steps. This guide uses
|
|
|
4
4
|
|
|
5
5
|
## Before you start
|
|
6
6
|
|
|
7
|
-
Use an existing Ionic Angular, React, or Vue application with Ionic `>=8.8.1 <10`. Keep Ionic's base CSS imports.
|
|
7
|
+
Use an existing Ionic Angular, React, or Vue application with Ionic `>=8.8.1 <10`. Keep Ionic's base CSS imports. Browser-only apps do not need a native Capacitor project.
|
|
8
8
|
|
|
9
|
-
## 1. Install the theme
|
|
9
|
+
## 1. Install the theme and Foldable
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
npm install @rdlabo/ionic-theme-ios27
|
|
12
|
+
npm install @rdlabo/ionic-theme-ios27 @erkamyaman/capacitor-foldable
|
|
13
13
|
```
|
|
14
14
|
|
|
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. Connect it using the [layout guide](vertical-bars-layout.md) when configuring device layout.
|
|
16
|
+
|
|
15
17
|
## 2. Load the styles
|
|
16
18
|
|
|
17
19
|
Add these imports to your global stylesheet after Ionic's base styles. Replace an existing Ionic dark palette import rather than loading multiple palettes:
|
package/docs/special-markup.md
CHANGED
|
@@ -74,7 +74,7 @@ These classes do not reposition a separate `ion-fab`; leave room for it when cho
|
|
|
74
74
|
|
|
75
75
|
iPhone Duo support, including standalone Vertical Bars, is stable starting with version 2.0.0.
|
|
76
76
|
|
|
77
|
-
iPhone Duo support — the vertical system rail, hinge posture, and the posture-driven split-pane layout — is independent of the iOS 27 theme and the full Native UI. See [
|
|
77
|
+
iPhone Duo support — the vertical system rail, hinge posture, and the posture-driven split-pane layout — is independent of the iOS 27 theme and the full Native UI. 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 device-layout monitoring without a projection runtime.
|
|
78
78
|
|
|
79
79
|
See [Vertical Bars](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/packages/capacitor-native-ui/docs/vertical-bars.md) for rail layout classes, control eligibility and native button appearance.
|
|
80
80
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
This optional theme stylesheet owns Web spacing and positioning around a vertical rail. It can be used with your existing theme without loading the full iOS 27 appearance. Native rendering and state synchronization are provided separately by [Capacitor Native UI](https://github.com/rdlabo-dev/ionic-theme-ios27/blob/main/packages/capacitor-native-ui/docs/vertical-bars.md).
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
npm install @rdlabo/ionic-theme-ios27
|
|
6
|
+
npm install @rdlabo/ionic-theme-ios27 @erkamyaman/capacitor-foldable
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
```scss
|
|
@@ -14,6 +14,8 @@ The layout behavior below assumes this stylesheet is loaded. For native runtime
|
|
|
14
14
|
|
|
15
15
|
## Reserve the vertical rail
|
|
16
16
|
|
|
17
|
+
For device setup, use the installed Foldable plugin and apply its initial placement and events through `setVerticalBarsLayout`; follow the [standard Ionic rail setup](../../capacitor-native-ui/docs/ionic-vertical-bars.md). The classes below describe the stylesheet's layout inputs and optional browser simulation, not a manual device setup step.
|
|
18
|
+
|
|
17
19
|
Add `.ios-theme-vertical-bars` to `ion-app` to reserve the rail region on the physical right, or add `.ios-theme-vertical-bars-left` as well to use the physical left:
|
|
18
20
|
|
|
19
21
|
```html
|
|
@@ -62,6 +64,74 @@ setVerticalBarsLayout({ edge: null }); // restore ordinary Web layout
|
|
|
62
64
|
|
|
63
65
|
The helper operates on Web CSS only and works without Capacitor or Native UI startup. The application supplies device state and owns subscriptions. Starting, disabling or destroying Native UI does not change these layout classes or the reserved inset. Unsupported native rails retain the chosen Web rail; choose `edge: null` explicitly if the application wants a horizontal layout instead.
|
|
64
66
|
|
|
67
|
+
## Read the device layout
|
|
68
|
+
|
|
69
|
+
The standard theme and Native UI setup commands install Foldable as a separate application dependency. After building your Web assets, sync the native project:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx cap sync
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Use Capacitor 8.5 or later and build with Xcode 27.1 or newer for iPhone Duo's iOS 27.1 APIs. Foldable supplies placement and posture in the standard setup. Browser simulation can temporarily replace its subscription with fixed layout values. Do not import the plugin's `ionic-tabs.css` alongside this package's rail projection; both would reposition the same tabs.
|
|
76
|
+
|
|
77
|
+
After `ion-app` is mounted, pass device state to `applyFoldStateClasses`. The application owns subscriptions and cleanup. No projection runtime is needed for posture-driven layout.
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { Foldable } from '@erkamyaman/capacitor-foldable';
|
|
81
|
+
import { applyFoldStateClasses } from '@rdlabo/ionic-theme-ios27';
|
|
82
|
+
|
|
83
|
+
const root = document.querySelector('ion-app')!;
|
|
84
|
+
const listener = await Foldable.addListener('foldStateChange', (fold) => applyFoldStateClasses(root, fold));
|
|
85
|
+
applyFoldStateClasses(root, await Foldable.getFoldState());
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
When the application owner is disposed:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
await listener.remove();
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Subscribe to changes, then read the current state. The same helper handles initial values and events.
|
|
95
|
+
|
|
96
|
+
### Posture classes
|
|
97
|
+
|
|
98
|
+
`applyFoldStateClasses` updates the supplied root while preserving unrelated classes:
|
|
99
|
+
|
|
100
|
+
| Class | Applied when |
|
|
101
|
+
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
102
|
+
| `ios-theme-fold-flat` | Flat posture. |
|
|
103
|
+
| `ios-theme-fold-half-opened` | Half-opened posture. |
|
|
104
|
+
| `ios-theme-fold-closed` | Closed posture. |
|
|
105
|
+
| `ios-theme-fold-expanded` | Half-opened, or flat with hinge geometry. Cleared for flat without geometry (including Web fallback) and closed posture. |
|
|
106
|
+
|
|
107
|
+
Only one of the first three classes is retained. The helper does not subscribe to the plugin or change Ionic's split-pane `when` property.
|
|
108
|
+
|
|
109
|
+
## Adapt the split pane
|
|
110
|
+
|
|
111
|
+
For a side-by-side menu on iPhone Duo, opt the `ion-split-pane` into the separately measured Settings layout. The sidebar is 320pt when fully unfolded and reaches the display midpoint when half-opened (50vw). The application supplies the posture; both states have the same viewport width, so a width media query cannot distinguish them:
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<ion-split-pane class="split-pane-fold-layout" contentId="main-content" when="(min-width: 900px)">
|
|
115
|
+
<ion-menu contentId="main-content">...</ion-menu>
|
|
116
|
+
<div id="main-content">...</div>
|
|
117
|
+
</ion-split-pane>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Set the ordinary split-pane width to 320pt in the application's stylesheet, and let the half-open class change only the width value:
|
|
121
|
+
|
|
122
|
+
```css
|
|
123
|
+
ion-split-pane.split-pane-fold-layout {
|
|
124
|
+
--ios-theme-menu-width: var(--ios-theme-split-pane-width);
|
|
125
|
+
--side-width: var(--ios-theme-menu-width);
|
|
126
|
+
--side-max-width: var(--ios-theme-menu-width);
|
|
127
|
+
transition: --ios-theme-split-pane-width 300ms ease;
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The registered `--ios-theme-split-pane-width` defaults to `320px`. `applyFoldStateClasses` sets `ios-theme-fold-half-opened` on `ion-app`; the stylesheet then sets only descendant split panes with `split-pane-fold-layout` to `50vw`. Add this opt-in class once; no state-dependent class binding is needed. Other split panes retain their existing width.
|
|
132
|
+
|
|
133
|
+
Ionic's `when` still controls whether the menu is persistent. The example chooses a fixed 900px breakpoint. If your app needs different breakpoints for folded and ordinary displays, use the `ios-theme-fold-expanded` class applied by the helper to select that policy in your application's layout code. The helper only updates state classes, not `when`. This layout does not enable Vertical Bars or move an overlay menu.
|
|
134
|
+
|
|
65
135
|
## Migration
|
|
66
136
|
|
|
67
137
|
Move `setVerticalControlAreaPlacement` calls from the plugin to `setVerticalBarsLayout({ edge, inset })` from the theme. Move `applyFoldStateClasses` imports to the theme too. Remove `nativeEdge`: it no longer reports availability. The old plugin helpers are deprecated; update existing imports using the [migration guide](../../capacitor-native-ui/docs/migration.md#web-layout-ownership).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rdlabo/ionic-theme-ios27",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "2.0.0-
|
|
4
|
+
"version": "2.0.0-2",
|
|
5
5
|
"description": "iOS27 Theme for Ionic Framework",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"homepage": "https://docs.rdlabo.dev/projects/ionic-theme-ios27",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@rdlabo/capacitor-native-ui": "2.0.0-
|
|
49
|
+
"@rdlabo/capacitor-native-ui": "2.0.0-2",
|
|
50
50
|
"@rdlabo/ionic-theme-utils": "0.1.4",
|
|
51
51
|
"@stencil/core": "^4.43.5",
|
|
52
52
|
"ionicons": "^8.1.0"
|
package/docs/iphone-duo.md
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: iPhone Duo support
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# iPhone Duo support
|
|
6
|
-
|
|
7
|
-
Adapt your Ionic app to iPhone Duo: place navigation and actions in its vertical system rail, and adjust your split pane as the device opens and closes. Existing Ionic markup remains the source of labels, icons, routing, and click handlers.
|
|
8
|
-
|
|
9
|
-
**New here?** Start with [iPhone Duo with your existing theme](../../capacitor-native-ui/docs/ionic-vertical-bars.md) to preview the side layout in Chrome. This page explains device events, placement and split panes. [Vertical Bars](../../capacitor-native-ui/docs/vertical-bars.md) documents control projection and the runtime API.
|
|
10
|
-
|
|
11
|
-
iPhone Duo support is stable starting with version 2.0.0. The real system rail and hinge reporting require iOS 27.1 or later and an app built with Xcode 27.1 or newer.
|
|
12
|
-
|
|
13
|
-
Use the theme layout and native plugin independently for that hardware. Neither requires the full iOS 27 appearance:
|
|
14
|
-
|
|
15
|
-
- Theme: `dist/css/vertical-bars.css` — opt-in classes that reserve the rail's safe area, plus a registered custom property for a posture-driven split-pane width.
|
|
16
|
-
- Native UI: `enableNativeUI({ controls: 'verticalOnly' })` — selects eligible tabs and toolbar controls placed in the reserved area. On Capacitor iOS they are rendered by a native SwiftUI `TabView` and toolbar; everywhere else the same controls appear as Web clones.
|
|
17
|
-
|
|
18
|
-
Device state belongs to [`@erkamyaman/capacitor-foldable`](https://github.com/erkamyaman/capacitor-foldable). The **application** subscribes to its events and chooses its layout. The theme reserves space and adapts the split pane; Native UI projects eligible controls. The theme does not monitor hinge state or bar placement.
|
|
19
|
-
|
|
20
|
-
| Owner | Responsibility |
|
|
21
|
-
| ------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
22
|
-
| Foldable | Report bar placement and hinge posture, initially and when they change. |
|
|
23
|
-
| Application / theme | Subscribe to device events and apply Web layout through `setVerticalBarsLayout` or `applyFoldStateClasses`. |
|
|
24
|
-
| Native UI | Project eligible controls and determine native rail availability independently. |
|
|
25
|
-
|
|
26
|
-
For the native package's integration, including application-owned CSS and plain HTML, see [Use with Capacitor Foldable](../../capacitor-native-ui/docs/vertical-bars.md#use-with-capacitor-foldable).
|
|
27
|
-
|
|
28
|
-
## Choose what to adopt
|
|
29
|
-
|
|
30
|
-
To keep your existing theme and add only the standalone support, follow [iPhone Duo with your existing theme](../../capacitor-native-ui/docs/ionic-vertical-bars.md). This page covers the shared device-layout rules.
|
|
31
|
-
|
|
32
|
-
| Goal | Stylesheet | Runtime |
|
|
33
|
-
| ------------------------------------------ | ------------------- | ---------------------------------------------- |
|
|
34
|
-
| Hinge posture only (layout switches) | none | none — subscribe to `Foldable` directly |
|
|
35
|
-
| Posture-driven split-pane width | `vertical-bars.css` | none — subscribe to `Foldable` directly |
|
|
36
|
-
| Vertical rail for tabs and toolbar actions | `vertical-bars.css` | `enableNativeUI({ controls: 'verticalOnly' })` |
|
|
37
|
-
| Native shell plus the rail | `vertical-bars.css` | `enableNativeUI()` — includes rail projection |
|
|
38
|
-
|
|
39
|
-
```scss
|
|
40
|
-
@use '@rdlabo/ionic-theme-ios27/dist/css/vertical-bars.css';
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
The stylesheet never changes ordinary Ionic UI by itself; every rule requires an opt-in class. Load it unconditionally — these values are simulation and layout inputs, independent from Ionic's normal safe-area variables.
|
|
44
|
-
|
|
45
|
-
The `/vertical-bars` entry point imports `@capacitor/core` at module load, so install it even for Web-only use (it is an optional peer dependency). Apps that want only the stylesheet and its opt-in classes need nothing else.
|
|
46
|
-
|
|
47
|
-
## Read the device layout
|
|
48
|
-
|
|
49
|
-
Install the device-state plugin in the application, then sync the native project:
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
npm install @erkamyaman/capacitor-foldable
|
|
53
|
-
npx cap sync
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Use Capacitor 8.5 or later and build with Xcode 27.1 or newer for iPhone Duo's iOS 27.1 APIs. The dependency is needed for device-driven layout, not for the theme's CSS, browser simulation, or native control projection alone. Do not import the plugin's `ionic-tabs.css` alongside this package's rail projection; both would reposition the same tabs.
|
|
57
|
-
|
|
58
|
-
After `ion-app` is mounted, pass device state to `applyFoldStateClasses`. The application owns subscriptions and cleanup. No projection runtime is needed for posture-driven layout.
|
|
59
|
-
|
|
60
|
-
```ts
|
|
61
|
-
import { Foldable } from '@erkamyaman/capacitor-foldable';
|
|
62
|
-
import { applyFoldStateClasses } from '@rdlabo/ionic-theme-ios27';
|
|
63
|
-
|
|
64
|
-
const root = document.querySelector('ion-app')!;
|
|
65
|
-
const listener = await Foldable.addListener('foldStateChange', (fold) => applyFoldStateClasses(root, fold));
|
|
66
|
-
applyFoldStateClasses(root, await Foldable.getFoldState());
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
When the application owner is disposed:
|
|
70
|
-
|
|
71
|
-
```ts
|
|
72
|
-
await listener.remove();
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Subscribe to changes, then read the current state. The same helper handles initial values and events.
|
|
76
|
-
|
|
77
|
-
### Posture classes
|
|
78
|
-
|
|
79
|
-
`applyFoldStateClasses` updates the supplied root while preserving unrelated classes:
|
|
80
|
-
|
|
81
|
-
| Class | Applied when |
|
|
82
|
-
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
83
|
-
| `ios-theme-fold-flat` | Flat posture. |
|
|
84
|
-
| `ios-theme-fold-half-opened` | Half-opened posture. |
|
|
85
|
-
| `ios-theme-fold-closed` | Closed posture. |
|
|
86
|
-
| `ios-theme-fold-expanded` | Half-opened, or flat with hinge geometry. Cleared for flat without geometry (including Web fallback) and closed posture. |
|
|
87
|
-
|
|
88
|
-
Only one of the first three classes is retained. The helper does not subscribe to the plugin or change Ionic's split-pane `when` property.
|
|
89
|
-
|
|
90
|
-
### Placement values
|
|
91
|
-
|
|
92
|
-
For rail placement, import `setVerticalBarsLayout` from the theme and pass the reported logical `edge` with the measured `inset`:
|
|
93
|
-
|
|
94
|
-
| Value | Web layout effect |
|
|
95
|
-
| ------------------ | ---------------------------------------------------- |
|
|
96
|
-
| `edge: 'leading'` | Physical left in LTR; physical right in RTL. |
|
|
97
|
-
| `edge: 'trailing'` | Physical right in LTR; physical left in RTL. |
|
|
98
|
-
| `edge: null` | Restores ordinary layout. |
|
|
99
|
-
| Measured `inset` | Reserves that width; zero clears the explicit width. |
|
|
100
|
-
|
|
101
|
-
The helper does not report native availability or activate projection. No start/stop monitoring calls are needed. See [Project controls into the rail](#project-controls-into-the-rail) for the subscription.
|
|
102
|
-
|
|
103
|
-
WebView corner radius remains a rendering concern: `configureNativeTransition()` uses the shell's `getWebViewMetrics()` API, independently of `Foldable`.
|
|
104
|
-
|
|
105
|
-
**Migration:** the theme's former `DeviceLayout`, `HingeStatus`, `getDeviceLayout()`, `deviceLayoutChange`, and start/stop device-layout monitoring APIs have been removed. Replace device subscriptions with the `Foldable` APIs above; use `getWebViewMetrics()` for one-shot radius reads. Foldable can infer Duo bar placement from safe-area insets when the app is built without the iOS 27.1 SDK. Hinge data still requires the newer SDK. Apps can also request a fixed rail placement independently of the reported edge.
|
|
106
|
-
|
|
107
|
-
## Reserve the vertical rail
|
|
108
|
-
|
|
109
|
-
Load `vertical-bars.css` as shown above. For class-based browser simulation, safe-area handling, RTL and overlay layout, see [Reserve the vertical rail](vertical-bars-layout.md#reserve-the-vertical-rail). On device, the placement helper below applies the layout classes and measured inset.
|
|
110
|
-
|
|
111
|
-
## Project controls into the rail
|
|
112
|
-
|
|
113
|
-
Enable rail projection once after `ion-app` is mounted, and apply Foldable's placement to the Web layout with `setVerticalBarsLayout`:
|
|
114
|
-
|
|
115
|
-
```ts
|
|
116
|
-
import { Foldable } from '@erkamyaman/capacitor-foldable';
|
|
117
|
-
import { setVerticalBarsLayout } from '@rdlabo/ionic-theme-ios27';
|
|
118
|
-
import { enableNativeUI } from '@rdlabo/capacitor-native-ui';
|
|
119
|
-
|
|
120
|
-
const rail = await enableNativeUI({ controls: 'verticalOnly' });
|
|
121
|
-
const listener = await Foldable.addListener('barPlacementChange', ({ verticalBarEdge, inset }) =>
|
|
122
|
-
setVerticalBarsLayout({ edge: verticalBarEdge, inset }),
|
|
123
|
-
);
|
|
124
|
-
const { verticalBarEdge, inset } = await Foldable.getBarPlacement();
|
|
125
|
-
setVerticalBarsLayout({ edge: verticalBarEdge, inset });
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
When the application owner is disposed:
|
|
129
|
-
|
|
130
|
-
```ts
|
|
131
|
-
await listener.remove();
|
|
132
|
-
await rail.destroy();
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
Native UI detects native availability independently through its own device metrics. The theme helper controls Web layout only. The measured `inset` is passed through instead of assuming a fixed width. Devices without a reported rail, including Web and Android, return a null edge and retain the ordinary layout. For browser simulation, use the [class-based preview](vertical-bars-layout.md#reserve-the-vertical-rail) without connecting device placement.
|
|
136
|
-
|
|
137
|
-
Start either `enableNativeUI({ controls: 'verticalOnly' })` or the full `enableNativeUI()` — not both. If the app already uses Native UI, keep that runtime and use the same `setVerticalBarsLayout` callback. The application owner removes its listeners and destroys its runtime on teardown.
|
|
138
|
-
|
|
139
|
-
On supported iOS versions the runtime hands eligible tabs, back navigation, menu buttons, and fixed-toolbar actions to a native SwiftUI `TabView` and toolbar; on Web, Android, or when native projection is unavailable, Web clones remain the fallback. See [Toolbar actions](../../capacitor-native-ui/docs/vertical-bars.md#toolbar-actions) for control eligibility.
|
|
140
|
-
|
|
141
|
-
### Toolbar actions
|
|
142
|
-
|
|
143
|
-
See [Vertical Bars: Toolbar actions](../../capacitor-native-ui/docs/vertical-bars.md#toolbar-actions) for eligible markup, placement, button appearance and local overrides.
|
|
144
|
-
|
|
145
|
-
### Tab bar
|
|
146
|
-
|
|
147
|
-
See [Vertical Bars: Tab bar](../../capacitor-native-ui/docs/vertical-bars.md#tab-bar) for navigation, labels and Web fallback behavior.
|
|
148
|
-
|
|
149
|
-
## Adapt the split pane
|
|
150
|
-
|
|
151
|
-
For a side-by-side menu on iPhone Duo, opt the `ion-split-pane` into the separately measured Settings layout. The sidebar is 320pt when fully unfolded and reaches the display midpoint when half-opened (50vw). The application supplies the posture; both states have the same viewport width, so a width media query cannot distinguish them:
|
|
152
|
-
|
|
153
|
-
```html
|
|
154
|
-
<ion-split-pane class="split-pane-fold-layout" contentId="main-content" when="(min-width: 900px)">
|
|
155
|
-
<ion-menu contentId="main-content">...</ion-menu>
|
|
156
|
-
<div id="main-content">...</div>
|
|
157
|
-
</ion-split-pane>
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Set the ordinary split-pane width to 320pt in the application's stylesheet, and let the half-open class change only the width value:
|
|
161
|
-
|
|
162
|
-
```css
|
|
163
|
-
ion-split-pane.split-pane-fold-layout {
|
|
164
|
-
--ios-theme-menu-width: var(--ios-theme-split-pane-width);
|
|
165
|
-
--side-width: var(--ios-theme-menu-width);
|
|
166
|
-
--side-max-width: var(--ios-theme-menu-width);
|
|
167
|
-
transition: --ios-theme-split-pane-width 300ms ease;
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
The registered `--ios-theme-split-pane-width` defaults to `320px`. `applyFoldStateClasses` sets `ios-theme-fold-half-opened` on `ion-app`; the stylesheet then sets only descendant split panes with `split-pane-fold-layout` to `50vw`. Add this opt-in class once; no state-dependent class binding is needed. Other split panes retain their existing width.
|
|
172
|
-
|
|
173
|
-
Ionic's `when` still controls whether the menu is persistent. The example chooses a fixed 900px breakpoint. If your app needs different breakpoints for folded and ordinary displays, use the `ios-theme-fold-expanded` class applied by the helper to select that policy in your application's layout code. The helper only updates state classes, not `when`. This layout does not enable Vertical Bars or move an overlay menu.
|
|
174
|
-
|
|
175
|
-
## Vertical Control Area API
|
|
176
|
-
|
|
177
|
-
The runtime handle reference is maintained in [Vertical Bars](../../capacitor-native-ui/docs/vertical-bars.md#vertical-control-area-api).
|