All Projects → tajo → React Range

tajo / React Range

Licence: mit
🎚️Range input with a slider. Accessible. Bring your own styles and markup.

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to React Range

Vue Infinite Slide Bar
∞ Infinite slide bar component (no dependency and light weight 1.48 KB)
Stars: ✭ 190 (-65.14%)
Mutual labels:  component, slider
Vue Draggable Resizable Gorkys
Vue 用于可调整大小和可拖动元素的组件并支持冲突检测、元素吸附、元素对齐、辅助线
Stars: ✭ 521 (-4.4%)
Mutual labels:  component, draggable
Vuetify Daterange Picker
The missing date range picker for Vuetify JS you have been looking for.
Stars: ✭ 192 (-64.77%)
Mutual labels:  component, range
Vue3 Draggable Resizable
[Vue3 组件] 用于拖拽调整位置和大小的的组件,同时支持冲突检测,元素吸附对齐,实时参考线。
Stars: ✭ 159 (-70.83%)
Mutual labels:  component, draggable
react-simple-range
🔉 React slider component for inputting a numeric value within a range.
Stars: ✭ 20 (-96.33%)
Mutual labels:  slider, range
Vue Draggable Resizable
Vue2 Component for draggable and resizable elements.
Stars: ✭ 2,431 (+346.06%)
Mutual labels:  component, draggable
TimeRangePicker
A customizable, easy-to-use, and functional circular time range picker library for Android. Use this library to mimic Apple's iOS or Samsung's bedtime picker.
Stars: ✭ 266 (-51.19%)
Mutual labels:  slider, range
Aura.ui
A Library with a lot of Controls for AvaloniaUI
Stars: ✭ 114 (-79.08%)
Mutual labels:  component, slider
AORangeSlider
AORangeSlider is a custom UISlider with two handlers to pick a minimum and a maximum range.
Stars: ✭ 82 (-84.95%)
Mutual labels:  slider, range
range-slider
Customizable slider (range) component for JavaScript with no dependencies
Stars: ✭ 26 (-95.23%)
Mutual labels:  slider, range
Vue Plain Slider
A simple slider component for Vue.js
Stars: ✭ 146 (-73.21%)
Mutual labels:  component, slider
Vue Ydui
A mobile components Library with Vue2.js. 一只基于Vue2.x的移动端组件库。
Stars: ✭ 2,798 (+413.39%)
Mutual labels:  component, slider
Vue Slide Bar
🎢 A Simple Vue Slider Bar Component.
Stars: ✭ 129 (-76.33%)
Mutual labels:  component, slider
React Rnd
🖱 A resizable and draggable component for React.
Stars: ✭ 2,560 (+369.72%)
Mutual labels:  component, draggable
React Spring Slider
A slider component for react
Stars: ✭ 118 (-78.35%)
Mutual labels:  component, slider
Vue Glide
A slider and carousel as vue component on top of the Glide.js
Stars: ✭ 225 (-58.72%)
Mutual labels:  component, slider
Vue Drag Resize
Vue Component for resize and drag elements
Stars: ✭ 1,007 (+84.77%)
Mutual labels:  component, draggable
React Siema
ReactSiema Demo
Stars: ✭ 90 (-83.49%)
Mutual labels:  component, slider
vue-histogram-slider
Range slider with histogram for Vue.js
Stars: ✭ 111 (-79.63%)
Mutual labels:  slider, range
Ngx Slider
Self-contained, mobile friendly slider component for Angular 6+ based on angularjs-slider
Stars: ✭ 258 (-52.66%)
Mutual labels:  component, slider

react-range

npm version npm downloads Build Status size

Labeled Range

Edit react-range

See all the other examples and their source code!

Installation

yarn add react-range

Usage

import * as React from 'react';
import { Range } from 'react-range';

