Skip to content

Repository files navigation

Expo Progress Slider

npm version npm downloads license platform

A performant, cross-platform, native progress slider for React Native and Expo. It provides a truly native experience on iOS and Android while offering identical functionality on the Web.

Features

  • Native Performance: Built using SwiftUI (iOS), Jetpack Compose (Android), and HTML5 Canvas (Web).
  • Smooth Dragging: Encapsulated local dragging state prevents slider snapping when bound to async playback timers.
  • Secondary Progress: Native support for secondary progress indicators (e.g., media buffering).
  • Stepped Snapping & Haptics: Snap to step increments with native haptic feedback on gesture interaction.
  • Accessible: Full native screen reader support (VoiceOver, TalkBack) and Web ARIA attributes.

Installation

npx expo install expo-progress-slider

Usage

import React, { useState } from "react";
import { View, Text, StyleSheet } from "react-native";
import { ProgressSlider } from "expo-progress-slider";

export default function App() {
  const [progress, setProgress] = useState(0.25);

  return (
    <View style={styles.container}>
      <Text>Progress: {progress.toFixed(2)}</Text>

      <ProgressSlider
        value={progress}
        minimumValue={0}
        maximumValue={1}
        step={0.05} // Optional snapping
        secondaryValue={0.5} // Optional buffered progress indicator
        color="#3498db" // Thumb and active track
        secondaryColor="#2980b9" // Buffered track
        backgroundColor="#bdc3c7" // Inactive track
        onValueChange={(val) => setProgress(val)}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    padding: 20,
  },
});

Media Player Integration

Because callbacks deliver raw numbers and dragging state is encapsulated, integrating with media players (like react-native-track-player or expo-audio) is completely smooth without needing extra local state:

<ProgressSlider
  value={position}
  maximumValue={duration}
  secondaryValue={bufferedPosition}
  onValueChange={(val) => TrackPlayer.seekTo(val)}
/>

API Reference

Props

Prop Type Default Description
value number Required The current value of the slider. The slider is a controlled component, meaning it won't update its internal playback state unless this prop is updated.
maximumValue number Required The maximum allowable value.
minimumValue number 0 The minimum allowable value.
secondaryValue number 0 The value of a secondary progress indicator, typically used to show buffering or background progress.
step number 0 The step interval. If > 0, the slider will snap to multiples of this value and emit haptic feedback (iOS/Android) while dragging.
color ColorValue Platform Default The color of the thumb and the primary active track.
secondaryColor ColorValue Platform Default The color of the secondary track indicator.
backgroundColor ColorValue Platform Default The color of the inactive background track.
thumbColor ColorValue Platform Default The color of the thumb. Overrides the thumb color inherited from color.
onSlidingStart (value: number) => void undefined Callback invoked when the user presses down to begin dragging.
onValueChange (value: number) => void undefined Callback invoked continuously as the user drags the slider.
onSlidingComplete (value: number) => void undefined Callback invoked when the user lifts their finger. Use this to sync your final state.

Architecture

This library is built with a deep focus on native performance and smooth interactions:

  • No JS rendering overhead: The UI is completely handled by SwiftUI on iOS, Jetpack Compose on Android, and HTML Canvas on the Web.
  • Strictly controlled component: The public API is highly predictable; the visual representation always mirrors your React state.
  • Accessible by default: Implements native Slider semantics for screen readers (VoiceOver/TalkBack) and ARIA attributes for Web.
graph LR
    Props[React Props] --> State[Native UI State]
    State --> Core[Platform Renderer]
    Core -.-> Gestures[Native Gesture Handler]
    Gestures -.-> Events[React Callbacks]
Loading

License

MIT © Lakhindar Pal