About this animation
A profile with an animated character sticker, achievement coins, and liftable friends, with configurable artwork, badges, palette, and fonts.
Why this one
The character is an alpha-shaped sticker with a six-point outline, rather than a rectangular image card. Achievements have moving light inside their hexagonal material. Inviting a friend turns a static social list into a physical, interruptible interaction with an equally useful tap alternative. Northwind is the demo wordmark from the shared brand kit. Icons: Lucide (ISC).
How it works
onLayoutmeasures the host; content uses a centered, bounded column and scrolls in short containers or landscape.- Skia dilates the character's alpha, recolors it, and paints a soft silhouette shadow underneath the original artwork.
- A shared entrance progress drives staggered coin drops, Y-axis projections, number rotations, and light clipped to each hexagon. All badges share one canvas.
- Digit columns derive their carry from a single counter progress. Digits settle at integers; commas have separate six-point widths.
- One persistent opaque card per friend travels between measured row and crew positions. Exclusive pan and tap gestures share the same spring flight. The empty prompt hides during overlap while the crew label stays visible. Card and chip content crossfade using the dimension morph's progress: card content stays opaque until chip content reaches 0.6. The chip retains both initials and optional sticker artwork, and the other cards close the gap with springs. Tapping a member reverses the flight.
- The demo reveals achievements, selects the gold badge at 1.4 seconds, and lifts Riley at 2.4 seconds. After the chip settles, it waits exactly 1.5 seconds and returns Riley to the original row position, then repeats. Touch stops autoplay. Reduced motion uses immediate membership changes without flight, breathing, jumps, coin flips, or light sweeps.
Install
npx expo install @shopify/react-native-skia expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-workletsCopy this folder without demo/. Place the host beneath GestureHandlerRootView, configure Reanimated/Worklets for your Expo project, and load your fonts before showing the component. On web, initialize Skia/CanvasKit before importing the component (Expo's lazy withSkia setup works). Demo assets are optional and are not imported by the reusable component.
Usage
import { StickerProfileBadges } from './sticker-profile-badges';
<StickerProfileBadges
character={require('./explorer.webp')}
name="Sam"
stats={[{ id: 'days', icon: 'flame', value: 417, label: 'days' }]}
badges={[{ id: 'year', icon: 'mountain', number: 365, color: '#2796ED', name: 'Year streak' }]}
friends={[{ id: 'riley', name: 'Riley Park', initials: 'RP' }]}
onAddFriend={(id) => inviteFriend(id)}
/>const profile = useRef<StickerProfileBadgesRef>(null);
<StickerProfileBadges
ref={profile}
character={character}
name={name}
stats={stats}
badges={badges}
friends={friends}
duration={620}
breathingAmplitude={0.012}
outlineWidth={5}
palette={{ sky: '#152C50', ground: '#0D192B', ink: '#F3F7FF', muted: '#B9C9E6', surface: '#213753', border: '#405B7C', accent: '#9EBFFF' }}
/>;
// Event handlers may call profile.current?.replayBadges() or addFriend('riley').Props
| Prop | Type | Default | Purpose |
|---|---|---|---|
character, name | DataSourceParam, string | Required | Transparent artwork and profile name |
stats | ProfileStat[] | Required | Kit icon, optional integer, and unit or rank label |
badges | ProfileBadge[] | Required | ID, kit icon, integer, color, achievement name |
friends | ProfileFriend[] | Required | ID, name, initials, optional character and avatar color |
following, followers | number | 22, 14 | Animated social metrics |
onAddFriend | (id: string) => void | — | Called once when the chip settles; removal and reset clear local membership |
onInteraction | () => void | — | Host autoplay cancellation |
onBack, onEdit | () => void | — | Optional navigation controls |
palette | Partial<ProfilePalette> | Sky blue/light | Complete surface, ink, border, accent, sticker colors |
labels | Partial<ProfileLabels> | American English | Structural copy and accessible action labels |
brand | string | Profile | Host wordmark |
fontFamily, displayFontFamily, monoFontFamily | string | System | Interface, heavy headline, and tabular fonts |
duration | number | 580 | Coin entrance/spin duration in ms |
outlineWidth | number | 6 | Alpha dilation radius in points |
breathingAmplitude | number | 0.02 | Maximum idle scale increment |
style, testID | StyleProp<ViewStyle>, string | —, sticker-profile-badges | Host layout and stable control IDs |
Ref methods: replayBadges(), spinBadge(id), addFriend(id), removeFriend(id), and reset(). Imperative invitation scrolls the crew into view when needed. Three badges and three friends are the intended phone composition.
Compatibility
Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, Worklets 0.13.0, Gesture Handler 3.3, and Skia 2.14.0. The embedded root fills its host; the host owns safe areas. A 52-point top gutter reserves the catalog viewer corner. Small containers use scroll; tablet content stays at a maximum width of 430 points. Character imagery stays below 240 points, within the supplied artwork's 3× density.
Accessibility
Buttons and invitation cards expose roles, labels, activation actions, and stable test IDs. Tap or screen-reader activation replaces drag. Duplicate additions are ignored and membership is announced. Achievement selection announces its name. Reduced motion removes ambient movement, displacement, spins, and sweeps; membership changes immediately, while coins fade over 200 ms. Text scaling remains enabled.
Implementation notes
Copy uses flow layout and at least 1.1× headline line height. The edit control ends 56 points before the column edge and starts below the viewer's top corner. The 390×844 and 320×568 layouts use scroll rather than shrinking touch areas; a 300×400 host also scrolls. The first coin sweep completes in the first second of autoplay. Highlights are Skia shaders clipped inside the hexagonal material, never opaque overlay blocks. The crew reserves measured card/chip heights and separates placeholder, card, and chip copy visibility.




