Repository navigation
Releases: erkamyaman/capacitor-foldable
Release list
8.4.1
- Fix: the viewport segments could go stale after the app moved between displays. The web view can report the previous window size for a while after a Duo opens or closes, with no resize event to follow, so the fold was measured against the wrong viewport: the crease at x 456 sits outside a 466 point cover display, which read as no fold at all. The fold is now ignored while the app is on the outer display, since that geometry belongs to the inner one, and a
ResizeObserveron<html>plus avisibilitychangelistener re-measure when the window really changes.
8.4.0
- The fold now works on an app built with Xcode 27.0. The hinge and reserved-region APIs arrived in the 27.1 SDK, so a build made with an older Xcode had the code compiled out entirely and reported no fold at all, even running on iPhone Duo. Those builds now reach the same APIs through the Objective-C runtime, so
isDeviceFoldable(), the fold state and the hinge angle work without waiting for Xcode 27.1. Verified on the Duo simulator: an Xcode 27.0 build tracked the hinge live from 0 to 180 degrees. A build made with 27.1 or later keeps the typed path and is untouched. - The package declares an
exportsmap, so@erkamyaman/capacitor-foldableand its two stylesheets resolve the same way under Node, bundlers and TypeScript.
8.3.3
getBarPlacement()reports the bar's width. The newinsetis how many points the vertical bar takes on its edge, measured rather than assumed, andbarPlacementChangefires when it moves. Asked for by ionic-theme-ios27, which needs the real width to reserve space: today it is 84 points on iPhone Duo, but that is not a number to hard-code.0where no bar is reported.
8.3.2
- Bar placement on an older Xcode.
getBarPlacement()reported no edge whenever the app was built against an SDK without theverticalBarEdgetrait, even though iPhone Duo still moved the bars. The edge is now inferred from the deep safe-area inset the bar leaves (over 70 points, where an ordinary iPhone stays under it), in the reading direction. Apps built with Xcode 27.1 or later keep reading the trait and are unaffected. - Ionic tabs, right-to-left: the side pill was placed with
leftandright, so in Arabic or Hebrew it sat on the opposite side from the native bar. It now usesinset-inline-startandinset-inline-end, which follow the reading direction the same way the reported edge does.
8.3.1
A security fix for dual screen, two accessibility fixes for the Ionic side pill, and some plain speaking in the docs.
Dual screen only loads pages from your own app
The page shown on the other display runs in a second web view that shares the app's profile, and therefore its cookies and storage. It used to take any URL you handed it: anything with a scheme went straight to loadUrl, and a protocol-relative //host/page slipped through the relative branch onto another origin. Once a page was loaded, nothing stopped it navigating the outer display somewhere else, including back onto the app's own origin.
startDualScreen() now rejects anything that is not a page of your app or a data: URL you built yourself, and the view refuses to navigate off your origin afterwards. The web view is also destroyed when dual screen stops, so its timers and connections stop with it.
If you were passing a remote URL it will now be rejected. Serve that page from your own build instead.
Ionic tabs, accessibility
Two real defects in ionic-tabs.css:
- The side pill's buttons were 41 points wide, under Apple's 44pt minimum and Material's 48dp. They now meet both.
- The tab labels were hidden with
display: none, which takes the name out of the accessibility tree, so every tab was an unnamed icon to VoiceOver and TalkBack. They are now hidden visually and kept for assistive technology, so leave the labels in your markup.
Both stylesheets also drop the blur under reduced transparency, increased contrast and forced colours.
Docs
A data: page has an opaque origin and cannot read the app's storage, and encodeURIComponent is URL encoding rather than HTML escaping, so anything interpolated into a data:text/html document has to be escaped first. The Capacitor 7 route closes when Apple requires the iOS 27 SDK in April 2027. And the store-review notes no longer promise more than any dependency can: they say the plugin gives review nothing to object to, not that an app cannot be rejected.
The skill gains an accessibility section, the right-to-left arm its layouts needed, and Apple's ordering rules for the side bar.
8.3.0
Nothing in the plugin can hold up a store review, and agents now know how to use it.
Privacy manifest
The plugin ships a PrivacyInfo.xcprivacy declaring no tracking, no collected data and no required-reason APIs, wired into both the Swift package and the podspec. Apple expects one from SDKs shipped this way, and without it there was a hole in your app's privacy report for a reviewer to ask about. Nothing else changed: the plugin uses public APIs only, adds no Android permissions, and sends nothing anywhere.
A skill for coding agents
npx skills add erkamyaman/capacitor-foldable@capacitor-foldableskills/capacitor-foldable teaches an agent to use this plugin properly rather than guess: laying out around the crease in CSS, the API and what is platform specific, Ionic's tab bar and the keyboard event a fold fires, iPhone Duo, Android foldables, and how to test on both. It also ships inside the npm package, so an agent working in a project that already depends on the plugin will find it in node_modules.
It is beta. Every claim in it was checked against this repo's source and measured on the iPhone Duo simulator, but it has had little real use, so please open an issue if any of it steers you wrong.
Docs
- Why the vertical bar opt-out exists, and why Apple asks you not to reach for it casually.
- The side bar arrives in the web view as
safe-area-inset-right, 84 points, and moves to an 82 point top inset when you disable it, live and without a reload. - A flat foldable still has a fold, but the system marks that region inactive, so reading it natively needs
options: .includeInactive. ionic-tabs.csskeeps one deliberately unscoped rule, which the docs previously denied.
Examples
The even-columns demo now lines its gutter up with the real crease, and tiles no longer land in the fold column from the second row down.
7.0.3 (Capacitor 7)
For Capacitor 7.
The plugin ships a PrivacyInfo.xcprivacy declaring no tracking, no collected data and no required-reason APIs, wired into both the Swift package and the podspec, so it shows up in your app's privacy report. No code changes.
Install with npm install @erkamyaman/capacitor-foldable@7. Capacitor 8 apps want 8.3.0.
8.2.0
Fold state that follows the hinge, everything the system reserves on screen, and control over iPhone Duo's vertical bars.
Fixed
- The fold state follows the hinge angle when UIKit's hinge status disagrees with it (#7). The status updates lazily on iPhone Duo, so the plugin could report
flatat 60 degrees,half-openedat 170, or no fold at all while the phone was open. - The polyfill measures the window again after a fold (#5), so segments and CSS variables are right even when the web view reports the previous size for a moment.
ionic-tabs.cssleaves a hidden tab bar hidden, instead of re-showingion-tab-bar[hidden]in apps that replace it with a native one.
New
getReservedRegions()returns every region the system reserves on the current display, with its kind, whether it is active, and the margins to keep clear. On iPhone Duo that is the fold, the vertical status bar strip and the under-display camera.setVerticalBarBehavior()keeps bars horizontal on iPhone Duo, or hands them back to the system, from JavaScript. The plugin shipsFoldableBridgeViewControllerfor it, which replaces the hand-written view controller subclass the guide used to ask for.foldingChangereports{ folding: true }as soon as the hinge starts moving and{ folding: false }half a second after it stops, so apps can pause animations while the screen is in motion. The polyfill mirrors it as afoldingclass on<html>.hingeMarginsongetFoldState()and--fold-margin-*in the polyfill: the space to keep clear around the crease, 20 points each side on iPhone Duo.getHingeAngle()also returns the system's hingestatus.
Apps
- A new
examplesapp: one runnable demo per API, one file each, laid out as two pages around the crease on iPhone Duo. - Hinge Guess, a game where the fold is the input, is now its own repo.
7.0.2 (Capacitor 7)
For Capacitor 7. Same plugin as 7.0.1, published from GitHub Actions through npm Trusted Publishing, with provenance.
- More npm keywords, so the plugin turns up in searches for viewport segments, device posture and WindowManager.
- No code changes.
Install with npm install @erkamyaman/capacitor-foldable@latest-7. Capacitor 8 apps want 8.2.0.
v8.1.0
Fold position in CSS
The polyfill now sets --fold-left, --fold-top, --fold-width and --fold-height, and a fold-vertical or fold-horizontal class on <html>, whenever the device reports a fold, flat or half-open. Layouts can split along the fold without JavaScript, such as a game on one side and its controls on the other (#3).
.fold-vertical .game { width: var(--fold-left); }
.fold-vertical .controls { left: calc(var(--fold-left) + var(--fold-width)); }Fixes, iPhone Duo
activeDisplaycomes from the fold region instead of the hinge, so it stays right when the app is still on the outer display with the hinge open.- The fold state is checked again after the app moves between displays, not only after hinge moves, so it no longer reports the previous display.