@neo4j-ndl/react
Version:
React implementation of Neo4j Design System
309 lines (252 loc) • 7.7 kB
Markdown
Import: `import { Slider } from '@neo4j-ndl/react'`
| 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;
```
```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;
```
```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;
```
```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;
```
```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;
```
```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;
```
```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;
```
```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));
}
},
[],
);
const handleSliderChange = useCallback(
(newValue: number) => {
setValue(newValue);
setInputValue(String(newValue));
},
[],
);
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;
```