Interactive slider components displayed on a futuristic interface with holographic data visualizations

React Compound Slider: Crafting Seamless Sliding Experiences

The Orange Cat
The Orange Cat

React Compound Slider is a powerful and flexible library that allows developers to create customizable slider components in React applications. It provides a set of low-level components that can be composed to build complex slider interfaces with multiple handles, custom styles, and various interaction modes. Whether you’re building a simple range selector or a sophisticated multi-handle slider, React Compound Slider offers the tools to bring your vision to life.

Key Features

React Compound Slider comes packed with a variety of features that make it stand out:

  • Compound Component API: Leverages React’s composition model for ultimate flexibility.
  • Multiple Handles: Support for sliders with any number of handles.
  • Custom Styles: Full control over the appearance of your sliders.
  • Keyboard Accessibility: Built-in keyboard navigation for improved usability.
  • Touch Support: Seamless interaction on touch devices.
  • Vertical and Horizontal Orientations: Create sliders in both directions.
  • Customizable Step Sizes: Define precise increments for value changes.
  • React Hooks Support: Modern API for easier integration with functional components.

Getting Started

To begin using React Compound Slider in your project, you’ll need to install it first. You can do this using either npm or yarn.

Using npm:

npm install react-compound-slider

Using yarn:

yarn add react-compound-slider

Basic Usage

Let’s start with a simple example to demonstrate how to create a basic slider using React Compound Slider.

Creating a Simple Slider

Here’s how you can create a basic horizontal slider:

import React from 'react';
import { Slider, Rail, Handles, Tracks } from 'react-compound-slider';

const SimpleSlider: React.FC = () => {
  const sliderStyle: React.CSSProperties = {
    position: 'relative',
    width: '100%',
    height: 80,
  };

  const railStyle: React.CSSProperties = {
    position: 'absolute',
    width: '100%',
    height: 10,
    marginTop: 35,
    borderRadius: 5,
    backgroundColor: '#8B9CB6',
  };

  return (
    <Slider
      rootStyle={sliderStyle}
      domain={[0, 100]}
      values={[50]}
    >
      <Rail>
        {({ getRailProps }) => (
          <div style={railStyle} {...getRailProps()} />
        )}
      </Rail>
      <Handles>
        {({ handles, getHandleProps }) => (
          <div className="slider-handles">
            {handles.map(({ id, value, percent }) => (
              <div
                key={id}
                style={{
                  position: 'absolute',
                  marginLeft: -15,
                  marginTop: 25,
                  zIndex: 2,
                  width: 30,
                  height: 30,
                  border: 0,
                  textAlign: 'center',
                  cursor: 'pointer',
                  borderRadius: '50%',
                  backgroundColor: '#2C4870',
                  color: '#fff',
                  left: `${percent}%`,
                }}
                {...getHandleProps(id)}
              >
                <div style={{ fontFamily: 'Roboto', fontSize: 11, marginTop: -35 }}>
                  {value}
                </div>
              </div>
            ))}
          </div>
        )}
      </Handles>
      <Tracks right={false}>
        {({ tracks, getTrackProps }) => (
          <div className="slider-tracks">
            {tracks.map(({ id, source, target }) => (
              <div
                key={id}
                style={{
                  position: 'absolute',
                  height: 10,
                  zIndex: 1,
                  marginTop: 35,
                  backgroundColor: '#546C91',
                  borderRadius: 5,
                  cursor: 'pointer',
                  left: `${source.percent}%`,
                  width: `${target.percent - source.percent}%`,
                }}
                {...getTrackProps()}
              />
            ))}
          </div>
        )}
      </Tracks>
    </Slider>
  );
};

export default SimpleSlider;

This example creates a horizontal slider with a single handle. The Slider component wraps the entire slider structure. The Rail component represents the full length of the slider, while Handles creates the draggable handle. The Tracks component fills the area between the start of the slider and the current handle position.

Advanced Usage

Now that we’ve covered the basics, let’s explore some more advanced features of React Compound Slider.

Multi-Handle Slider

Creating a slider with multiple handles is straightforward with React Compound Slider. Here’s an example of a range slider with two handles:

import React from 'react';
import { Slider, Rail, Handles, Tracks, Ticks } from 'react-compound-slider';

const MultiHandleSlider: React.FC = () => {
  const sliderStyle: React.CSSProperties = {
    position: 'relative',
    width: '100%',
    height: 80,
  };

  const railStyle: React.CSSProperties = {
    position: 'absolute',
    width: '100%',
    height: 10,
    marginTop: 35,
    borderRadius: 5,
    backgroundColor: '#8B9CB6',
  };

  return (
    <Slider
      rootStyle={sliderStyle}
      domain={[0, 100]}
      values={[20, 60]}
      step={1}
      mode={2}
    >
      <Rail>
        {({ getRailProps }) => (
          <div style={railStyle} {...getRailProps()} />
        )}
      </Rail>
      <Handles>
        {({ handles, getHandleProps }) => (
          <div className="slider-handles">
            {handles.map(({ id, value, percent }) => (
              <div
                key={id}
                style={{
                  position: 'absolute',
                  marginLeft: -15,
                  marginTop: 25,
                  zIndex: 2,
                  width: 30,
                  height: 30,
                  border: 0,
                  textAlign: 'center',
                  cursor: 'pointer',
                  borderRadius: '50%',
                  backgroundColor: '#2C4870',
                  color: '#fff',
                  left: `${percent}%`,
                }}
                {...getHandleProps(id)}
              >
                <div style={{ fontFamily: 'Roboto', fontSize: 11, marginTop: -35 }}>
                  {value}
                </div>
              </div>
            ))}
          </div>
        )}
      </Handles>
      <Tracks left={false} right={false}>
        {({ tracks, getTrackProps }) => (
          <div className="slider-tracks">
            {tracks.map(({ id, source, target }) => (
              <div
                key={id}
                style={{
                  position: 'absolute',
                  height: 10,
                  zIndex: 1,
                  marginTop: 35,
                  backgroundColor: '#546C91',
                  borderRadius: 5,
                  cursor: 'pointer',
                  left: `${source.percent}%`,
                  width: `${target.percent - source.percent}%`,
                }}
                {...getTrackProps()}
              />
            ))}
          </div>
        )}
      </Tracks>
      <Ticks count={5}>
        {({ ticks }) => (
          <div className="slider-ticks">
            {ticks.map(tick => (
              <div
                key={tick.id}
                style={{
                  position: 'absolute',
                  marginTop: 52,
                  marginLeft: -10,
                  width: 20,
                  height: 20,
                  textAlign: 'center',
                  left: `${tick.percent}%`,
                }}
              >
                <div style={{ fontSize: 10, fontFamily: 'Arial' }}>{tick.value}</div>
              </div>
            ))}
          </div>
        )}
      </Ticks>
    </Slider>
  );
};

