Skip to content
Native Animation
Hanging Banners Welcome animation preview

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

npx nativeanimation add hanging-banners-welcome
OnboardingWelcome

Hanging Banners Welcome

A pet welcome screen with swinging ribbons that open into details, with configurable pets, copy, background color, and fonts.

$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 pet welcome screen with swinging ribbons that open into details, with configurable pets, copy, background color, and fonts.

Why this one

Instead of a static onboarding illustration, the composition responds like a set of hanging curtains. Pull an individual ribbon, sweep across the group, then let the selected ribbon become the next screen. The original image stays mounted throughout the transition.

How it works

  1. The host is measured with onLayout; ribbon widths divide its width evenly and lengths use the hero height.
  2. Each ribbon enters 80 ms after its neighbor with an explicitly configured, nearly critical spring and a finite, damped four-degree swing.
  3. A Gesture Handler tap/pan race supplies immediate pressure feedback, elastic vertical pull, and horizontal curtain motion. Release uses gesture velocity.
  4. One shared detail progress controls ribbon geometry, portrait position, and welcome/detail opacity. Independent shared values handle pressure and local physics.
  5. The selected ribbon expands into the detail background. replay() brings the welcome back; all gestures can interrupt ongoing springs.
  6. The demo performs entrance → Biscuit pull → horizontal sweep → continue → return. Physical interaction cancels its timers.

Install

npx expo install expo-image react-native-gesture-handler react-native-reanimated react-native-worklets

Copy this folder and place your screen inside a GestureHandlerRootView. Load any custom font families in your app before rendering. The component has no catalog or theme imports; the demo uses the catalog's fonts. No icons or logos are used.

Usage

import { HangingBannersWelcome } from './hanging-banners-welcome';

<HangingBannersWelcome
  pets={[
    { name: 'Luna', color: '#D9DEFF', image: require('./kitten.webp'), length: 0.65 },
    { name: 'Biscuit', color: '#CFF5D6', image: require('./puppy.webp'), length: 0.83 },
  ]}
  title="Find your new best friend nearby"
  body="Meet the friends waiting for a home."
  cta="Meet them"
  onContinue={(pet) => openProfile(pet)}
/>
const welcome = useRef<HangingBannersWelcomeRef>(null);
<HangingBannersWelcome
  ref={welcome}
  pets={pets}
  swingAngle={3}
  staggerMs={80}
  backgroundColor="#17192D"
  textColor="#F9F7F2"
  mutedColor="#C7C5D4"
  accentColor="#FF7A5C"
  buttonTextColor="#1E2250"
  fontFamily="YourRegularFont"
  mediumFontFamily="YourMediumFont"
  titleFontFamily="YourBoldFont"
/>
// welcome.current?.pull(1); welcome.current?.replay();

Props

PropTypeDefaultPurpose
petsHangingPet[]RequiredOne to four names, colors, image sources, and relative lengths; extra entries are ignored.
titlestringFind your new best friend nearbyWelcome heading.
bodystringA little hello could be the start of something wonderful.Supporting copy.
ctastringMeet themContinue button and label.
brandstringNoneOptional text-only wordmark below the ribbons.
detailBodystringYour next chapter starts with a new best friend.Detail copy and announcement.
backLabelstringBack to friendsReturn button.
backgroundColorstring#FBF6F1Welcome surface.
textColorstring#1E2250Headings, names, detail ink, and return border.
mutedColorstring#646477Welcome body and wordmark.
accentColorstring#FF7A5CContinue surface and glow.
buttonTextColorstring#1E2250Continue ink.
fontFamily / mediumFontFamily / titleFontFamilystringSystemBody, controls, and heading fonts.
swingAnglenumber4Swing amplitude, capped at four degrees.
staggerMsnumber80Entrance stagger in milliseconds.
onSelect / onContinue(pet, index) => voidNoneDiscrete JS callbacks.
onInteraction() => voidNoneStops host-driven playback on touch.
styleStyleProp<ViewStyle>NoneHost layout overrides.
testIDstringhanging-banners-welcomeRoot prefix, with -pet-N, -continue, and -back controls.

HangingPet.accessibilityLabel overrides its spoken name. length is clamped to 0.4–0.85 of the hero area. Ref methods: pull(index), replay(), sway(), and continue().

Compatibility

Targets Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, and Worklets 0.13.0. Uses Expo Go's installed modules. No Skia or native custom module is required. Supports iOS, Android, and web.

The root fills its parent. The host screen supplies safe-area insets; the component adds none. Copy stays in a scrollable flow for compact containers, landscape, and larger accessibility fonts. Portraits cap at 256 pt, preserving 3× density for the provided 768 px images. The top-right area contains no text or added controls. For tablet use, a centered phone-width host keeps the welcome composition compact. The full palette is caller-controlled; choose pet backgrounds that contrast with your detail ink.

Accessibility

Pet banners expose button roles, caller-overridable labels, and an activate action. Tapping provides an alternative to dragging. Continue and return buttons are 56 pt high; banner widths are at least 75 pt in the standard 300 pt host. Selection and detail changes announce their content. Hidden welcome/detail regions are removed from the accessibility tree. Font scaling remains enabled.

Reduced motion removes falls, pulls, rotations, and curtain sweeps. Welcome/detail changes use 200 ms fades; pressure feedback stays subtle.