Skip to content
Native Animation
Flavor Wheel Match animation preview

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

npx nativeanimation add flavor-wheel-match
Skia

Flavor Wheel Match

A coffee tasting wheel with a recommendation reveal and configurable product image, recommendation copy, accent color, 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 coffee tasting wheel with a recommendation reveal and configurable product image, recommendation copy, accent color, and fonts.

Why this one

Replace a text questionnaire with a barista’s tasting wheel. A six-axis radar makes your palate visible as you choose. The same wheel becomes a seal on the recommended bag, connecting discovery to the product rather than displaying an unrelated result panel.

How it works

  1. An onLayout measurement sizes a single Skia canvas with six inner families and eighteen outer notes. TextPath follows each segment’s arc.
  2. A pan measures angular movement around the center. Tangential velocity drives withDecay; touching again cancels inertia. A Gesture Handler tap selects a segment independently of pan recognition.
  3. Selection drives shared arrays for wedge extrusion, color saturation, and the spring-driven radar. React updates only on discrete selections.
  4. A small dot travels from the selected segment to its chip. Selecting the third note aligns the circular mean of the notes with the top.
  5. One shared transition shrinks the actual wheel into a product seal and reveals the bag. Two carry-aware digit columns count to the matching percentage.
  6. The demo calls the public ref at 650, 1200, and 1780 ms. The reveal finishes by 2530 ms; the cycle restarts at 5100 ms. Any touch stops playback.

Install

Copy this folder into your app, excluding demo/.

npx expo install @shopify/react-native-skia expo-image react-native-gesture-handler react-native-reanimated react-native-worklets

Tested dependency versions: Skia 2.14.0, expo-image ~58.0.17, Gesture Handler ~3.3.0, Reanimated 4.7.1, worklets 0.13.0. Wrap your application in GestureHandlerRootView. For web, configure CanvasKit loading in the host app and mount this component after Skia has loaded. Pass a bundled font through labelFont for curved text on web. Native falls back to a system font.

Usage

import FlavorWheelMatch from './flavor-wheel-match';

<FlavorWheelMatch
  labelFont={require('./assets/Interface-Regular.ttf')}
  imageSource={require('./assets/coffee.jpg')}
  onAddToBag={() => addCoffeeToCart()}
/>
const wheel = useRef<FlavorWheelMatchRef>(null);

<FlavorWheelMatch
  ref={wheel}
  labelFont={require('./assets/Interface-Regular.ttf')}
  roastName="Mountain Roast"
  description="Sweet, rounded, and bright."
  actionLabel="Add to bag — $18"
  accentColor="#B45309"
  extrusion={10}
  colorScheme="light"
  matchPercent={92}
  onSelectionChange={setFlavorNotes}
  onMatch={showRecommendation}
/>;

wheel.current?.select(6);
wheel.current?.rotate(Math.PI / 3);
wheel.current?.reset();

Props

PropTypeDefaultPurpose
imageSourceImageSource—Local or host-supplied bag artwork
roastNamestringYour roastResult title
descriptionstringA balanced, comforting cup.Tasting copy
actionLabelstringAdd to bagPurchase action
matchPercentnumber92Match score, clamped to 0–99
fontFamilystringsystemInterface font
titleFontFamilystringsystemEditorial result font
monoFontFamilystringsystemCounter font
labelFontDataSourceParamnative systemCurved label font; required on web
accentColorstring#B45309Accent; six-digit hex color
colorSchemelight / dark / autoautoSurface and text theme
extrusionnumber10Selected wedge offset in points
onSelectionChange(notes: string[]) => void—Selection event
onMatch(notes: string[]) => void—Third-note event
onAddToBag() => void—Purchase event
onInteraction() => void—Touch event for playback cancellation
styleStyleProp<ViewStyle>—Root overrides
testIDstring—Test identifier
durationnumber580Match highlight reveal duration in milliseconds. Spring physics and reduced-motion timing are unchanged.
imageSourceImageSourceundefinedBag artwork supplied by the host application.
roastNamestring'Your roast'Recommendation name.
descriptionstring'A balanced, comforting cup.'Recommendation description.
actionLabelstring'Add to bag'Purchase button label.
matchPercentnumber92Final matching percentage.
fontFamilystringundefinedInterface font, with the system font as fallback.
titleFontFamilystringundefinedEditorial headline font.
monoFontFamilystringundefinedNumeric font.
labelFontDataSourceParamundefinedBundled font source for curved Skia labels; required on web.
accentColorstring'#B45309'Warm accent.
colorScheme'light' | 'dark' | 'auto''auto'Theme selection.
extrusionnumber10Selected wedge extrusion in points.
onSelectionChange(notes: string[]) => voidundefinedCalled once per selection change.
onMatch(notes: string[]) => voidundefinedCalled when the third note creates a recommendation.
onAddToBag() => voidundefinedPurchase callback.
onInteraction() => voidundefinedUser interaction callback, used to stop demo playback.
styleStyleProp<ViewStyle>undefinedContainer overrides.
testIDstringundefinedTest identifier.

Ref: select(index), rotate(radians), reset(). FLAVOR_NOTES exports the ordered notes. The fourth selection is ignored until a note is removed. The score and coffee are supplied by the host; this is an interaction component, not a recommendation engine.

Compatibility

Expo SDK 58 / React Native 0.88.0. Compatible with the installed Expo Go stack. The demo includes local artwork and uses the catalog’s loaded fonts; the reusable component has no catalog imports.

Accessibility

Every action has a button role and label. The horizontally scrolling note buttons provide at least 44-point targets for all eighteen notes, including segments too narrow to be accessible touch targets. “Turn wheel” offers a tap alternative to dragging; chips remove selected notes. Important selection and match changes are announced, and selection/result text uses a polite live region. Reduced motion removes dot flights, inertia, rotation alignment, extrusion, and radar springs. The wheel fades out and the result fades in over 200 ms; the match score changes immediately.

Icons: Lucide (ISC). The Ember & Oat demo mark comes from the repository’s brand kit.