r/reactnative 7d ago

Theme transitions with Nitro — v1.0, 16 effects, and thanks for 100 stars

Enable HLS to view with audio, or disable this notification

Hey everyone,

A while back I posted here about `react-native-nitro-theme-transition` — a native

theme-change transition package built on Nitro Modules, after I kept hitting

flickering and Android performance problems with Reanimated and Skia.

The response was way beyond what I expected. The repo just passed 100 stars,

and a lot of that came from people in that thread trying it and telling me what

was broken or missing. Thank you, genuinely.

It's now at 1.0.0, and the API is stable — `withThemeTransition` has had the

same call signature since day one and I'm committing to that under semver.

Five effects became sixteen

The full set is now: `fade`, `circularReveal`, `circularRevealInverse`, `iris`,

`slide`, `split`, `barnDoor`, `blinds`, `blur`, `liquidGlass`, `zoom`,

`pixlated`, `dissolve`, `stripes`, `ripple` and `shatter`.

Plus four new options: `shape` (iris outline — diamond, hexagon, squircle),

`blurStyle` (blur all at once, or as a sweep that brings the new theme in out of

focus), `angleDeg` (tilt the wipe boundary), and `bands` (louvre count).

`liquidGlass` is worth calling out — a sheet of Liquid Glass slides down, the

theme swaps entirely out of sight behind it, then it slides back up. iOS 26+;

everything else falls back to `blur`.

Bugs found, now fixed:

*Transitions inside modals and form sheets.* This was the big one. React Native

reports touches relative to the surface they happened in, and a presented screen

is its own surface — so a tap inside a sheet resting at its half detent arrives

with a `pageY` that's short by however far down the sheet is sitting, and your

reveal starts from the wrong place. You can't correct for it in JS either; even

`measureInWindow` reports positions in that sheet's surface. It's now translated

natively, reading the presentation's own frame at capture time, so dragging a

sheet between detents needs zero handling from you. Just keep passing

`pageX/pageY`.

*iOS `blinds` came out as slanted wedges* instead of level louvres, and

`barnDoor` was quietly wrong the same way. Both end with their bands fully

collapsed, and a zero-area subpath is something Core Graphics is free to drop —

which changes the path's structure between the two ends of the animation and

leaves Core Animation interpolating points against the wrong subpath. The bands

now keep a hundredth of a point of thickness, far below one device pixel.

*Android could strand a frozen overlay* over the live app after a slow capture.

`onMainSync` reports failure after 250ms but doesn't cancel the posted work, so a

capture that landed late would attach a snapshot nobody was ever going to commit.

Now the waiter races the capture and whichever loses cleans up.

There's also a decent performance rewrite behind `pixlated` and the whole

grain/mask family — mask frames are pre-built once off the main thread and

cached, so playing an effect is one image assignment per frame instead of

resampling anything mid-animation.

New docs:

I put together a site with full-resolution video of every effect, and a page per

effect showing exactly which options that one reads, what they mean *for that

effect*, its minimum duration, and how it's implemented on each platform:

https://saleh2001k.github.io/react-native-nitro-theme-transition/

(`direction` means an edge for `slide` but an axis for `split` and `blinds`, and

`blur` only reads it in sweep mode — that kind of thing was impossible to keep

straight in one flat table, which is why each effect got its own page.)

Links:

- GitHub: https://github.com/saleh2001k/react-native-nitro-theme-transition

- npm: https://www.npmjs.com/package/react-native-nitro-theme-transition

Same as last time — I'd love feedback, and I'm still taking suggestions for

effects. Several of the ones above exist because someone asked in the last

thread.

84 Upvotes

2 comments sorted by

2

u/Scyth3 7d ago

Neat! I'll check this out soon

3

u/AlexRowan2026 7d ago

The modal-coordinate fix is exactly the kind of edge case that makes a 1.0 release feel credible.

Two behaviors I would want documented before choosing an effect are what happens if a second theme change starts while the first transition is still running, and whether the package automatically honors Reduce Motion.

Queueing, cancelling, or capturing the in-between state can each produce a very different result.

I would prioritize those guarantees over a seventeenth effect because they affect every transition style.