class SuperSimple extends React.Component {
  state = { values: [50] };
  render() {
    return (
      <Range
        step={0.1}
        min={0}
        max={100}
        values={this.state.values}
        onChange={(values) => this.setState({ values })}
        renderTrack={({ props, children }) => (
          <div
            {...props}
            style={{
              ...props.style,
              height: '6px',
              width: '100%',
              backgroundColor: '#ccc'
            }}
          >
            {children}
          </div>
        )}
        renderThumb={({ props }) => (
          <div
            {...props}
            style={{
              ...props.style,
              height: '42px',
              width: '42px',
              backgroundColor: '#999'
            }}
          />
        )}
      />
    );
  }
}

Features

  • Range input supporting vertical and horizontal sliding
  • Unopinionated styling, great for CSS in JS too
  • No wrapping divs or additional markup, bring your own!
  • Accessible, made for keyboards and screen readers
  • Touchable, works on mobile devices
  • Can handle negative and decimal values
  • Stateless and controlled single component
  • Typescript and Flow type definitions
  • No dependencies, less than 5kB (gzipped)
  • Coverage by e2e puppeteer tests
  • RTL support

Keyboard support

  • tab and shift+tab to focus thumbs
  • arrow up or arrow right or k to increase the thumb value by one step
  • arrow down or arrow left or j to decrease the thumb value by one step
  • page up to increase the thumb value by ten steps
  • page down to decrease the thumb value by ten steps

<Range /> props

renderTrack

renderTrack: (params: {
  props: {
    style: React.CSSProperties;
    ref: React.RefObject<any>;
    onMouseDown: (e: React.MouseEvent) => void;
    onTouchStart: (e: React.TouchEvent) => void;
  };
  children: React.ReactNode;
  isDragged: boolean;
  disabled: boolean;
}) => React.ReactNode;

renderTrack prop to define your track (root) element. Your function gets four parameters and should return a React component:

  • props - this needs to be spread over the root track element, it connects mouse and touch events, adds a ref and some necessary styling
  • children - the rendered thumbs, thumb structure should be specified in a different prop - renderThumb
  • isDragged - true if any thumb is being dragged
  • disabled - true if <Range disabled={true} /> is set

The track can be a single narrow div as in the Super simple example; however, it might be better to use at least two nested divs where the outer div is much thicker and has a transparent background and the inner div is narrow, has visible background and is centered. props should be then spread over the outer bigger div. Why to do this? It's nice to keep the onMouseDown and onTouchStart targets bigger since the thumb can be moved also by clicking on the track (in a single thumb scenario).

renderThumb

renderThumb: (params: {
  props: {
    key: number;
    style: React.CSSProperties;
    tabIndex?: number;
    'aria-valuemax': number;
    'aria-valuemin': number;
    'aria-valuenow': number;
    draggable: boolean;
    role: string;
    onKeyDown: (e: React.KeyboardEvent) => void;
    onKeyUp: (e: React.KeyboardEvent) => void;
  };
  value: number;
  index: number;
  isDragged: boolean;
}) => React.ReactNode;

renderThumb prop to define your thumb. Your function gets four parameters and should return a React component:

  • props - it has multiple props that you need to spread over your thumb element
  • value - a number, relative value based on min, max, step and the thumb's position
  • index - the thumb index (order)
  • isDragged - true if the thumb is dragged, great for styling purposes

renderMark (optional)

renderMark?: (params: {
  props: {
    key: string;
    style: React.CSSProperties;
    ref: React.RefObject<any>;
  };
  index: number;
}) => React.ReactNode;

renderMark is an optional prop so you can render an element at each step. See this example. Your function gets 2 parameters and should return a React component:

  • props - this needs to be spread over the root track element, it adds a ref, key and some necessary styling
  • index - index of the mark, might be useful if you want to use different styles for even/odd marks

You can use any dimensions for your marks and react-range will automatically position them at the correct place.

values

values: number[];

An array of numbers. It controls the position of thumbs on the track. values.length equals to the number of rendered thumbs.

onChange

onChange: (values: number[]) => void;

Called when a thumb is moved, provides new values.

onFinalChange

onFinalChange: (values: number[]) => void;

