Skip to content
Native Animation
Liquid Value Slider animation preview

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

npx nativeanimation add liquid-value-slider
SliderSkia

Liquid Value Slider

React Native Slider with a Liquid Value Vessel

A value slider with a motion-responsive liquid surface and rolling readout, with configurable bounds, liquid colors, 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

This React Native slider selects a numeric value through a vertical liquid vessel. One shared progress controls the fill, grip, and value position, while a damped response bends the meniscus against drag velocity. Releasing snaps to a step; track taps and separate adjustment buttons provide alternatives to dragging. The host controls the range, formatting, and accepted value, with callbacks for selected steps and successful commits. Use it for a savings target, intensity, or another value that benefits from a large liquid display. It uses Skia rather than a stock platform slider; read the published README for layout space and CanvasKit setup on web.

When to use it

  • Set a savings target.
  • Choose a bounded intensity.
  • Display units beside a numeric input.

Related guides

A value slider with a motion-responsive liquid surface and rolling readout, with configurable bounds, liquid colors, and fonts.

How it works

  1. A single continuous shared progress value drives the fill, grip, and value position. React only receives selected steps for formatting and accessibility, never fluid animation frames.
  2. A UI-thread frame callback measures progress velocity. A damped fluid response (mass 1, stiffness 180, damping 27) turns that velocity into bounded cubic meniscus curvature.
  3. Skia clips the liquid gradient and surface light inside a rounded vessel. Highlights and two shadows give the vessel depth without opaque overlays on text.
  4. Dragging cancels the active progress spring. Release snaps to the nearest step with explicit mass and gesture velocity; the fluid settles even during a pause in the drag.
  5. Taps and adjustment buttons select a value without dragging. External value changes and ref.setValue() use the same fluid response; they do not emit change callbacks.

Install

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

Wrap your app in GestureHandlerRootView. Configure Reanimated/Worklets for your Expo SDK. On web, load CanvasKit before mounting this component using Skia's supported web initialization. The catalog demo already does this.

Usage

import { LiquidValueSlider } from './liquid-value-slider';

<View style={{ height: 440 }}>
  <LiquidValueSlider defaultValue={50} showTicks />
</View>
<LiquidValueSlider
  min={0}
  max={1000}
  step={25}
  defaultValue={200}
  format={(value) => `$${value.toLocaleString('en-US')}`}
  unitLabel="set aside each month"
  colorScheme="dark"
  colors={['#246448', '#A8F3C9']}
  waveAmplitude={22}
  accessibilityLabel="Monthly savings amount"
  onChange={saveDraft}
  onChangeEnd={commitSavings}
/>

The component uses the host's available width (onLayout). It stretches vertically with flex: 1; use style={{ flexGrow: 0, flexShrink: 0, flexBasis: 'auto' }} for intrinsic height. The host owns safe areas and should provide scrolling for enlarged text or long custom formats. The value, vessel, scale, endpoint labels, and buttons occupy separate flow rows. The vessel adapts to width (144–380 points tall), or accepts vesselHeight (104–420 points). Reserve the vessel height plus about 220 points with a unit label and marks; allow scrolling when that exceeds the available space. The demo uses a scrollable, width-limited product screen for phones, tablets, landscape, and embedded containers.

Props

PropTypeDefaultDescription
min, max, stepnumber0, 100, 1Numeric range and interval. Invalid ranges/steps receive safe defaults.
valuenumber—External value; user changes are requested through callbacks.
defaultValuenumber50Initial uncontrolled value.
onChange(value: number) => void—Each changed step during a drag; requested target for taps/buttons.
onChangeEnd(value: number) => void—Once after a successful gesture or button/accessibility adjustment. Canceled drags do not commit.
format(value: number) => stringStringLarge value and endpoints; may include currency or units.
unitLabelstring''Optional secondary line under the value.
colors[string, string]['#237B69', '#85F3C4']Liquid gradient and surface light.
showTicksbooleanfalseScale capped at 21 evenly spaced marks. Dense ranges use reference marks rather than every step.
vesselHeightnumberWidth-basedVessel height in points, clamped to 104–420.
waveAmplitudenumber22Maximum dynamic curvature; bounded to 0–28 points.
colorScheme'light' | 'dark' | 'auto''auto'Complete light/dark appearance.
trackColorstringThemeEmpty vessel.
textColor, mutedColorstringThemeMain and secondary text.
borderColor, controlColorstringThemeRim/borders and adjustment surfaces.
fontFamily, labelFontFamilystringSystemValue and supporting fonts.
accessibilityLabelstring'Value'Adjustable control name.
decreaseLabel, increaseLabelstring'Decrease value', 'Increase value'Button names.
styleStyleProp<ViewStyle>—Container styling.
testIDstring—Root ID; -track, -decrease, and -increase suffixes identify controls.

The forwarded LiquidValueSliderRef exposes setValue(value) (silent), increment(), and decrement() (user callbacks). Values are clamped and quantized. Endcaps reserve room for the grip at both range limits.

Compatibility

Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, Worklets 0.13.0, Gesture Handler 3.3, and Skia 2.14.0. Uses the installed Expo Go modules; no added native dependency. Web requires CanvasKit initialization.

Accessibility

The vessel exposes accessibilityRole="adjustable", numeric bounds, the formatted current value, and increment/decrement actions. Separate 48×48 buttons and track taps offer alternatives to dragging. Reduced Motion updates progress immediately, disables fluid deformation and value translation, and retains a gently curved static meniscus. Font scaling is enabled; values and endpoint labels can wrap.

FAQ

Is this a horizontal slider?
The published component uses a vertical liquid vessel. The slider guide builds a horizontal rail; choose the geometry that fits your screen.
Can the host control the selected value?
Yes. Supply value with onChange, or defaultValue for local state. min, max, step, format, and onChangeEnd configure the range and commit behavior.
Can someone select a value without dragging?
Yes. Track taps, separate adjustment buttons, and screen-reader increment/decrement actions provide alternatives. Reduced Motion disables fluid deformation and value travel.