Skip to content
Native Animation
Bubble Sale Banner animation preview

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

npx nativeanimation add bubble-sale-banner
SkiaBlack friday

Bubble Sale Banner

A sale banner with jumping balloon letters and a printing receipt, with configurable copy, character artwork, fonts, and colors.

$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 sale banner with jumping balloon letters and a printing receipt, with configurable copy, character artwork, fonts, and colors.

Why this one

A sale illustration usually locks its headline into an image. This poster keeps the headline editable, draws each character with rounded ink and cream outlines, and lets a touch send a jump through the lettering.

How it works

  1. The container measures its available space and fits a 360 × 640 poster inside it, including landscape and embedded layouts.
  2. The poster canvas draws the window, grain, seventeen fine bristle passes per percentage, six textured flower petals, and balloon letters. A sixteen-point mustard badge carries a fitted heavy sale label, a slowly rotating ring of editable offer copy, thick ink outlines, and a hard offset shadow. It stamps in at 430 ms with scale 1.6 → 1 and a short window shake.
  3. Each letter derives its pose from an entrance spring, an interruptible jump, and one shared ambient clock. Entrance springs use explicit mass 1 and stagger by 45 ms.
  4. Touching the headline locates the closest letter and emits three ink sparks. The accessible headline button provides the same interaction; the offer button sends a wave through every letter.
  5. The character jumps from below after 680 ms. One shared progress drives a mass-1 entrance spring, foot-pivoted squash and stretch (0.9 × 1.1 → 1.08 × 0.92 → 1), and the resting effects. A 600 ms laugh moves it up to 2.7 points with ±2° rotation every 3 seconds; the remaining time is still. Every 4 seconds, a 700 ms shine crosses the artwork-specific card clip with four yellow sparks. Skia dilates the alpha silhouette for a thick white sticker border and a hard black offset shadow. The optional hand clip retains a subtle synchronized card tap.
  6. Reduced motion removes movement and particles, and fades in the poster artwork.

Install

npx expo install @shopify/react-native-skia expo-image react-native-reanimated react-native-worklets

Configure Reanimated for your Expo app. On web, configure Skia's CanvasKit asset using the Skia web installation instructions. No fonts or character images are bundled into the reusable component: supply your own font asset and transparent cutout.

Usage

import { useRef } from 'react';
import { BubbleSaleBanner, type BubbleSaleBannerRef } from './bubble-sale-banner';

const poster = useRef<BubbleSaleBannerRef>(null);

<BubbleSaleBanner
  ref={poster}
  titleFont={require('./assets/Display-ExtraBold.ttf')}
  fontFamily="DisplayExtraBold"
  headline={['BLACK', 'FRIDAY']}
  date="11.27.26"
  character={require('./assets/shopper.webp')}
  onPress={() => openOffers()}
/>;

// Personality knobs and external control:
<BubbleSaleBanner
  titleFont={require('./assets/Display-ExtraBold.ttf')}
  headline={['BIG', 'WEEKEND']}
  offerLines={['SHOP', 'THE SALE']}
  stagger={55}
  sway={1.4}
  colors={{ background: '#FF9AD9', flower: '#74DD8A' }}
/>;
poster.current?.wave();
poster.current?.replay();

Props

PropTypeDefaultDescription
headlinereadonly string[]['BLACK', 'FRIDAY']Up to three fitted headline lines; use short words for generous letter touch spacing.
datestring'11.27.26'Date label.
ribbonstring'SALE'Fitted center label on the sale badge.
saleRingTextstring'UP TO 70% OFF • UP TO 70% OFF •'Rotating badge ring copy.
offerLinesreadonly string[]['SPECIAL', 'OFFER']Short offer button lines.
characterImageSource—Transparent character cutout; use a source at least 640 px wide.
characterFlipHorizontalbooleanfalseMirrors the illustration toward the offer.
characterHandPathstring—SVG path around the hand and card, in original image pixels; enables the separate tap. Supply an artwork-specific silhouette and a URI or bundled image source.
characterCardPathstring—SVG clip around the card in original artwork pixels; enables the synchronized shine and anchors four sparkles. Works without a hand clip.
titleFontDataSourceParamRequiredFont asset for Skia lettering.
fontFamilystringSystemLoaded supporting text font.
colorsPartial<BubbleSaleColors>Poster paletteBackground, frame, block, accent, flower, percentA, percentB, letterFill, letterStroke, ribbon, pattern, and paper.
onPress() => void—Offer action callback.
onInteraction() => void—Stops host autoplay on direct interaction.
headlineAccessibilityLabelstring'Make the headline jump'Headline button instruction.
offerAccessibilityLabelstringOffer linesAccessible offer label.
staggernumber45Entrance delay per letter in milliseconds.
swaynumber2Ambient rotation amplitude in degrees.
styleStyleProp<ViewStyle>—Root container style.
testIDstring'bubble-sale-banner'Prefix for root, headline, and offer identifiers.

The ref exposes replay() and wave(). Autoplay belongs to the demo and stops on interaction.

Compatibility

Targets Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, Skia 2.14.0, and expo-image 58.0.17. Uses bundled Expo Go modules. Supports iOS, Android, and web.

The host owns safe-area padding. The poster fits its parent instead of scrolling and centers in wide containers. Very long copy should be shortened for this display composition. Supporting text respects system font scaling; the headline is deliberately drawn as poster artwork.

Accessibility

The headline is one accessible button announcing the complete headline. Touch position selects the nearest letter, and the offer button provides an accessible whole-headline wave. The offer has a stable test identifier and an effective target larger than 48 points in the required layouts. Reduced motion disables flights, sway, spinning, scrolling, sparks, and spring jumps. Decorative artwork is excluded from interaction.

The demo uses a supplied 1024 × 1024 transparent comic sticker, shown at 212 × 212 poster points at the lower right and extending below the browser frame. The default poster retains its vertical mobile composition; it adapts the horizontal reference rather than reproducing its landscape aspect ratio.