Called when a change is finished (mouse/touch up, or keyup), provides current values. Use this event when you have to make for example ajax request with new values.

min (optional)

min: number;

The range start. Can be decimal or negative. Default is 0.

max (optional)

max: number;

The range end. Can be decimal or negative. Default is 100.

step (optional)

step: number;

The minimal distance between two values. Can be decimal. Default is 1.

allowOverlap (optional)

allowOverlap: boolean;

When there are multiple thumbs on a single track, should they be allowed to overlap? Default is false.

draggableTrack (optional)

draggableTrack: boolean;

When there are multiple thumbs on a single track, should it be possible to drag all thumbs at once? Default is false.

direction (optional)

direction: Direction;

enum Direction {
  Right = 'to right',
  Left = 'to left',
  Down = 'to bottom',
  Up = 'to top'
}

It sets the orientation (vertical vs horizontal) and the direction in which the value increases. You can get this enum by:

import { Direction } from 'react-range';

Default value is Direction.Right.

disabled (optional)

disabled: boolean;

If true, it ignores all touch and mouse events and makes the component not focusable. Default is false.

rtl (optional)

rtl: boolean;

If true, the slider will be optimized for RTL layouts. Default is false.

getTrackBackground

There is an additional helper function being exported from react-range. Your track is most likely a div with some background. What if you want to achieve a nice "progress bar" effect where the part before the thumb has different color than the part after? What if you want to have the same thing even with multiple thumbs (aka differently colored segments)? You don't need to glue together multiple divs in order to do that! You can use a single div and set background: linear-gradient(...). getTrackBackground function builds this verbose linear-gradient(...) for you!

getTrackBackground: (params: {
  min: number;
  max: number;
  values: number[];
  colors: string[];
  direction?: Direction;
  rtl?: boolean;
}) => string;

min, max, values and direction should be same as for the <Range /> component. colors is a list of colors. This needs to be true:

values.length + 1 === colors.length;

That's because one thumb (one value) splits the track into two segments, so you need two colors.

Motivation

There is a native input solution:

<input type="range" />

However, it has some serious shortcomings:

  • vertical-oriented slider is not supported in all browsers
  • supports only a single direction
  • very limited styling options
  • no support for multiple thumbs

There are also many React based solutions but most of them are too bloated, don't support styling through CSS in JS or have lacking performance.

react-range has two main goals:

  • Small footprint - less then 4kB gzipped, single component.
  • Bring your own styles and HTML markup - react-range is a more low-level approach than other libraries. It doesn't come with any styling (except some positioning) or markup. It's up to the user to specify both! Think about react-range as a foundation for other styled input ranges.

End to end testing

This library is tightly coupled to many DOM APIs. It would be very hard to ensure 100% test coverage just with unit tests that would not involve a lot of mocking. Or we could re-architect the library to better abstract all DOM interfaces but that would mean more code and bigger footprint.

Instead of that, react-range adds thorough end to end tests powered by puppeteer.

All tests are automatically ran in Travis CI with headless chromium. This way, the public API is well tested, including pixel-perfect positioning. Also, the tests are pretty fast, reliable and very descriptive.

Do you want to run them in the dev mode (slows down operations, opens the browser)?

yarn ladle serve #start the ladle server
yarn test:e2e:dev #run the e2e tests

CI mode (ladle started on the background, quick, headless)

yarn test:e2e

Browser support

  • Chrome (latest, mac, windows, iOS, Android)
  • Firefox (latest, mac, windows)
  • Safari (latest, mac, iOS)
  • Edge (latest, windows)

Contributing

This is how you can spin up the dev environment:

git clone https://github.com/tajo/react-range
cd react-range
yarn
yarn ladle serve

Shoutouts 🙏

Big big shoutout to Tom MacWright for donating the react-range npm handle! ❤️

BrowserStack Logo

Big thanks to BrowserStack for letting the maintainers use their service to debug browser issues.

And Netlify for free hosting.

Author

Vojtech Miksu 2019, miksu.cz, @vmiksu

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].