SwiftUI · Part 1 of 2

iPhone Duo on an iPad - Part 1: The fold

How the iPhone Duo concept fakes a book-fold display on a flat iPad: gyro-driven tilt, a 3D hinge at the crease, and a progressive blur that leads the fold. SwiftUI walkthrough with full source.

6 October 2026 · 12 min read

When the iPhone Duo was announced, there was no simulator for it. So we built one: a small Duo mini OS running full screen on an iPad. The moment people asked about most was the fold. Tilt the iPad and the left half of the home screen frosts over, dims and leans away on a soft hinge, the way a book-fold display looks as it closes. Level it out and it snaps back.

There is no folding hardware here. The screen stays flat. This is part 1 of 2: how the fold is faked on the surface, driven by the gyroscope. Part 2 rebuilds the rest of the OS around it and builds Mail on top.

The AI way

How the prompt came together

It wasn’t one prompt. The first days went in circles over the same mistake, putting the effects on the image instead of the screen. These are the prompts that changed direction, with typos fixed:

  • “Here is what we are going to build using the gyroscope for iPad. Before writing any code, tell me what you can see.”
  • “Can you add a visualiser for the progressive blur, and sliders for the blur values, so I can tune them?”
  • “We need to make all the effects on the screen, not on the image.”
  • “The blur is not on the image but on the screen surface. The blur near the edge of the left screen comes first as the screen moves, so it doesn’t show that the screen is empty, and by the time it goes above 45 degrees it reaches the middle.”
  • “Instead of having multiple sliders, tie all of them to one slider.”
  • “I’d like it to go to a max of 85% and then stick with the same blur and everything.”

The hard way

Or build it yourself. This is everything the prompt asks for, one piece at a time, and why each piece is there.

What we’re building

  • A tilt reading from CoreMotion’s gravity vector, smoothed and normalised to −1…1
  • A fold amount from 0 to 1, mapped from the iPad’s long axis in landscape
  • The home screen split at the centre crease, with the left half hinged back in 3D
  • A progressive blur, heaviest at the outer edge and sharp at the crease, using the same filter iOS uses for its own gradient blurs
  • A frost and scrim that sweep toward the crease ahead of the hinge, so the fold never shows an empty gap

Requirements: Xcode 26 or later, an iOS 26 target, and a real iPad to feel it. The fold is driven by the gyroscope, and the Simulator has no gyroscope, so there it rests on the flat home screen.

Fake it on the surface

The obvious approach is to hinge the whole screen like a real page. It falls apart straight away: there is no second display behind it, so any real rotation shows a black void where the page used to be. A tilting picture doesn’t read as folding.

What sells it is everything that happens on the surface. Three layers sit over a home screen that never moves:

  1. A gentle rotation3DEffect leans the left half back from the centre crease.
  2. A progressive blur frosts that half: heaviest at the outer edge, easing to sharp at the crease.
  3. A dark scrim rides along, so the folding side reads as glass catching shadow.

It didn’t start there. The first draft rotated the wallpaper image itself with the gyroscope, with a visualiser for the blur stops and sliders to tune them in the Simulator. It took a few days to see the mistake: the image was never the thing folding. The screen was.

The first draft: the wallpaper itself rotating, tuned with sliders in the Simulator.

The trick is that the blur leads the tilt. As the fold deepens, the frost sweeps inward toward the crease ahead of the geometry, so the receding edge is already soft by the time it would look wrong.

Every screenshot below is the iPad Simulator, built up one step at a time. The Simulator has no gyroscope, so the fold is pinned with launch arguments. Run the repo with -DuoStep 3 -DuoFold 0.5, for example, to see any step for yourself.

The canvas

Start with a home screen that never moves. It’s laid out on a fixed 1194 × 834 design canvas and scaled to cover the display, not fit it. Fitting would letterbox the canvas and leave a sharp gutter right beside where the frost will be.

The Duo home screen, flat and sharp: Music and Calendar widgets on the left, Weather, Find My and the app grid on the right, a dock on the trailing edge.
The canvas, flat. Nothing moves yet.

Split at the crease

Each half of the screen is the full home screen canvas, clipped to one side. Rendering both halves from the same canvas means they line up perfectly when the fold is flat: no seam at the crease.

On screen, nothing changes. That’s the test: if you can see a line at the crease here, the two halves aren’t being drawn from the same layout.

The hinge

Now rotate the left half about its trailing edge, the crease, with a little perspective. Perspective is 0.55: enough to read as depth without the far edge ballooning. Behind it goes a copy of the wallpaper blurred at 60 points and dimmed with 45% black, so the space the half leaves as it leans never reads as pure black.

The left half of the home screen leaning back from the centre crease, completely sharp, with the dark backdrop showing at its outer edge.
The hinge alone, at fold 0.5. It reads as a picture being tilted, not a screen folding.

One small detail: the right-hand group of widgets and icons nudges right by up to 24 points as the fold deepens. It’s barely visible on its own, but it makes the flat half feel like it’s being pushed open rather than standing still.

The progressive blur

The variable blur filter

SwiftUI’s .blur is uniform: one radius for the whole view. The fold needs a blur that’s heavy at one edge and fades to nothing, the same gradient frost iOS draws behind the status bar and the keyboard. That’s Core Animation’s variableBlur filter. It’s private, so it isn’t in any public header, but it can be created by name and attached to the backdrop layer of a UIVisualEffectView.

The iPhone version, built alongside it: the same blur, hinged from the right edge with the whole screen moving.

A mask made of alpha

The catch that cost an afternoon: the filter reads the mask’s alpha, not its brightness. A grey gradient blurs the whole screen evenly. What you need is a white image whose alpha fades from opaque, full blur, to clear, sharp. The mask is only two pixels tall, because the sweep is purely horizontal; the filter stretches it over the layer. Raising the falloff to a power of 1.6 gives the frost a soft tail instead of a hard line.

