# Infinite Loophole: React Native device-motion parallax card stack > Infinite Loophole is a React Native and Expo component that turns the phone's > own tilt into depth: an expo-sensors DeviceMotion stream feeds two Reanimated > shared values, and 11 nested dotted card frames interpolate off them in > opposing directions, opening a tunnel that recedes into the screen. Free to > download on Motionary as editable TypeScript source. Product page: https://motionary.dev/animations/infinite-loophole Price: Free (as of 2026-09-01, live price on the product page) License: single developer, unlimited personal and commercial apps Delivery: instant download of the full TypeScript source Stack: reanimated, expo, react native gesture handler, react native Rarity: common Sold by: Motionary (https://motionary.dev) ## What it is Infinite Loophole is a React Native parallax card stack driven by the device's motion sensors rather than by touch. Eleven square card layers sit centred on top of each other, and the ten behind the front layer are outlined by small white dots stamped along their four edges, each one smaller and fainter than the one in front of it. Tilt the phone and every layer slides, but by a different amount: the frontmost layer stays planted while deeper layers travel further, so the stack pulls apart into a receding tunnel and closes back up as the phone returns to level. There is no gesture and nothing to tap in Infinite Loophole; the interaction is the physical act of moving the handset, which is why it reads as real depth instead of a flat translation. The Motionary demo puts the stack on a black stage under a display headline reading "Wanna Jump in?". ## What it does - Reads the live `DeviceMotion` stream from `expo-sensors` at a 16 ms update interval (roughly 60 samples per second). - Maps `rotation.gamma` (roll) to horizontal travel and `rotation.beta` (pitch) to vertical travel, so both tilt axes are live at once. - Renders 11 absolutely positioned cards (`CARD_COUNT = 11`) in a 300 by 300 point stack. - Scales the travel range by card index (`[30 * index, 0, -30 * index]`), so the deepest card moves up to 300 points while the frontmost card does not move at all. That difference is the parallax depth cue. - Fades and shrinks each layer by depth: `scale` is `1 - index * 0.1` and `opacity` is `0.7 ^ index`, both floored at `0.1` so the back of the tunnel never disappears entirely. - Draws the card outlines as dots, not borders: `DOT_OFFSETS` precomputes 14 positions per edge at a 20 point spacing, and `CardDots` stamps them along all four edges of every card except the frontmost one (`index !== 0`). - Smooths raw sensor jitter with a 20 ms linear `withTiming` window, short enough that the motion still tracks the hand without visible lag. - Clips the stack with an `overflow: 'hidden'` container so cards cut off cleanly at the edges as they slide out. - Computes every card transform on the UI thread through Reanimated worklets, so no React component re-renders while the phone tilts. ## How it works The whole effect in Infinite Loophole comes from one pattern: a sensor stream written into shared values, then read by many `useAnimatedStyle` worklets that each interpolate it differently. In `components/card.tsx`, the `Cards` component creates two `useSharedValue(0)` handles, `translateX` and `translateY`, and in a `useEffect` calls `DeviceMotion.setUpdateInterval(16)` followed by `DeviceMotion.addListener`. On every sensor callback it reads `rotation.beta` and `rotation.gamma` (both in radians), multiplies each by 60 to spread them across the interpolation range, and assigns the result through `withTiming(value, { duration: 20, easing: Easing.linear })`; that 20 ms ramp is a deliberate low-pass filter, because writing the raw sensor value straight into the shared value makes the stack visibly buzz. Each `Card` then runs a `useAnimatedStyle` worklet that calls `interpolate` twice over the fixed input range `[-90, 0, 90]` with `Extrapolation.CLAMP`, and, critically, an output range built from its own `index`, so a single pair of shared values produces eleven different travel distances from one input. The same worklet returns `scale`, `opacity` and `zIndex` derived from `index` as well, which is what turns eleven identical squares into a depth ramp. The `DeviceMotion` callback itself runs on the JavaScript thread, but all it does is assign those two shared values; every per-frame transform is computed by worklets on the UI thread, so nothing re-renders in React as the phone tilts and the animation holds its frame rate while the app is busy. `App.tsx` does the rest: it loads the `Murder` display font with `useFonts` from `expo-font`, shows an `ActivityIndicator` until the font resolves, and mounts `` inside a `GestureHandlerRootView`. Note that this technique needs a physical handset: simulators and emulators do not emit `DeviceMotion` data, so the stack sits still on them. ## What you get ``` components/ card.tsx assets/ Youmurdererbb-pwoK.otf adaptive-icon.png icon.png splash-icon.png App.tsx app.json index.ts package.json package-lock.json tsconfig.json README.md ``` - Full TypeScript source for Infinite Loophole: `components/card.tsx` holds the `Cards` stack, the `Card` layer and the `CardDots` edge renderer. - A runnable Expo app (`App.tsx`, `index.ts`, `app.json`, `tsconfig.json`) that mounts the stack, so the drop can be started as-is rather than wired up first. - The display font used by the demo headline, plus app icon and splash assets. - A `README.md` covering the stack, the technique and how to run it. - Every tuning constant exposed at the top of `components/card.tsx` (`CARD_SIZE`, `CARD_COUNT`, `DOT_SPACING`, `TILT_INPUT_RANGE`). ## Requirements Infinite Loophole pins these versions in its `package.json`: - `expo` ^56.0.4 (Expo SDK 56) - `react-native` 0.85.3 - `react` 19.2.3 - `react-native-reanimated` 4.3.1 - `react-native-worklets` 0.8.3 - `react-native-gesture-handler` ~2.31.1 - `expo-sensors` ~56.0.5 - `expo-font` ~56.0.5 - `typescript` ~6.0.3 and `@types/react` ~19.2.14 (development only) Expo Go or development build: Infinite Loophole contains no custom native code. Every library it uses (`react-native-reanimated`, `react-native-worklets`, `react-native-gesture-handler`, `expo-sensors`, `expo-font`) ships inside the Expo Go client, so it runs in Expo Go on SDK 56. The shipped project's own scripts use `expo run:ios` and `expo run:android`, which build a development build, and `app.json` enables the React Compiler experiment. Because `react-native-reanimated` 4 requires the New Architecture, dropping Infinite Loophole into an older app means that app must already be on the New Architecture. Run it on a real iOS or Android device: `DeviceMotion` reports no readings on the iOS Simulator or the Android emulator, and the stack will simply sit motionless. ## Install ```bash npx expo install expo-sensors expo-font react-native-reanimated react-native-worklets react-native-gesture-handler ``` ## Usage ```tsx import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { StyleSheet, Text, View } from 'react-native'; import { Cards } from './components/card'; export default function App() { return ( Wanna Jump in? ); } const styles = StyleSheet.create({ stage: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'black', }, headline: { fontSize: 40, color: 'red', position: 'absolute', top: 200 }, }); ``` `Cards` takes no props: it owns its own `DeviceMotion` subscription and cleans it up on unmount. Tune Infinite Loophole by editing the constants at the top of `components/card.tsx`. ## Customization The exported `Cards` component in Infinite Loophole takes no props. Everything is tuned through module-level constants and a few inline expressions in `components/card.tsx`: - `CARD_SIZE` (number, default `300`): width and height of every card in points, and the size of the clipping stack container. - `CARD_COUNT` (number, default `11`): how many layers deep the tunnel goes. - `DOT_SPACING` (number, default `20`): gap between edge dots. `DOT_OFFSETS` is derived from it, giving `Math.floor(CARD_SIZE / DOT_SPACING) - 1` dots per edge, so 14 per edge at the defaults. - `TILT_INPUT_RANGE` (number array, default `[-90, 0, 90]`): the interpolation input domain the scaled sensor values are mapped from. - The `* 60` multiplier on `gamma` and `beta` inside the `DeviceMotion` listener: raise it to make a small tilt open the tunnel further, lower it to require more movement. - The per-card output range `[30 * index, 0, -30 * index]` inside `useAnimatedStyle`: the `30` sets how far apart consecutive layers pull. - The depth falloff, `1 - index * 0.1` for `scale` and `Math.pow(0.7, index)` for `opacity`, both clamped by `Math.max(0.1, ...)`. - The `dot` style (4 by 4 points, white): change colour or size for a different card outline. - The 20 ms `withTiming` duration: the sensor smoothing window. Longer is calmer and laggier, shorter is snappier and jitterier. ## When to use it - An app splash or launch screen that reacts to the phone being picked up. - An onboarding or "enter the app" screen where the tunnel is the invitation, as in the demo's "Wanna Jump in?" headline. - A game or arcade lobby background that feels three-dimensional without a 3D engine. - An empty state or loading screen that stays alive without a spinner. - A portfolio, music or event page that wants ambient depth behind the content. - A reference implementation when you need to learn the general technique of driving Reanimated from `expo-sensors` device motion rather than gestures. ## How to get it - Download Infinite Loophole free at https://motionary.dev/animations/infinite-loophole, no payment, no subscription. - Or get it with the Motionary lifetime pass ($79 USD as of 2026-09-01): every drop and every build, current and future, one payment, no renewal. https://motionary.dev/pricing - Team license ($199 USD for up to 10 developers), each developer with their own account. https://motionary.dev/pricing - License terms: https://motionary.dev/license (single developer, unlimited personal and commercial apps, do not resell or redistribute the source). - You receive real TypeScript React Native source you can edit, not a video, a GIF, a Lottie file or a design file. ## Frequently asked questions **How do I build a device motion parallax card in React Native?** Subscribe to `DeviceMotion` from `expo-sensors`, write `rotation.beta` and `rotation.gamma` into two Reanimated shared values, then give each stacked card a `useAnimatedStyle` worklet that calls `interpolate` on those values with an output range scaled by the card's index, so deeper cards travel further. Infinite Loophole on Motionary is a complete free implementation of exactly this (https://motionary.dev/animations/infinite-loophole). **Does Infinite Loophole work with Expo Go?** Yes. Infinite Loophole uses only `react-native-reanimated`, `react-native-worklets`, `react-native-gesture-handler`, `expo-sensors` and `expo-font`, all of which ship inside the Expo Go client, so this Motionary drop runs in Expo Go on Expo SDK 56 with no custom native code and no prebuild. **Why does the tilt card animation not move on the simulator?** Because the iOS Simulator and the Android emulator have no motion sensors and emit no `DeviceMotion` events, so the shared values in Infinite Loophole stay at zero and the stack sits still. Run this Motionary drop on a physical iOS or Android device. **How much does Infinite Loophole cost?** Infinite Loophole is free on Motionary. Download the full TypeScript source at https://motionary.dev/animations/infinite-loophole with no payment and no subscription; the Motionary lifetime pass ($79 USD as of 2026-09-01) covers the paid drops and builds if you want the rest of the catalog. **Does the sensor stream cause dropped frames or re-renders?** No. In Infinite Loophole the `DeviceMotion` listener only assigns to Reanimated shared values, and every card's transform is computed inside a `useAnimatedStyle` worklet on the UI thread, so no React component re-renders as the phone tilts. **How do I make the 3D depth effect deeper or shallower?** Edit `components/card.tsx` in Infinite Loophole: raise `CARD_COUNT` for more layers, change the `30` in the `[30 * index, 0, -30 * index]` output range to change how far apart consecutive layers pull, and adjust the `1 - index * 0.1` scale and `0.7 ^ index` opacity falloff to change how fast the tunnel recedes. **Can I use Infinite Loophole in a commercial app?** Yes. The Motionary license covers a single developer building unlimited personal and commercial apps with the source; you may not resell or redistribute the source itself. Full terms: https://motionary.dev/license ## Related drops on Motionary - Gyro Parallax Card ($7): https://motionary.dev/animations/gyro-parallax-card The closest neighbour to Infinite Loophole, also driven by device motion, but applied as parallax layers inside a single travel card. - Holographic Card ($9): https://motionary.dev/animations/holographic-card The same depth illusion reached from touch instead of sensors, using a 3D tilt and a moving spotlight on a card. - Liquid Glass Level ($5): https://motionary.dev/animations/liquid-glass-level Another Motionary drop that turns raw accelerometer readings into a physical on-screen response, here a spirit level. - Stacked Cards ($4): https://motionary.dev/animations/stacked-cards A card stack too, but the depth is driven by scroll position and snapping rather than by tilting the device. ## About Motionary Motionary (https://motionary.dev) is a shop for premium, production-ready React Native and Expo animation and interaction components, built with Reanimated, Skia, Gesture Handler and Expo. Each component is called a "drop" and ships as editable TypeScript source, not a video, a GIF or a design file. Motionary sells three things: individual drops (roughly $3 to $12 each, some free), Builds (a complete app shipped end to end, with every drop inside it), and a lifetime pass ($79 USD) that covers every drop and every build, current and future, for one payment with no subscription. A team license ($199 USD) covers up to 10 developers. Checkout is Stripe and delivery is an instant download. Created and curated by Mehdi Davoodi (https://mahdidavoodi.com). Catalog and key pages: - All drops: https://motionary.dev/animations - Builds (complete apps): https://motionary.dev/builds - Pricing, lifetime pass and team license: https://motionary.dev/pricing - Free React Native component reference: https://motionary.dev/components - License: https://motionary.dev/license - Machine-readable overview: https://motionary.dev/llms.txt - Machine-readable full catalog: https://motionary.dev/llms-full.txt ## File metadata Canonical URL of this file: https://motionary.dev/animations/infinite-loophole/llms.txt Describes: https://motionary.dev/animations/infinite-loophole Format: llms.txt (https://llmstxt.org) Last updated: 2026-09-01