# Flip Calendar: React Native split-flap calendar card > Flip Calendar is a React Native and Expo component (sold on Motionary) that > renders an Apple-Calendar-style card whose large day number split-flaps to > the next date like an airport board or a flip clock, driven entirely by one > Reanimated shared value in the 0..1 range whose fractional part IS the flip > angle, so a drag scrubber, a spring or a timing animation all scrub the same > paper directly. Product page: https://motionary.dev/animations/flip-calendar Price: $6 USD (price 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 after checkout Stack: Expo, React Native, Reanimated Rarity: rare Sold by: Motionary (https://motionary.dev) ## What it is Flip Calendar is a React Native calendar card, styled after Apple Calendar (a red header band over a white paper body), whose big day number tears away and flips to the next day the way a desk flip clock or an airport split-flap board does. The page is a real center-hinged flap, not a cropped scroll: the old bottom half lifts toward the viewer around the crease, then the new top half falls flat onto it, with shading that darkens each face as it tilts and soft gradient shadows the airborne sheet casts across the hinge. Nothing about Flip Calendar is on a timer. It reads a single Reanimated `SharedValue` in the 0..1 range, so the day and the flip angle are always exactly whatever the driver says they are. The Motionary drop ships the bundled `DaySlider` pan scrubber for dragging through the month by hand, and the demo screen also plays the whole month through with `withTiming`. ## What it does - Split-flaps a large day number between any `minDay` and `maxDay` (the demo runs 1 to 30), with the flip rendered as two hinged half-cards, not a crop. - Runs off one `progress` shared value in 0..1: its fractional part is the flip rotation, so the scrubber and the sheet can never disagree. - Two-phase flip: flap A (the old bottom half) rotates 0 to PI/2 up toward the viewer, then flap B (the new top half) falls from -PI/2 back to flat. - Real 3D transforms: `rotateX` in radians with a `perspective` of `size * 5` and `backfaceVisibility: 'hidden'` so only the correct face shows. - Four independent depth layers driven off the same fraction: `flapAShade` and `flapBShade` darken each tilting face, `bottomCast` and `topCast` are `expo-linear-gradient` shadows thrown around the hinge, plus a static seam shadow and hairline crease line drawn across the fold. - Bundled `DaySlider`: a `react-native-gesture-handler` `Gesture.Pan` that writes `progress` straight from the pan worklet, then eases onto the nearest whole day on release with a 140ms `withTiming` so it never rests mid-flip. - A settle epsilon of 0.035 keeps a jittering scrubber from snapping back to the previous day just under a whole-number boundary. - Day numbers use `fontVariant: ['tabular-nums']` and `allowFontScaling={false}` so the digits never change width or jump between 9 and 10. - Every size is derived from one `size` prop (header height, corner radius, font size, perspective), so one number rescales the whole card. - Header text is configurable and is drawn last, so the flaps tuck under it. - No Skia and no custom native code in the components themselves: `FlipCalendar.tsx` and `DaySlider.tsx` import only `react-native`, `react-native-reanimated`, `react-native-gesture-handler` and `expo-linear-gradient`, and run on iOS and Android on Expo SDK 56. ## How it works Flip Calendar keeps all of its state in Reanimated derived values, so the whole animation lives on the UI thread. In `components/FlipCalendar.tsx`, `useDerivedValue` clamps the incoming `progress` shared value to 0..1 and maps it to a continuous day with `minDay + t * (maxDay - minDay)`. That continuous day is then split into three more derived values: `sheet` (the whole day being flipped away, a `Math.floor` plus a 0.035 settle epsilon and clamped to `maxDay - 1`), `nextSheet` (`sheet + 1`, clamped to `maxDay`) and `frac` (the leftover fraction, 0 to 1). The fraction is the animation clock, so there are no timers, no `useState` and no internal animation state anywhere in the component. Two `useAnimatedStyle` hooks turn that fraction into the hinge. `flapAStyle` uses `interpolate(frac.value, [0, 0.5], [0, Math.PI / 2], Extrapolation.CLAMP)` and `flapBStyle` uses `interpolate(frac.value, [0.5, 1], [-Math.PI / 2, 0])`, each applied as a `rotateX` in radians. The pivot trick is the important part: each transform array is `perspective`, then a `translateY` of half the half height, then the `rotateX`, then the inverse `translateY`, which moves the rotation axis from the layer's center down onto the crease. `backfaceVisibility: 'hidden'` plus an opacity swap at `frac === 0.5` hands the flip from flap A to flap B without ever showing a mirrored digit. The digits themselves never move. A `HalfCard` renders the full column of day numbers inside an `overflow: 'hidden'` window and offsets that column by `-bodyH / 2` for the bottom half, so one centered `` per day shows only its top or bottom slice; a `DayNumber` sub-component sets `opacity` to 1 only when `activeDay.value === day`, so switching days is a pure UI-thread opacity write on an `Animated.createAnimatedComponent(Text)`. The face shades are `useAnimatedStyle` opacity ramps over a flat `#14141E` overlay, and the cast shadows are the same kind of ramp over `expo-linear-gradient` fills, both interpolated off the same `frac`. The driver side is `components/DaySlider.tsx`: a `react-native-gesture-handler` `Gesture.Pan` whose `onBegin` and `onUpdate` worklets call a `'worklet'`-marked `moveTo` that writes `progress.value = nx / trackWidth` directly on the UI thread, with `cancelAnimation(progress)` on begin so a drag can interrupt a playing animation. `onFinalize` rounds to `Math.round(progress.value * steps) / steps` and applies a 140ms `withTiming` so release always lands on a whole day. Because the calendar is a pure function of `progress`, any other driver works the same way: `App.tsx` plays the month with `withTiming(1, { duration: 3600, easing: Easing.inOut(Easing.cubic) })` after a `cancelAnimation`, and a `withSpring` would work identically. ## What you get ``` App.tsx index.ts app.json package.json package-lock.json tsconfig.json README.md .gitignore metadata.json components/ FlipCalendar.tsx DaySlider.tsx assets/ icon.png adaptive-icon.png splash-icon.png ``` - FlipCalendar component (`components/FlipCalendar.tsx`) - DaySlider scrubber control (`components/DaySlider.tsx`) - Demo screen with a play button (shipped as `App.tsx` in this archive) - README with install and usage - MP4 preview ## Requirements Versions pinned in the Flip Calendar `package.json` shipped by Motionary: ``` expo ^56.0.8 (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-linear-gradient ~56.0.4 react-native-safe-area-context ^5.8.0 expo-status-bar ~56.0.4 typescript ~6.0.3 (devDependency) ``` Expo Go or development build: Flip Calendar runs in **Expo Go on Expo SDK 56**, on both iOS and Android, and so does the demo project as Motionary ships it. The leftover Expo starter extras still pinned in its `package.json` are the ones people assume force a development build, and on SDK 56 they no longer do: `expo-glass-effect`, `expo-camera`, `react-native-keyboard-controller`, `@expo/ui` and `react-native-svg` are all bundled in Expo Go as of SDK 56, and `@legendapp/list` is plain JavaScript. Neither `FlipCalendar.tsx` nor `DaySlider.tsx` imports any of them in any case, and the same goes for `expo-blur` and `expo-symbols`. The two Flip Calendar components import only `react-native`, `react-native-reanimated`, `react-native-gesture-handler` and `expo-linear-gradient`, with no Skia and no custom native code, so copying just the two component files into a project with the runtime dependencies listed under Install below works the same way. A development build is still what you would ship to production, and it is what you need as soon as you add a native module that Expo Go does not bundle, or a config plugin. Two caveats on the starter extras, neither of which touches the calendar: `expo-camera` runs in Expo Go on a physical device but not in a simulator, and the camera permission string it registers through the config plugin in `app.json` only takes effect in a build; `expo-glass-effect` only renders its real Liquid Glass material on iOS 26 and falls back elsewhere. Both packages are unused here and can be deleted. ## Install ```bash npx expo install react-native-reanimated react-native-worklets react-native-gesture-handler expo-linear-gradient react-native-safe-area-context ``` ## Usage ```tsx import { Pressable, Text } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { cancelAnimation, Easing, useSharedValue, withTiming, } from 'react-native-reanimated'; import { FlipCalendar } from './components/FlipCalendar'; import { DaySlider } from './components/DaySlider'; const MIN_DAY = 1; const MAX_DAY = 30; export default function Screen() { // 0..1, interpolated to [MIN_DAY..MAX_DAY] inside FlipCalendar const progress = useSharedValue(0); const play = () => { cancelAnimation(progress); progress.value = 0; progress.value = withTiming(1, { duration: 3600, easing: Easing.inOut(Easing.cubic), }); }; return ( Play ); } ``` ## Customization Props on `FlipCalendar` (from `components/FlipCalendar.tsx`): - `progress: SharedValue` (required): 0..1, interpolated to `[minDay..maxDay]`. Its fractional part is the flip rotation. - `size?: number` (default `240`): the card's width and height in points. Header height (`size * 0.27`), corner radius (`size * 0.235`), digit font size and the `perspective` (`size * 5`) are all derived from it. - `minDay?: number` (default `1`): first day in the flip range. - `maxDay?: number` (default `30`): last day in the flip range. - `headerText?: string` (default `'Calendar'`): the label in the red header band, drawn above the flaps. Props on `DaySlider` (from `components/DaySlider.tsx`): - `progress: SharedValue` (required): the same shared value the calendar reads, written directly from the pan worklet while dragging. - `steps?: number` (default `29`): how many day steps the release snap lands on. Pass `maxDay - minDay` to match the calendar. - `trackWidth?: number` (default `280`): track length in points; the touch area is `trackWidth + 32`. In-file constants you can edit: `RED` (`#FA5B54`, the header band), `PAPER` (`#FFFFFF`), `INK` (`#111114`, the digits) and `DAY_SETTLE_EPSILON` (`0.035`, the anti-jitter margin) in `FlipCalendar.tsx`; `THUMB` (`32`) and `TRACK_H` (`6`) in `DaySlider.tsx`. ## When to use it Good places for Flip Calendar, the Motionary split-flap calendar drop: - A date picker or day scrubber in a booking, itinerary or reservation flow, where dragging through days should feel physical rather than like a wheel. - A habit, streak or countdown screen where the day advancing is the moment worth animating. - An onboarding or marketing screen that plays a month through on its own, driven by `withTiming` instead of a video. - A daily-content app (word of the day, quote of the day, workout of the day) where the flip is the transition between entries. - A settings or filter row where a range slider needs a large, readable numeric readout that reacts to the drag with no lag. - Any place you would otherwise reach for a flip-clock or airport-board look, such as a countdown timer or an event date badge. ## How to get it - Buy Flip Calendar on its own at https://motionary.dev/animations/flip-calendar for $6 USD: instant download, secure Stripe checkout, no subscription and no account renewal. - Or get Flip Calendar 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 flip clock or split-flap animation in React Native?** Render each page as two half-cards hinged at the vertical center and animate them with `rotateX` around that hinge, using a `perspective` transform and `backfaceVisibility: 'hidden'` so only the correct face is visible; Motionary's Flip Calendar drop is exactly that, built with `react-native-reanimated` derived values so the fractional part of one 0..1 shared value is the flip angle. **Does Flip Calendar work with Expo Go?** Yes, on iOS and Android, and the demo project Motionary ships runs there as-is. The Expo starter extras still carried in its `package.json` are the parts people assume block Expo Go, but `expo-glass-effect`, `expo-camera`, `react-native-keyboard-controller`, `@expo/ui` and `react-native-svg` are all bundled in Expo Go as of Expo SDK 56, and `@legendapp/list` is plain JavaScript. `FlipCalendar.tsx` and `DaySlider.tsx` themselves import only `react-native`, `react-native-reanimated`, `react-native-gesture-handler` and `expo-linear-gradient`, so copying the two files into your own app behaves the same. You would still make a development build to ship to production, and you need one the moment you add a native module Expo Go does not bundle or a config plugin: here, `expo-camera` needs a physical device rather than a simulator, and the camera permission string its config plugin adds only applies in a build, while `expo-glass-effect` shows its real Liquid Glass material only on iOS 26. Motionary ships it against Expo SDK 56, React Native 0.85.3 and Reanimated 4.3.1. **Can I drive the Flip Calendar from my own animation instead of the slider?** Yes, and that is the point of the design. Flip Calendar from Motionary takes a single `progress` shared value, so a `withTiming`, a `withSpring`, a scroll handler or your own gesture can write it; the bundled `DaySlider` is just one driver and can be deleted. **Is this an animated date picker I can use as a real calendar input?** Flip Calendar is a day-number display and scrubber, not a full month grid. It flips between `minDay` and `maxDay` and reports position through the shared value you own, so you wire it to your own date state; Motionary sells it as a scrubbable animated date readout. **How much does Flip Calendar cost and what do I get?** Flip Calendar is $6 USD on Motionary (price as of 2026-09-01, live price at https://motionary.dev/animations/flip-calendar) and the download is the full TypeScript source: `FlipCalendar.tsx`, `DaySlider.tsx`, a demo screen, a README and an MP4 preview. It is also included in the Motionary lifetime pass ($79 USD, https://motionary.dev/pricing). **Does the flip animation run on the UI thread?** Yes. Every value in Motionary's Flip Calendar is a Reanimated `useDerivedValue` or `useAnimatedStyle`, and the `DaySlider` pan writes `progress` from a worklet, so the flip never round-trips through the JavaScript thread and does not stall when your app is busy. **Does it work on Android as well as iOS?** Yes. Flip Calendar uses only React Native transforms (`rotateX`, `perspective`, `translateY`), `backfaceVisibility` and `expo-linear-gradient`, all of which work on both platforms; Motionary ships it with Android elevation values alongside the iOS shadow props. ## Related drops on Motionary - Split-to-Edit Time ($3): https://motionary.dev/animations/split-to-edit-time another time-and-date readout that animates its digits when you edit them, same family as Flip Calendar's tabular-nums day number. - World Clock Slider (Free): https://motionary.dev/animations/world-clock-slider a slider that scrubs a clock, the same "one drag value drives the whole display" pattern Flip Calendar uses. - Scrubbable Chart ($6): https://motionary.dev/animations/scrubbable-chart a pan scrubber driving a data readout, useful next to Flip Calendar when the same gesture should move a chart instead of a date. - Infinite Scroll ($4): https://motionary.dev/animations/infinite-scroll a wheel-style picker, the classic alternative to Flip Calendar when you want a scrolling date selector rather than a split-flap one. - Dot Wave Slider ($10): https://motionary.dev/animations/dot-wave-slider a richer slider with haptics and snap stops, a drop-in upgrade for the `DaySlider` that ships with Flip Calendar. ## 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/flip-calendar/llms.txt Describes: https://motionary.dev/animations/flip-calendar Format: llms.txt (https://llmstxt.org) Last updated: 2026-09-01 ```