Skip to content
Native Animation
Pinned Section List animation preview

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

npx nativeanimation add pinned-section-list

Pinned Section List

A project list with arcing flights into pinned cards, with configurable projects, section labels, accent color, and font.

$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 project list with arcing flights into pinned cards, with configurable projects, section labels, accent color, and font.

Why this one

A jump between sections can hide where a project went. This version preserves its icon and name throughout the journey, then changes its proportions to fit a compact horizontal shelf. Unpinning returns it to its original order. The landing pin makes the destination explicit.

How it works

  1. Section onLayout measurements locate the shelf and list inside the component, rather than using screen dimensions.
  2. Each project's flight has one UI-thread progress value. Position, size, arc height, and rotation derive from that value. Retargeting captures the current geometry before starting another transition.
  3. React stores discrete membership, names, and menu state. Shared values handle flight, pressure, lift, compacting, and drag without React updates per frame.
  4. Tap and long-press use Gesture Handler composition. Horizontal dragging projects momentum into a reorder destination; menu arrows offer the same action by tap.
  5. The list closes the vacated slot, the shelf expands, and the Lucide pin lands with a restrained spring.
  6. Reduced motion replaces travel and pin motion with a 200 ms fade. Demo timers live outside the component and stop on touch.

Install

npx expo install expo-image react-native-gesture-handler react-native-reanimated react-native-worklets

Use a GestureHandlerRootView at the application root. Icons: Lucide (ISC), copied from the Native Animation kit and rendered with Expo Image. No Skia initialization is required. The demo additionally uses expo-linear-gradient and the catalog's loaded fonts; these are not component dependencies.

Usage

import { PinnedSectionList } from './pinned-section-list';

<PinnedSectionList
  projects={[
    { id: 'plan', name: 'Project plan', color: '#6366F1', icon: 'folder', members: ['AK'] },
  ]}
/>
const projectsRef = useRef<PinnedSectionListRef>(null);

<PinnedSectionList
  ref={projectsRef}
  projects={projects}
  accentColor="#6366F1"
  colorScheme="auto"
  fontFamily="YourLoadedFont"
  flightDuration={560}
  onPinnedChange={(ids) => savePinnedOrder(ids)}
  onRename={(id, name) => saveProjectName(id, name)}
  onArchive={(id) => archiveProject(id)}
/>
// Invoke from an event handler:
projectsRef.current?.toggle('plan');

Props

PropTypeDefaultDescription
projectsProject[]RequiredStable unique IDs, names, colors, optional kit icons, initials, and update labels. Original array order is the return order.
accentColorstring#6366F1Hex accent used for borders and pins.
fontFamilystringSystemA font already loaded by the host app.
pinnedTitlestringPinnedShelf heading.
listTitlestringAll projectsList heading.
emptyLabelstringLong-press to pin a projectEmpty shelf instruction.
colorScheme'light' | 'dark' | 'auto'lightSurface and text treatment.
flightDurationnumber560Pin/unpin travel duration in milliseconds.
onPinnedChange(ids: string[]) => void—Membership and reorder callback.
onRename(id: string, name: string) => void—Committed rename callback.
onArchive(id: string) => void—Archive callback.
onInteraction() => void—Stops an external autoplay controller.
styleStyleProp<ViewStyle>—Root container style.
testIDstring—Root test identifier.

Project fields: id, name, color, optional icon, members, and updated (default Updated 2h ago). Two compact cards fit on the shelf; arrows expose additional pins. Tap any card for unpin, rename, archive, and reorder controls.

Ref methods: toggle(id), open(id), and reset(). Reset restores archived projects and clears pins, preserving names. State is internal; callbacks let the host persist changes.

Compatibility

Targets Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, Worklets 0.13.0, and Gesture Handler 3.3. Expo Go compatible. No native directories or app configuration changes are needed.

Accessibility

Interactive cards and actions have button roles and labels. Tap offers an alternative to long-press and horizontal drag. Actions have at least 44 pt hit areas; full rows are 64 pt tall. Pinning, returning, reordering, renaming, and archiving announce their outcome and update a polite live region. Reduced motion removes arcs, rotation, lift, and pin bounce, and fades membership changes over 200 ms. Content remains scrollable on smaller screens. The demo reserves the upper-right corner for the catalog close control.