Slider
A Slider is a draggable input that allows a user to select an imprecise numerical value within a range.
const DefaultSliderExample = () => {const [value, setValue] = React.useState(0.75);const id = useUID();const numberFormatter = React.useMemo(() => {return new Intl.NumberFormat('en-US');}, []);return (<Form><FormControl><Label htmlFor={id}>Brightness</Label><Sliderid={id}numberFormatter={numberFormatter}value={value}onChange={(newValue) => setValue(newValue)}/></FormControl></Form>);};render(<DefaultSliderExample />)
A Slider allows a user to select a numerical value when:
- Immediate feedback is important.
- The value doesn’t need to be precise, especially when the act of choosing a bigger or smaller value is more important than the value itself.
- The value is in a defined range.
Slider uses Adobe's Spectrum React-Aria useSlider under the hood.
Both Sliders and number Inputs are form fields that take numerical values. Because the mouse and touch interaction on a Slider is less precise, use a Slider when the exact number value isn’t important, for example, when selecting image opacity or audio volume.
If the user needs to select an exact value, use a number Input instead. If you want to let users select between consecutive values, you can also use a Radio Button Group.
Slider is a form element and follows the same accessibility guidelines as other form fields:
- Include a label on all form fields. Use one of 3 ways to label a form field:
- Visible label with Label (preferred)
- Visible label that's associated to the input with
aria-labelledby
- Label directly using
aria-label
- Each label must use the
htmlFor
prop that equals theid
of the associated Input. - Provide clear identification of required fields in the label or at the start of a form.
Use the
required
prop to programmatically indicate they are required to browsers. - Include inline error Help Text on any field that errors to make it visually clear that the field changed.
- If the input has associated help text, include the
aria-describedby
prop on the input. This should match theid
of the help text.
Use a Slider when a user should select an imprecise value from a midsized and defined numerical range, such as 1–100.
const DefaultSliderExample = () => {const [value, setValue] = React.useState(0.75);const id = useUID();const numberFormatter = React.useMemo(() => {return new Intl.NumberFormat('en-US');}, []);return (<Form><FormControl><Label htmlFor={id}>Brightness</Label><Sliderid={id}numberFormatter={numberFormatter}value={value}onChange={(newValue) => setValue(newValue)}/></FormControl></Form>);};render(<DefaultSliderExample />)
Avoid errors on Sliders by changing the defined range so no errors can occur.
If a user is still able to choose an invalid option, change the Slider to its error state and use Help Text to add an inline error. For additional guidance on how to compose error messages, refer to the error state pattern.
const ErrorSliderExample = () => {const [value, setValue] = React.useState(0.2);const id = useUID();const helpTextId = useUID();const numberFormatter = React.useMemo(() => {return new Intl.NumberFormat('en-US', { style: 'percent' });}, []);const hasError = value < 0.3;return (<Form><FormControl><Label required htmlFor={id}>Delivery alerts</Label><SliderhasError={hasError}id={id}aria-describedby={helpTextId}value={value}minValue={0}maxValue={1}step={0.01}onChange={(newValue) => setValue(newValue)}numberFormatter={numberFormatter}/><HelpText id={helpTextId} variant={hasError ? "error" : "default"}>The delivery rate's threshold must be greater than 30%.</HelpText></FormControl></Form>);};render(<ErrorSliderExample />)
Use a disabled Slider to show users that they can't interact with the Slider.
const DisabledSliderExample = () => {const [value, setValue] = React.useState(0.5);const id = useUID();const numberFormatter = React.useMemo(() => {return new Intl.NumberFormat('en-US', { style: 'percent' });}, []);return (<Form><FormControl><Label disabled htmlFor={id}>Volume</Label><Sliderdisabledid={id}value={value}minValue={0}maxValue={1}step={0.01}onChange={(newValue) => setValue(newValue)}numberFormatter={numberFormatter}/></FormControl></Form>);};render(<DisabledSliderExample />)
Use a custom range Slider when the default range doesn't fit your use case.
const CustomRangeSliderExample = () => {const [value, setValue] = React.useState(0.55);const id = useUID();const PercentFormatter = React.useMemo(() => {return new Intl.NumberFormat('en-US', { style: 'percent' });}, []);return (<Form><FormControl><Label htmlFor={id}>Partition size</Label><Sliderid={id}value={value}minValue={0.5}maxValue={0.8}step={0.01}onChange={(newValue) => setValue(newValue)}numberFormatter={PercentFormatter}/></FormControl></Form>);};render(<CustomRangeSliderExample />)
Use a Slider with hidden range labels when the range is obvious or the labels are not needed.
const HiddenRangeLabelsSlider = () => {const [value, setValue] = React.useState(32);const id = useUID();const NumberFormatter = React.useMemo(() => {return new Intl.NumberFormat('en-US');}, []);return (<Form><FormControl><Label htmlFor={id}>Scale</Label><Sliderid={id}value={value}onChange={(newValue) => setValue(newValue)}numberFormatter={NumberFormatter}hideRangeLabels/></FormControl></Form>);};render(<HiddenRangeLabelsSlider />)
Do
Use a Slider for mid-sized, defined ranges, usually 1–100.
Don't
Don’t use a Slider for very large or very small ranges.
Do
Use a number Input when an exact number value matters.
Don't
Don’t use a Slider when an exact number value matters.
Do
Use a Meter when you need to visually show the size of a numerical value, but don’t want the bar to be interactive.
Don't
Don’t use a disabled Slider when the value of the Slider is important to show. Disabled form fields aren’t high-contrast enough to be visible.
Do
Use a Radio Group or Radio Button Group to allow users to select a list of consecutive options with precision, whether they’re numerical or not.
Don't
Don’t use a Slider to allow selection of non-numerical values or when there isn’t a definable range.
yarn add @twilio-paste/core - or - yarn add @twilio-paste/slider
import {Slider} from '@twilio-paste/core/slider';
const Component = () => {
const [value, setValue] = React.useState(10);
const sliderId = useUID();
const helpTextId = useUID(); // optional
const numberFormatter = React.useMemo(() => {
return new Intl.NumberFormat('en-US', {style: 'percent'});
}, []);
return (
<Slider
id={sliderId}
aria-describedby={helpTextId}
value={value}
minValue={0}
maxValue={100}
step={1}
onChange={(newValue) => setValue(newValue)}
numberFormatter={numberFormatter}
/>
);
};
Prop | Type | Description | Default |
---|---|---|---|
id | string | Must provide an id to match with a label | undefined |
numberFormatter | Intl.NumberFormatter | Used to format the value into i18n formats. Can return localized currencies and percentages | |
aria-describedby? | string | Optional id to pair the input to its help text | undefined |
aria-labelledby? | string | Optional id to pair the input to its label text (if not using a regular label with htmlFor ) | undefined |
disabled? | boolean | Disables the slider | false |
hasError? | boolean | Shows error styling on the Slider | false |
hideRangeLabels? | boolean | Hides the min and max values that appear over the slider | false |
minValue? | number | The smallest number in the slider range | 1 |
maxValue? | number | The largest number in the slider range | 100 |
step? | number | The incremented value as you drag along the range | 1 |
value? | number | The current selected value | 1 |
onChange? | (value: number) => void | Fired on every change as the thumb is dragged along the track | |
onChangeEnd? | (value: number) => void | Fired at the end of the dragging event once | |
element? | string | Overrides the default element name to apply unique styles with the Customization Provider | 'SLIDER' |
Changelog
80decbe21
#3478 Thanks @nkrantz! - [Slider] Update designs to reflect generic Paste value bar design with min and max value labels below the visual bar.
733709127
#3395 Thanks @SiTaggart! - Modified the compile target of our JavaScript bundles fromnode
tobrowser
to minimize the risk of clashing with RequireJS. This is marked as a major out of an abundance of caution. You shouldn't need to do anything but we wanted you to be aware of the change on the off chance it has unintended consequences
- Updated dependencies [
733709127
]:- @twilio-paste/uid-library@2.0.0
- @twilio-paste/color-contrast-utils@5.0.0
- @twilio-paste/screen-reader-only@13.0.0
- @twilio-paste/box@10.0.0
- @twilio-paste/customization@8.0.0
- @twilio-paste/design-tokens@10.0.0
- @twilio-paste/icons@12.0.0
- @twilio-paste/animation-library@2.0.0
- @twilio-paste/react-spectrum-library@2.0.0
- @twilio-paste/styling-library@3.0.0
- @twilio-paste/style-props@9.0.0
- @twilio-paste/theme@11.0.0
- @twilio-paste/types@6.0.0
- @twilio-paste/utils@5.0.0
54afe1ce8
#3378 Thanks @TheSisb! - [Slider] add new Slider package. A Slider is a draggable input that allows a user to select an imprecise numerical value within a range.
- Updated dependencies [
c4a70d95b
]:- @twilio-paste/react-spectrum-library@1.0.0