Skip to content
Native Animation
Permission primer animation preview
OnboardingGlass

Permission primer

An inviting notification onboarding screen: a ringing bell releases realistic previews before the user chooses a reminder time.

$9 for this animation

Checkout opens soon. Leave your email and we will tell you the moment you can buy it.

One email when checkout opens. No spam.

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.

npx nativeanimation add permission-primer

About this animation

An inviting notification onboarding screen: a ringing bell releases realistic previews before the user chooses a reminder time.

Why this one

The bell demonstrates what a reminder feels like instead of showing a static permission icon. Each swing releases a different preview, and users choose their morning time before agreeing. Activation gathers the previews back into the bell and draws a confirmation check. The Aurora demo uses the shared brand kit, not a third-party app identity.

How it works

  1. Measure the component with onLayout; hide the measured composition until its first layout.
  2. Advance one UI-thread introduction timeline from 0 to 3. Three arrivals are spaced 450 ms apart; each card falls from the bell center with a short damped landing and pushes earlier cards down into the stack.
  3. Derive the bell swing from that timeline with a decaying oscillation around its upper anchor. The default intro settles in 1,350 ms.
  4. A separate interruptible outcome spring controls collection, bell color, label removal, and the Lucide check's drawn path. Press feedback uses independent springs.
  5. The time popover grows from the pill and offers three 44-point touch targets. The host owns the system permission call; this component invokes onRequestPermission and immediately presents its optimistic success state.
  6. Reduced motion keeps the bell still and fades previews, outcome, and popover without displacement or scale changes.

Install

Copy this folder without demo/ into your project:

npx expo install react-native-reanimated expo-blur expo-linear-gradient @shopify/react-native-skia

Validated package versions: Reanimated 4.5.1, expo-blur ~57.0.3, expo-linear-gradient ~57.0.2, Skia 2.6.2. React and React Native are supplied by the host. Use the SDK-compatible worklets setup in your app.

For web, load CanvasKit before rendering this component, using your app's Skia web loader / deferred boundary. This folder imports Skia; do not register it as an eager catalog import before CanvasKit is ready. The component contains six small canvases at most, below Chromium's context limit.

Usage

import { PermissionPrimer } from './permission-primer';

export function ReminderStep() {
  return (
    <PermissionPrimer
      onRequestPermission={(hour) => configureReminders(hour)}
    />
  );
}

With content and personality controls:

<PermissionPrimer
  appName="Your app"
  messages={[
    'Take a quiet moment.',
    'Your routine is ready.',
    'A new story awaits.',
  ]}
  gradientColors={['#F472B6', '#8B5CF6']}
  initialHour={8}
  staggerMs={450}
  blurIntensity={50}
  colorScheme="light"
  onRequestPermission={(hour) => configureReminders(hour)}
  onDefer={() => continueOnboarding()}
/>

Load fonts in the host and pass their family names. Without font props the component uses system fonts. The demo uses Geist, Instrument Serif, and Geist Mono; the available shared kit weight is Geist Medium for stronger labels.

Props

PropTypeDefaultPurpose
appNamestringYour appWordmark and notification sender
messagesreadonly [string, string, string]Three neutral remindersPreview arrival order
titlestringStay on track,\nsoftly.Two-line editorial heading
descriptionstringOne reminder a day explanationFrequency and scheduling promise
promisestringGentle reminders, never spamOnboarding eyebrow
enableLabelstringTurn on remindersPrimary action and accessible label
deferLabelstringNot nowSecondary action and accessible label
successLabelstringReminders onSuccess status prefix
deferredLabelstringYour pace, always.Deferred status
gradientColorsreadonly [string, string]Pink / violetApp tile, button, filled bell
initialHour7 | 8 | 98Initial morning reminder hour
onRequestPermission(hour) => void—Host permission integration; no native prompt in demo
onDefer() => void—Skip integration
onStateChange(state) => void—presenting, enabled, or deferred
onHourChange(hour) => void—Selected morning hour
fontFamilystringSystemBody font
mediumFontFamilystringSystemStrong label font
titleFontFamilystringSystemEditorial font
monoFontFamilystringSystemTabular time font
colorSchemelight | dark | autoautoAppearance
timeAccessibilityLabelstringChoose reminder timeHour selector label
staggerMsnumber450Arrival spacing; clamped to at least 250 ms
blurIntensitynumber50Glass intensity
styleStyleProp<ViewStyle>—Root styling
testIDstring—Root identifier

PermissionPrimerRef exposes reset(), enable(), toggleTime(), and selectHour(7 | 8 | 9). Reset restores presenting and replays the intro while preserving the selected hour. The demo's 5.2-second autoplay loop shows arrivals, opens the time selector, then activates. Terminal states prevent duplicate activation; reset starts another interaction.

Compatibility

Expo SDK 57, React Native 0.86.3, Reanimated 4.5.1, Skia 2.6.2. Uses the SDK 57 BlurTargetView / blurTarget API with dimezisBlurViewSdk31Plus on Android. Older Android versions use its supported fallback. Expo Go includes the installed native modules; a copied host needs SDK-compatible dependencies and worklets configuration.

Typecheck, lint, exports, and native bundle checks are build validation. iOS, Android, and web visual behavior and touch behavior remain unverified until the owner reviews the demo. No Chromium recording was performed.

Accessibility

Buttons announce their purpose and disabled state. The time pill announces its current value and expansion; choices announce selection. Hidden options reject touches and are excluded from the accessibility tree. Results use a polite live region. All controls are at least 44 points tall. There are no gesture-only actions. Reduced motion removes swings, falls, collection movement, scaling, and bounce while retaining short fades.

The full heading and explanation remain in normal flow and can expand with text scaling. The designed phone sizes are 390×844 and 320×694; larger accessibility text or longer custom copy should be reviewed by the host in its container.

Icons: Lucide (ISC), copied from docs/kit/lucide-paths.json. Aurora's demo colors and sparkles tile come from docs/kit/marcas.json.