Skip to content
Native Animation
carouselproductgesturecolor

Color Variant Carousel

A gesture-driven product carousel that synchronizes product imagery, copy, and a full-screen color field.

Free
Get it free with your email

No password and no card: we email you a sign-in link, then the full source is yours.

Add to your project

Copy the component and its assets into your app with the Native Animation CLI.

npx nativeanimation add variant-carousel

About this animation

A gesture-driven product carousel that synchronizes product imagery, copy, and a full-screen color field.

How it works

  1. One Reanimated shared value represents the carousel's continuous position.
  2. Each product image and variant name derives its wrapped distance from that position, so the carousel loops without duplicating data.
  3. Background and foreground colors interpolate between the current and incoming variants.
  4. A horizontal pan updates progress directly on the UI thread and settles with an interruptible spring.
  5. The imperative API uses the same spring path, allowing controls and autoplay to stay outside the component.

Install

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

Mount your app under GestureHandlerRootView as described by React Native Gesture Handler.

Usage

import { VariantCarousel } from './VariantCarousel';

const variants = [
  {
    name: 'Sand',
    image: require('./sand.png'),
    backgroundColor: '#C8B49B',
    brandColor: '#FFF5E8',
    textColor: '#201B17',
    secondaryColor: 'rgba(32,27,23,0.6)',
  },
  {
    name: 'Ocean',
    image: require('./ocean.png'),
    backgroundColor: '#365D73',
    brandColor: '#D7ECF5',
    textColor: '#FFFFFF',
    secondaryColor: 'rgba(255,255,255,0.6)',
  },
];

export function ProductScreen() {
  return <VariantCarousel variants={variants} />;
}

Customize the measured motion and content with knobs:

<VariantCarousel
  actionLabel="Reserve"
  brandName="NORTH"
  onIndexChange={(index) => setSelectedVariant(index)}
  priceLabel="$189.00"
  productSizeRatio={1.15}
  springDamping={24}
  springStiffness={160}
  variants={variants}
/>

Props

NameTypeDefaultDescription
variantsVariantCarouselVariant[]RequiredTwo or more images, names, and color sets.
brandNamestring"NOVA"Oversized brand wordmark.
logoTextstring"n"Short circular logo mark.
specificationsVariantCarouselSpecification[]Generic product factsUp to three product facts.
actionLabelstring"Add to cart"Purchase action text.
priceLabelstring"$249.00"Formatted price text.
nextAccessibilityLabelstring"Next color"Screen-reader name for the next control.
nextAccessibilityHintstring"Shows the next color variant"Screen-reader hint for the next control.
onIndexChange(index: number) => void—Runs after a transition settles.
onGestureStart() => void—Runs when a drag begins.
springDampingnumber20Transition spring damping.
springStiffnessnumber180Transition spring stiffness.
springMassnumber1Transition spring mass.
swipeDistanceThresholdnumber0.22Required drag distance as a width fraction.
swipeVelocityThresholdnumber600Required horizontal fling velocity.
productSizeRationumber1.25Product size as a width fraction.
productHorizontalOffsetnumber0.24Product left offset as a width fraction.
productVerticalOffsetnumber0.03Product top offset as a height fraction.
purchaseBarColorstring"rgba(0,0,0,0.22)"Purchase-bar background color.
purchaseTextColorstring"#FFFFFF"Purchase-bar text color.
brandFontFamilystringSystemBrand and logo font family.
variantFontFamilystringSystemVariant-name font family.
bodyFontFamilystringSystemSpecification-label font family.
emphasisFontFamilystringSystemValues and purchase-label font family.
styleStyleProp<ViewStyle>—Outer container style.
testIDstring—Outer container test identifier.

The forwarded ref exposes goTo(index), next(), and prev().

Compatibility

  • Expo SDK 57, React Native 0.86, Reanimated 4.5, and Worklets 0.10.
  • Web: verified.
  • iOS and Android: bundles verified; physical devices not yet verified.
  • Works in Expo Go because all native dependencies are included in the SDK 57 client.

Accessibility

The next-variant touch target exposes a button role, label, and hint. Dragging is not the only way to advance. When reduced motion is enabled, spatial product and name movement is removed while the selected content and colors still update.

Source code

Free with an account

Sign in with your email to read the full source here, or install it in one command with the CLI.

Get it free