export default MultiHandleSlider;

In this example, we’ve added a second handle and included tick marks for better visual reference. The mode={2} prop ensures that the handles can cross each other, which is typical for range selectors.

Vertical Slider

React Compound Slider also supports vertical sliders. Here’s how you can create one:

import React from 'react';
import { Slider, Rail, Handles, Tracks } from 'react-compound-slider';

const VerticalSlider: React.FC = () => {
  const sliderStyle: React.CSSProperties = {
    position: 'relative',
    height: '400px',
    width: 80,
  };

  const railStyle: React.CSSProperties = {
    position: 'absolute',
    width: 10,
    height: '100%',
    marginLeft: 35,
    borderRadius: 5,
    backgroundColor: '#8B9CB6',
  };

  return (
    <Slider
      vertical
      rootStyle={sliderStyle}
      domain={[0, 100]}
      values={[50]}
      step={1}
    >
      <Rail>
        {({ getRailProps }) => (
          <div style={railStyle} {...getRailProps()} />
        )}
      </Rail>
      <Handles>
        {({ handles, getHandleProps }) => (
          <div className="slider-handles">
            {handles.map(({ id, value, percent }) => (
              <div
                key={id}
                style={{
                  position: 'absolute',
                  marginLeft: 25,
                  marginTop: -15,
                  zIndex: 2,
                  width: 30,
                  height: 30,
                  border: 0,
                  textAlign: 'center',
                  cursor: 'pointer',
                  borderRadius: '50%',
                  backgroundColor: '#2C4870',
                  color: '#fff',
                  bottom: `${percent}%`,
                }}
                {...getHandleProps(id)}
              >
                <div style={{ fontFamily: 'Roboto', fontSize: 11, marginTop: 35 }}>
                  {value}
                </div>
              </div>
            ))}
          </div>
        )}
      </Handles>
      <Tracks right={false}>
        {({ tracks, getTrackProps }) => (
          <div className="slider-tracks">
            {tracks.map(({ id, source, target }) => (
              <div
                key={id}
                style={{
                  position: 'absolute',
                  width: 10,
                  zIndex: 1,
                  marginLeft: 35,
                  backgroundColor: '#546C91',
                  borderRadius: 5,
                  cursor: 'pointer',
                  bottom: `${source.percent}%`,
                  height: `${target.percent - source.percent}%`,
                }}
                {...getTrackProps()}
              />
            ))}
          </div>
        )}
      </Tracks>
    </Slider>
  );
};

export default VerticalSlider;

The key differences here are the vertical prop on the Slider component and the adjusted styles to accommodate the vertical layout.

Customizing Behavior

React Compound Slider offers various props to customize the behavior of your sliders. Here are some examples:

Step Size

You can control the step size of the slider using the step prop:

<Slider
  domain={[0, 100]}
  values={[50]}
  step={5}
>
  {/* ... */}
</Slider>

This will make the slider move in increments of 5.

Disabled State

To disable a slider, you can use the disabled prop:

<Slider
  domain={[0, 100]}
  values={[50]}
  disabled={true}
>
  {/* ... */}
</Slider>

Custom Handle Rendering

You can customize the appearance of handles by providing your own render function:

<Handles>
  {({ handles, getHandleProps }) => (
    <div className="slider-handles">
      {handles.map(({ id, value, percent }) => (
        <button
          key={id}
          style={{
            position: 'absolute',
            left: `${percent}%`,
            transform: 'translate(-50%, -50%)',
            cursor: 'pointer',
            padding: '5px',
            borderRadius: '50%',
            backgroundColor: '#4CAF50',
            color: 'white',
            border: 'none',
          }}
          {...getHandleProps(id)}
        >
          {value}
        </button>
      ))}
    </div>
  )}
</Handles>

This example renders the handles as circular buttons with the current value displayed inside.

Wrapping Up

React Compound Slider provides a powerful and flexible way to create customizable slider components in React applications. Its compound component structure allows for granular control over every aspect of the slider, from appearance to behavior.

By leveraging the library’s various components like Rail, Handles, Tracks, and Ticks, developers can create sliders that range from simple single-handle implementations to complex multi-handle, multi-track designs. The ability to customize styles, handle rendering, and interaction modes makes it suitable for a wide range of use cases.

Whether you’re building a simple volume control or a complex data range selector, React Compound Slider offers the tools and flexibility to bring your slider designs to life. With its support for both horizontal and vertical orientations, touch devices, and keyboard accessibility, it ensures that your sliders are not only functional but also user-friendly across different platforms and input methods.

As you continue to explore React Compound Slider, you’ll discover even more ways to tailor your sliders to your specific needs,

Comments