The flat home screen with a gradient blur over the left half: heavy at the outer edge, fading toward the crease.
The blur alone, at fold 0.5, with no hinge: heaviest at the outer edge, sharp toward the crease.

One warning: variableBlur is a private API. That’s fine for a concept or a prototype on your own device, but App Review will reject it in a shipping app.

The scrim

A blur on its own looks like fog. A dark gradient riding with it, heaviest at the outer edge, makes the folding side read as glass catching shadow. It shares the blur’s front, so the two move as one surface.

  1. The folding half at fold 0.85 with the blur alone: frosted, pale, like fog.Blur alone
  2. The same half with the scrim added: frosted and darkened toward the outer edge.Blur and scrim
The folding half at 0.85. The scrim darkens the outer edge, so the frost reads as glass in shadow, not fog.

All of it together

Put the hinge, the blur and the scrim together, all driven by one fold value from 0 (flat) to 1.

  1. The fold at 0.5 with the frost only keeping pace with the hinge: the leaning half is mostly sharp.If the frost only followed the hinge
  2. The same fold with the frost leading: the leaning half is frosted and dark all the way to the crease.With the frost leading it
The same fold, 0.5. Following, the receding half stays sharp. Leading, it’s frosted to the crease.

The left frame is a what-if, not a stage the project went through: it’s what you get if the frost only keeps pace with the hinge. The half that recedes stays sharp, and your eye reads it as a tilted picture again. That’s why the frost has to lead.

A frost that leads the fold

FoldFrost turns one fold value into the blur radius, the scrim and the position of the frost’s front edge. Two curves do the work. bite raises the fold to the power of attack, 0.4, so the frost arrives early: most of the blur is already there in the first few degrees of tilt. front moves the sharp edge from the outside of the screen toward the crease, and reaches it when the fold is halfway, at sweepAt. The hinge is still only at around 45° by then, so the frost is always ahead of it.

  1. A slight lean with frost already covering the outer part of the left half.Fold 0.15
  2. The left half almost edge-on, frosted and dark, held at the cap.Fold 0.85, the cap
Leading: at 0.15 most of the frost has already arrived. At the 0.85 cap the fold holds.

The blur view is clipped to its own half and left out entirely at rest, so the flat side is never under an effect layer and a level iPad costs nothing extra. The scrim uses the same front, which keeps the darkening and the frost moving as one surface.

The feel is in the numbers

Every value that shapes the fold sits at the top of iPadDuoView. They’re the part worth spending time on:

  • Hinge: 80° at full fold, so the half goes almost edge-on.
  • Cap: the fold stops at 0.85 and holds there, the best-looking pose.
  • Blur: up to 90 points at the outer edge.
  • Scrim: up to 60% black at the outer edge.
  • Lead: the frost reaches the crease at half the fold, about 45°.
  • Nudge: the right-hand icons and widgets slide up to 24 points.
  • Gain: −1.6, from tilt to fold, with the sign setting the direction.
  1. The fold at the cap with the first-pass values: a shallower 35 degree lean and a lighter frost.First pass: 35°, about half the blur
  2. The fold at the cap with the final values: almost edge-on, with a heavy frost.Final: 80° hinge, 90 pt blur
The same fold, 0.85. The first pass is reconstructed from the notes: a 35° hinge, with roughly half the final blur.

The first pass was a shy 35° hinge with a light frost, and it didn’t sell the fold at all. Matching the reference meant pushing the hinge almost edge-on to 80°, roughly doubling the blur, and sweeping the frost across the whole half. Then the fold is capped at 85%, so it settles on its best-looking pose instead of collapsing to a sliver.

Drive it with the gyroscope

Everything so far ran on a fixed fold. On a real iPad, the fold comes from how far you tilt it.

Reading the tilt

MotionManager wraps CoreMotion. It reads the gravity vector rather than Euler angles: gravity’s components are already normalised, stable, and free of the gimbal-lock jumps you get from attitude. asin turns a gravity component back into a true angle, so the mapping doesn’t compress near 90°. Updates arrive 60 times a second, a full 90° tilt maps to 1, and a low-pass filter with a factor of 0.12 takes out the sensor noise.

isUsingGyro matters more than it looks. In the Simulator it stays false, and the view falls back to a fold of zero: the clean home screen, which is exactly what you want while laying things out.

Turning tilt into a fold

The app is locked to landscape, so the roll that folds the screen is the device’s long axis, gy. The two landscape orientations are mirror images of each other, so the sign flips for landscapeLeft. A signed gain of −1.6 sets both sensitivity and direction, and subtracting 0.03 before clamping gives a deadzone: a level iPad stays perfectly still.

Driving it every frame

A TimelineView redraws the canvas every frame from the latest tilt. The visual layer ignores touches; app launches go through transparent hit targets placed over the icons.

Hiding the status bar and the persistent system overlays is what makes the iPad disappear: no iPad clock, no home indicator, just the Duo. Keeping the screen awake stops it dimming mid-demo while you hold it and tilt.

Takeaways

  • When the hardware can’t do it, sell the effect on the surface. A flat screen with the right blur reads as a fold; a rotated screen reads as a picture.
  • Read tilt from the gravity vector and smooth it. It’s stable and avoids gimbal-lock jumps.
  • Let the blur lead the geometry, so the receding edge is soft before it can look wrong.
  • variableBlur reads the mask’s alpha, not its brightness.
  • Put every value that shapes the feel in one place, then tune on a real device.

The full project, including the home screen layout and the motion manager, is open source under the MIT license. The icons and wallpaper are placeholders that resemble Apple artwork; swap in your own before doing anything beyond experimenting.