Welcome screen

ProReact Native · Expo

A complete first-run welcome: an onboarding pager with parallax pages and a worm page dot, where each page's art plays as it settles (a weekly ring fills, a distance chart draws, a group of runners fans out), Get started and a Sign in link.

View as Markdown
Try it on your phone
Scan to open this demo in your phone's browser and use it with your fingers.

Installation

$ npx shadcn@latest add @goodui-native-pro/welcome-screen

Then run npx expo install --fix so dependencies match your Expo SDK. Files land in components/goodui-native/welcome-screen.

Pro screens install from the license-gated @goodui-native-pro registry. Setup: Pro access.

Usage

// app/welcome.tsx
import { router } from "expo-router";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { WelcomeScreen } from "@/components/goodui-native/welcome-screen/welcome-screen";

export default function WelcomeRoute() {
  return (
    <WelcomeScreen
      appName="Stride"
      onGetStarted={async () => {
        await AsyncStorage.setItem("seen-welcome", "1");
        router.replace("/sign-up");
      }}
      onSignIn={() => router.push("/sign-in")}
    />
  );
}

When to use

Use it for
  • The first screen a new install sees, before sign-up: three or four pages of value, then Get started.
  • When returning people need a clear way to sign in from the same screen.
Reach for something else
  • Pointing at controls inside the app after sign-in: use coach-mark.
  • A single splash with one message: a plain screen with a button is enough.
  • A pager inside another layout: use page-dots-onboarding directly.

Examples

Your own pages

import { Image } from "react-native";

<WelcomeScreen
  appName="Fernway"
  pages={[
    { key: "trips", title: "Plan trips together", description: "One itinerary everyone can edit.", illustration: <Image source={tripsArt} style={{ width: 220, height: 220 }} /> },
    { key: "split", title: "Split costs fairly", description: "Add a receipt and it is shared by who was there." },
    { key: "offline", title: "Works offline", description: "Maps and bookings stay on your phone." },
  ]}
  onGetStarted={finish}
  onSignIn={signIn}
/>

Photos for the default runners

<WelcomeScreen people={[{ name: "Maya Patel", source: mayaPhoto }, { name: "Leo Martins", source: leoPhoto }, { name: "Aiko Tanaka" }]} onGetStarted={finish} />

API reference

PropTypeDefault
appName
Product name, shown at the top left and in the footer copy.
string"Stride"
pages
Your own pages (two to six). Omit to get three running-app pages whose art plays as each page settles: a ring fills, a chart draws, a group of runners fans out.
OnboardingPage[]—
people
People for the default third page's avatar group. Names alone give colored initials; add `source` for photos.
AvatarGroupPerson[]RUNNERS
onGetStarted
The last page's Get started button. Return a promise (for example saving a "seen onboarding" flag) to show a spinner.
() => unknown—
onSignIn
"Sign in" link under the pager, for people who already have an account. Hidden when omitted.
() => void—
onSkip
Skip at the top. Defaults to jumping to the last page; pass `onGetStarted` to leave right away.
() => void—
labels
Localized pager labels.
{ next?: string; done?: string; skip?: string }—
style
Style for the outer container.
StyleProp<ViewStyle>—
testID
Identifier for end-to-end tests.
string—

Motion and haptics

  • Pages follow the finger with parallax, the worm dot stretches between dots and Next grows into Get started (from page-dots-onboarding).
  • Each default page's art plays when its page settles: the progress ring fills to 72 %, the sparkline morphs from flat into eight rising weeks, and the avatar stack fans out on the smooth spring. Leaving a page resets its art, so coming back plays it again.
  • Reduced motion: the pager jumps between pages and the art changes in place without travel.
  • Haptic: select when a page settles and tap on Next, Get started and Skip (from page-dots-onboarding). The art plays no haptics.
  • All pages stay mounted; the art is SVG and views. Only the settled index re-renders the page list.

Accessibility

  • The page dots are one adjustable element named 'Welcome to {appName}': swipe up or down on them with VoiceOver or TalkBack, or use the arrow keys on the web (from page-dots-onboarding). Page content, including its buttons, stays outside it.
  • The default art is labelled: the ring as 'Weekly goal, 18 of 25 kilometers', the chart with its range; the avatar group reads its names.
  • The app name at the top is plain text; Sign in is a link with a 44 pt touch target from hitSlop.

Notes for AI

  • Pass onGetStarted (may return a promise) and onSignIn; navigate inside them.
  • pages replaces the default running-app pages entirely; each page needs key and title, optional description and illustration.
  • people only feeds the default third page. Images come in through props; the component bundles none.
  • Render it as the whole route with the header hidden; it handles safe areas itself.