Skip to content
Native Animation
Storybook Welcome animation preview

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

npx nativeanimation add storybook-welcome
WelcomeOnboardingSkia

Storybook Welcome

A reading welcome screen with a flowing sky and spring-driven book fan, with configurable illustration, books, colors, 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 reading welcome screen with a flowing sky and spring-driven book fan, with configurable illustration, books, colors, and fonts.

How it works

  1. A local illustration fills the central scene. A small Skia runtime shader displaces its upper region with two slow sine waves while leaving the reader steady.
  2. Forty deterministic stars fade in and twinkle independently. Two short meteors cross each nine-second ambient cycle.
  3. A continuous fan value drives every cover's position, rotation, depth, and scale. Tapping a side cover or dragging selects it with an interruptible spring.
  4. Each authentication letter uses its real Geist 700 advance, measured with Skia, along the arc length of the panel's concave quadratic edge. A trimmed Skia stroke travels under the selected action before its callback fires.
  5. The host can replay the entrance, focus a book, or highlight an action through the imperative handle. No React state updates run per frame.

Install

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

Copy this folder without demo/ into your project. Wrap your app in GestureHandlerRootView. Load the font families passed to the component. On web, initialize CanvasKit before importing the component, following the Skia web setup for your application.

Usage

import { StorybookWelcome } from './storybook-welcome';

<StorybookWelcome
  illustration={require('./assets/reader.jpg')}
  books={[
    { id: 'ember', title: 'The Tiny Ember', cover: require('./assets/ember.jpg') },
    { id: 'pines', title: 'Girls of the Pines', cover: require('./assets/pines.jpg') },
    { id: 'court', title: 'The Moonlit Court', cover: require('./assets/court.jpg') },
  ]}
  bottomInset={insets.bottom}
  topInset={insets.top}
  onSignUp={() => router.push('/sign-up')}
  onOpenBook={(id) => openBook(id)}
/>

Use skyMode="still" for a static scene or skyMode="sway" for a lower-cost ambient alternative. Customize all UI colors with colors, and all copy with labels:

<StorybookWelcome
  illustration={reader}
  books={books}
  skyMode="sway"
  starCount={24}
  fontFamily="Geist_300Light"
  titleFontFamily="Geist_700Bold"
  serifFontFamily="InstrumentSerif_400Regular"
  italicFontFamily="InstrumentSerif_400Regular_Italic"
  colors={{ edge: '#C4BAFF', glow: '#FFFFFF' }}
  labels={{ title: 'Evening Tales', signUp: 'Join Us' }}
/>

Props

PropTypeDefaultPurpose
illustrationImageSourceRequiredLocal reader and sky artwork
booksStorybookBook[]RequiredIDs, titles, covers, optional title colors
labelsPartial<StorybookLabels>English welcome copyAll visible and accessibility copy; openBook supports {title}
colorsPartial<StorybookColors>Indigo and lavenderEvery UI surface, ink, star, shadow, and highlight
colorSchemelight / dark / autodarkLavender surface palette; does not recolor artwork
skyModeflow / sway / stillflow on native and webAmbient rendering cost and appearance
starCountnumber40Additional stars, clamped to 0–80
fontFamilystringGeist_300LightWelcome text
titleFontFamilystringGeist_700BoldHeading, section, curved actions
serifFontFamilystringInstrumentSerif_400RegularCover titles
italicFontFamilystringInstrumentSerif_400Regular_ItalicTagline
monoFontFamilystring—Reserved for host API consistency
bottomInset / topInsetnumber0Host-owned safe area, in points
motionauto / reduced / fullautoOS motion preference or explicit override
onSignIn / onSignUp() => void—Called after 650 ms, or 220 ms in reduced motion
onOpenBook(id: string) => void—Tap on the centered cover
onMenu() => void—Menu action
onInteraction() => void—Stop a host autoplay on user input
autoplaybooleanfalseHost demo flag; sequencing lives in the demo
style / testID / accessibilityLabelCommon propsstorybook-welcome IDContainer and automation

The ref exposes focusBook(index), highlight('signIn' | 'signUp'), and replayIntro(). Highlight invokes the same callback as tapping. A new highlight or replay cancels the preceding pending callback.

Compatibility

Designed for Expo SDK 58, React Native 0.88, Reanimated 4.7, Gesture Handler 3.3, Worklets 0.13, and Skia 2.14. Uses modules bundled in Expo Go on iOS and Android. Web uses the same gestures with CanvasKit and defaults to localized hair flow. Use sway for a lower-cost alternative.

The component measures its container. Tablet and landscape layouts center a phone-width stage; compact layouts retain 48-point action regions. The host supplies safe area insets. Use source images at least three times their displayed dimensions for crisp high-density rendering. The supplied 768-pixel demo illustration is an art-direction sample; production artwork should be at least 1290 pixels wide for a 430-point screen.

Accessibility

Every action has a button role and configurable label. Focused books expose their selected state. Side-cover taps provide an alternative to dragging. The semantic authentication state is exposed as auth none, auth signIn, or auth signUp. Reduced motion freezes the sky and stars, removes meteors and parallax, and replaces large transitions with a 220 ms entrance fade. Curved action containers expose one readable label, while individual decorative letters remain grouped out of the accessibility tree.

Why this one

The hair and the sky read as one illustrated world. A responsive book fan and a light that follows the curved panel edge turn a static welcome composition into a tactile introduction without adding navigation or authentication dependencies.