Skip to content
Native Animation
Gift Unwrap Reveal animation preview

This preview uses fictional demo content. See the props below for the customization options available in this component.

npx nativeanimation add gift-unwrap-reveal
HolidaysSkia

Gift Unwrap Reveal

A gift box that opens to reveal interactive content, with configurable reward content, colors, labels, and box size.

$9 for this animation

Add to your project

Copy the component and its assets into your app with the Native Animation CLI, or paste the agent prompt into Claude Code, Codex or Cursor once the MCP server is connected.

About this animation

A gift box that opens to reveal interactive content, with configurable reward content, colors, labels, and box size.

Why this one

Two satin bow loops follow a resisted pull. The ribbon slips away, the solid lid jumps and lands beside the box, and warm light escapes through the open rim. The reward emerges behind the front wall before settling above the box. No wrapping-paper flaps or disappearing body.

How it works

  1. Follow the knot drag with bounded resistance and spring back if released before opening.
  2. Drive the ribbon release, detached lid, rising card, and particles from one opening phase.
  3. Layer native card content between two Skia canvases so the box rim occludes the reveal; reduced motion uses static poses and a crossfade.

Opening choreography

One 2,300 ms phase drives the opening after release:

  • 0–500 ms: the two loops narrow and separate; the crossed ribbons slide out and fall with rotation and gravity.
  • 450–1,050 ms: the lid rises by 28% of the scene width in an arc, rotates from a negative tilt to +18°, and lands to the right with one small bounce. It remains visible.
  • 450 ms onward: a radial gold light and five soft rays emerge from the dark interior.
  • 900–2,300 ms: a moving target with damping: 14, stiffness: 160, mass: 1 raises the opaque card to 84% width. A native clip follows the front rim; a foreground Skia canvas paints the front wall over the entering card.
  • 1,650 ms: 24 confetti pieces and six sparkles launch from the mouth after the card has cleared it.
  • Final: the box settles to 82% scale below the measured card, with its detached lid and a faint warm glow.

The closed gift breathes from 1 to 1.015 over 2.4 seconds. The knot follows the finger with a maximum displacement of 12% of scene width. Releasing early returns it with an interruptible spring. Two Skia canvases handle the complete scene, with native interactive content between them.

Install

npx expo install @shopify/react-native-skia expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets

Targets Expo SDK 58, React Native 0.88.0, Skia 2.14.0, Reanimated 4.7.1, Worklets 0.13.0, and Gesture Handler ~3.3.0. Wrap the host in GestureHandlerRootView. For web, load CanvasKit before rendering the piece and serve canvaskit.wasm. Copy all three source files listed in piece.json.

Usage

import { GiftUnwrapReveal, type GiftUnwrapRevealRef } from './gift-unwrap-reveal';

const gift = useRef<GiftUnwrapRevealRef>(null);

<GiftUnwrapReveal
  ref={gift}
  style={{ flex: 0, width: 300, height: 400 }}
  fontFamily="Geist_500Medium"
  titleFontFamily="InstrumentSerif_400Regular"
  monoFontFamily="GeistMono_400Regular"
  colors={{ paper: '#426A5A', shadow: '#254539', ribbon: '#F3D69B' }}
  onAccept={() => addGiftCardToWallet()}
/>;

gift.current?.unwrap();
gift.current?.rewrap();

Load these fonts in the host or pass your own. There are no catalog or theme imports. Provide children to replace the default opaque card with native application content. Custom content should fit 84% of the scene width and leave room below for the box. Its measured height sets the final rim position. Give the component a bounded parent; enlarge the host for long copy or accessibility text sizes.

Props

PropTypeDefaultPurpose
childrenReactNodeGift cardContent revealed above the box
onReveal() => void—Once after each completed reveal
onAccept() => void—Default wallet action
colorsPartial themeHoliday paletteGiftColors plus cream, ink, glass, border
labelsPartial labelsEnglish holiday copypull, unwrap, hint, title, amount, description, accept, announcement
pullThresholdnumber0.7Release threshold, clamped to 0.15–1
sizenumber400Maximum scene width
fontFamilystringSystemInterface font
titleFontFamilystringSystemCard heading font
monoFontFamilystringSystemAmount font
onInteraction() => void—Stops host autoplay on direct input
styleStyleProp<ViewStyle>—Outer container
testIDstringgift-unwrap-revealRoot identifier

Exported GiftColors: paper (printed box), pattern, ribbon, reverse (rim and lid light), shadow, highlight, and confetti. Set confetti: [] to disable paper particles. Legacy color keys remain supported. No blur dependency is required; the reward uses an opaque surface with a light gradient.

Ref: unwrap(): void simulates a 350 ms resisted pull and runs the same opening as the gesture. rewrap(): void cancels the sequence and restores the complete gift immediately, including during opening. There is no fade to an empty scene.

Compatibility

Designed for Expo Go on SDK 58 and web.

Accessibility

The gift is a button labeled “Unwrap gift,” with a tap alternative, a 48-point knot target, and the activate accessibility action. The card is excluded from the accessibility tree until reveal completes; its wallet button is at least 48 points high. Announcements and visible copy are configurable.

Reduced motion uses a 200 ms crossfade between static closed and open compositions and the card. Breathing, flying ribbons, lid travel, card movement, digit rolling, and particles are disabled.