Skip to content
Native Animation
Finish Configurator animation preview

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

npx nativeanimation add finish-configurator
Glass

Finish Configurator

A product finish picker with a liquid color reveal and configurable color options, finishes, product copy, and fonts.

$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 product finish picker with a liquid color reveal and configurable color options, finishes, product copy, and fonts.

How it works

  1. A transparent product image supplied through colors is placed in a responsive frame above the controls, with transparent studio margins cropped out.
  2. A single interruptible wave shared value clips the next color from the base upward and drives its white wave edge.
  3. A Gesture Handler pan gives the bottle a restrained false-3D tilt; release springs back with the gesture velocity.
  4. Matte, Gloss, and Metal change restrained vertical reflections confined to the straight bottle body; the price updates from the selected state.
  5. The store header introduces Tidewell, Halo, and the current product price. Pre-rendered color names cross-fade and slide with interruptible springs, without replacing text mid-frame.
  6. The panel is a light glass surface with a sliding swatch ring, a finish segmented control, engraving, and a bag success state.

Install

npx expo install expo-blur expo-image expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets

Supply your own product images through the required, non-empty colors prop; demo artwork is not included in the delivered files.

Usage

import { FinishConfigurator, type FinishConfiguratorColor } from './finish-configurator';

const colors: FinishConfiguratorColor[] = [
  { name: 'Ink', value: '#172A3A', source: require('./assets/product-ink.webp') },
  { name: 'Sage', value: '#8FAF9A', source: require('./assets/product-sage.webp') },
];

<FinishConfigurator colors={colors} />
<FinishConfigurator
  colors={colors}
  initialColor={1}
  initialFinish={2}
  initialEngraving
  fontFamily="Geist_400Regular"
  serifFontFamily="InstrumentSerif_400Regular"
  monoFontFamily="GeistMono_400Regular"
  onAddToBag={() => cart.add('tidewell-halo')}
/>

Load custom fonts in the host app before rendering. Without font props, the component uses the system font. The catalog demo supplies its shared fonts; the component does not import the catalog theme.

Props

PropTypeDefaultDescription
colorsFinishConfiguratorColor[]RequiredNon-empty product color list; each option supplies name, value (swatch color), and source (an expo-image image source or local require()).
finishesFinishConfiguratorFinish[]DEFAULT_FINISHESFinish labels and price adjustments.
brandNamestring'Tidewell'Product brand.
titlestring'Halo bottle'Product title.
productDetailstring'HALO / 24 OZ'Product metadata below the color name.
pricenumber58Base price in dollars.
engravingPricenumber6Engraving surcharge in dollars.
initialColornumber0Initial color swatch.
initialFinishnumber0Initial finish option.
initialEngravingbooleanfalseInitial engraving state.
onColorChange(index: number) => voidundefinedCalled after a color is selected.
onFinishChange(index: number) => voidundefinedCalled after a finish is selected.
onAddToBag() => voidundefinedCalled when the bag action is completed.
autoplaybooleanfalseLets the demo show its opening sequence.
fontFamilystringundefinedInterface font supplied by the host app. Defaults to the system font.
serifFontFamilystringfontFamilyEditorial font supplied by the host app. Defaults to fontFamily.
monoFontFamilystringfontFamilyMonospaced font supplied by the host app. Defaults to fontFamily.
styleStyleProp<ViewStyle>undefinedOptional style for the component root.
accessibilityLabelstring'Product finish configurator'Screen-reader label for the configurator.
testIDstringundefinedOptional test identifier.
durationnumber650Color-wave transition duration in milliseconds. Spring physics and reduced-motion timing are unchanged.

Compatibility

Built for Expo SDK 58, React Native 0.88, Reanimated 4, Worklets 0.13, and Gesture Handler 3. It is designed for iOS, Android, and web.

Accessibility

Color, finish, engraving, and bag controls expose labels, roles, and selected/checked state. Reduced motion removes the bottle turn and liquid wave and commits color changes immediately while preserving the state transition.

Icons: Lucide (ISC), with the selected paths copied to icons.ts.

Why this one

The familiar product configurator pattern becomes a material moment: color fills the bottle like liquid instead of cross-fading, the wave carries a thin line of light, and Metal lets the finish follow the user's finger. The result communicates what changed without turning the UI into decoration.