About this animation
A portrait-card carousel that turns a vertical editorial title into a full detail header with a measured shared transition.
Why this one
The opening frame is measured on the UI thread, so the image grows from its real on-screen position without a shared-element library. The title rotates from vertical to horizontal, the image uses scroll-linked parallax, and a downward drag reverses the same transition back to the card under your finger.
How it works
- Every card keeps an animated ref and measures itself relative to the component when opened.
- One continuous position value drives horizontal placement, depth, and image parallax.
- A shared open-progress value interpolates the measured card frame into the detail header.
- The title rotates into its horizontal detail position while the information panel rises into view.
- Dragging the detail downward directly rewinds open progress; release velocity decides whether it closes or returns.
- Reduced Motion replaces spatial interpolation and parallax with short fades.
Install
npx expo install expo-image expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-workletsUsage
import { VerticalTitleCards } from './VerticalTitleCards';
<VerticalTitleCards cards={cards} />;With external controls and custom personality:
const cardsRef = useRef<VerticalTitleCardsRef>(null);
<VerticalTitleCards
ref={cardsRef}
cards={cards}
accentColor="#FFD43B"
fontFamily="Geist-Regular"
titleFontFamily="Geist-Medium"
onOpen={(index) => trackOpen(index)}
onClose={() => trackClose()}
/>Call cardsRef.current?.open(2) to center and open a card, or cardsRef.current?.close() to return it to the carousel.
Props
| Name | Type | Default | Description |
|---|---|---|---|
cards | TitleCard[] | Required | Portrait images, titles, and detail rows. |
accentColor | string | '#FFD43B' | Highlight, rail, glow, and control-border color. |
fontFamily | string | System | Labels, values, and controls. |
titleFontFamily | string | System | Large vertical and horizontal titles. |
onOpen | (index: number) => void | — | Fires when a card starts opening. |
onClose | () => void | — | Fires after the detail view closes. |
style | StyleProp<ViewStyle> | — | Outer-container style override. |
testID | string | — | Test identifier for the outer container. |
TitleCard is { image: ImageSourcePropType; title: string; details: { label: string; value: string }[] }.
Compatibility
- Expo SDK 57
- React Native 0.86
- Reanimated 4.5 and Worklets 0.10
- iOS: unverified on device
- Android: unverified on device
- Web: verified by export and bundle
- Works in Expo Go with the SDK-bundled native modules
Accessibility
Cards and controls expose button roles and descriptive labels. The carousel supports adjustable increment and decrement actions, and the close button provides a touch alternative to the downward-dismiss gesture. With Reduce Motion enabled, parallax, title rotation, and frame travel are replaced by short fades.



