UNPKG

@neo4j-ndl/react

Version:

React implementation of Neo4j Design System

309 lines (252 loc) 7.7 kB
# Slider Import: `import { Slider } from '@neo4j-ndl/react'` ## Props ### Slider | Prop | Type | Required | Default | Description | |------|------|----------|---------|-------------| | `as` | `ElementType<any, keyof IntrinsicElements>` | | | An override of the default HTML tag of the root of the component. Can also be another React component. | | `inputProps` | `HtmlAttributes<"input">` | | `{}` | Input props of the underlying input element | | `isDisabled` | `boolean` | | `false` | Whether the slider is disabled | | `maxValue` | `number` | | `100` | The maximum value possible to choose | | `minValue` | `number` | | `0` | The minimum value possible to choose | | `onChange` | `((value: number) => void) \| ((value: [number, number]) => void)` | ✅ | | Callback function triggered when the slider value(s) changes. The function parameter varies depending on the slider type, for single slider, it is a number and for range slider, it is an array of two numbers. | | `ref` | `any` | | | A ref to apply to the root element. | | `showSteps` | `boolean` | | `false` | Whether to display visual indicators for each step in the slider | | `showValues` | `boolean` | | `false` | Whether to display a tooltip with the current value when the slider is being dragged | | `step` | `number` | | `1` | Determines the step size that will be added or removed from the current value when moving the slider button | | `type` | `'range' \| 'single'` | | `single` | Type of the slider | | `value` | `number` | ✅ | | Current value of the single slider. **Only required when the type is 'single'**. | | `values` | `[number, number]` | ✅ | | Current values of the range slider as an array of two numbers `[min, max]`. **Only required when the type is 'range'**. | The `type` prop is used to determine the type of the slider. It can be `single` or `range`. The `value` prop is required when the `type` is `single` and `values` is required when the `type` is `range`. It also affects the `onChange` prop type. ## Accessibility ## Implementation guidelines The Slider component is built with full accessibility support using React Aria. It includes proper ARIA attributes, keyboard navigation support, and focus management. Users can interact with the slider using: - **Mouse/Touch**: Click and drag the thumb(s) to adjust values - **Keyboard**: Use arrow keys to increment/decrement values, Home/End keys to jump to min/max values - **Screen Readers**: Proper ARIA labels and value announcements The component supports explicit and custom `aria-valuetext` through the `inputProps` for enhanced screen reader experience. ## Examples ### Default ```tsx import { Slider } from '@neo4j-ndl/react'; const Component = () => { return ( <Slider minValue={0} maxValue={100} value={50} onChange={(newValue) => { console.info('onChange', newValue); }} /> ); }; export default Component; ``` ### Custom Step Length ```tsx import { Slider } from '@neo4j-ndl/react'; const Component = () => { return ( <Slider minValue={0} maxValue={100} step={10} value={50} onChange={(newValue) => { console.info('onChange', newValue); }} showSteps showValues /> ); }; export default Component; ``` ### Disabled ```tsx import { Slider } from '@neo4j-ndl/react'; const Component = () => { return ( <Slider minValue={0} maxValue={100} step={10} value={50} onChange={(newValue) => { console.info('onChange', newValue); }} isDisabled /> ); }; export default Component; ``` ### Range ```tsx import { Slider } from '@neo4j-ndl/react'; const Component = () => { return ( <Slider type="range" values={[10, 50]} onChange={(newValue) => { console.info('onChange', newValue); }} minValue={0} maxValue={200} step={10} isDisabled={false} showSteps={true} showValues={true} /> ); }; export default Component; ``` ### Show Steps ```tsx import { Slider } from '@neo4j-ndl/react'; const Component = () => { return ( <Slider minValue={0} maxValue={100} value={50} onChange={(newValue) => { console.info('onChange', newValue); }} showSteps /> ); }; export default Component; ``` ### Show Values ```tsx import { Slider } from '@neo4j-ndl/react'; const Component = () => { return ( <Slider minValue={0} maxValue={100} value={50} onChange={(newValue) => { console.info('onChange', newValue); }} showValues /> ); }; export default Component; ``` ### Single ```tsx import { Slider } from '@neo4j-ndl/react'; const Component = () => { return ( <Slider type="single" value={100} onChange={(newValue) => { console.info('onChange', newValue); }} minValue={0} maxValue={200} isDisabled={false} step={10} showSteps={true} showValues={true} inputProps={{ 'aria-valuetext': 'percent' }} /> ); }; export default Component; ``` ### Single Controlled ```tsx import { Slider, TextInput } from '@neo4j-ndl/react'; import { useCallback, useState } from 'react'; const MIN_VALUE = 0; const MAX_VALUE = 100; const STEP = 5; const INITIAL_VALUE = 50; const getValidationError = ( input: string, ): { error: string; isValid: false } | { error: undefined; isValid: true } => { const trimmed = input.trim(); if (!trimmed) { return { error: 'Value is required', isValid: false }; } const numValue = Number(trimmed); if (isNaN(numValue)) { return { error: 'Please enter a valid number', isValid: false }; } if (!Number.isInteger(numValue)) { return { error: 'Please enter a whole number', isValid: false }; } if (numValue < MIN_VALUE) { return { error: `Value must be at least ${MIN_VALUE}`, isValid: false }; } if (numValue > MAX_VALUE) { return { error: `Value must be at most ${MAX_VALUE}`, isValid: false }; } return { error: undefined, isValid: true }; }; const Component = () => { const [value, setValue] = useState(INITIAL_VALUE); const [inputValue, setInputValue] = useState(String(INITIAL_VALUE)); const { error, isValid } = getValidationError(inputValue); const hasError = !isValid; const handleInputChange = useCallback( (e: React.ChangeEvent<HTMLInputElement>) => { const newInputValue = e.target.value; setInputValue(newInputValue); if (isValid) { setValue(Number(newInputValue)); } }, [setInputValue, setValue, isValid], ); const handleSliderChange = useCallback( (newValue: number) => { setValue(newValue); setInputValue(String(newValue)); }, [setInputValue, setValue], ); return ( <div className="n-flex n-flex-col n-gap-token-16"> <TextInput label="Slider value" helpText={`Enter a value between ${MIN_VALUE} and ${MAX_VALUE}`} isRequired errorText={error} htmlAttributes={{ max: MAX_VALUE, min: MIN_VALUE, step: STEP, type: 'number', }} value={inputValue} onChange={handleInputChange} /> <Slider type="single" value={value} onChange={handleSliderChange} minValue={MIN_VALUE} maxValue={MAX_VALUE} step={STEP} showSteps showValues isDisabled={hasError} inputProps={{ 'aria-valuetext': `${value} out of ${MAX_VALUE}`, }} /> </div> ); }; export default Component; ```