Components
Range Slider
BetaA draggable slider for selecting a numeric value within a defined range. Used for price filters, budget selectors, and rating range pickers.
Purpose
The RangeSlider lets users select a value by dragging a thumb along a track — a more spatial and efficient interaction than typing in a number field when the user is exploring a range. Typical travel use cases:
- Price filter — "Max budget: £4,000" on search results
- Star rating filter — "3 stars and above"
- Holiday duration — "Up to 14 nights"
The filled track portion is always Site Teal. The current value displays next to the label in teal. Min/max labels appear at each end of the track.
Usage
Reach for RangeSlider when the user is exploring a continuous range and dragging feels more natural than typing — a budget cap, a duration cutoff, a minimum star rating. When the user needs to enter or adjust a precise, specific number (like traveller count), use CounterInput or a plain Input instead.
RangeSlider typically appears in a search filter panel or sidebar, alongside other filter controls, rather than inside a booking form itself.
Anatomy
- 1Label — Descriptive label on the left of the header row. 14px medium weight.
- 2Value display — Current formatted value on the right of the header row. Teal, semibold. Updates live as thumb moves.
- 3Track background — 6px tall pill track in grey-200. Full width of the container.
- 4Filled track — Teal portion of the track from left edge to thumb position. Updates with thumb.
- 5Thumb — 20×20px white circle with teal border and small shadow. Draggable handle.
- 6Range labels — Min value on the far left, max on the far right. 12px grey-400.
Variants
Default — numeric
With custom format
Use formatValue to display currency, units, or custom suffixes.
Without value label
Set showValue={false} when displaying the value elsewhere (e.g. in a summary line).
Disabled
States
| State | Track fill | Thumb |
|---|---|---|
| Default | Teal | White + teal border |
| Hover (thumb) | Teal | Elevated shadow |
| Focus | Teal | Teal focus ring (2px, 2px offset) |
| Disabled | Grey-300 | Opacity 60%, cursor-not-allowed |
Best practices
Always pair the slider with a label and formatted current value so the user knows exactly what they are adjusting.
'Maximum budget: £4,500' is unambiguous about what value is being set.
Render a RangeSlider without a label in a filter panel.
A slider without a label is impossible to interpret for sighted and screen reader users alike.
Set step to a value that produces clean, meaningful stops (100 for currency, 1 for star ratings).
£100 steps snap to round numbers — more natural for price selection than £37 increments.
Use step=1 on wide price ranges where any specific value is acceptable to the user.
Step of 1 on a £0–15,000 price range creates 15,000 possible stops — too granular.
Set defaultValue near the midpoint or to a sensible starting point for the typical user.
Starting at £3,000 on a 'Max budget' slider covers most Kuoni holidays and saves scrolling.
Always initialise at the minimum value on wide ranges.
Starting at the minimum forces all users to drag from £0 when most want a mid-range value.
Use formatValue to show currency symbols, units, or suffixes alongside the raw number.
'£4,500' is clear. The inline teal label updates as the user drags.
Show raw numeric values without formatting on currency or star-rating sliders.
A raw '4500' with no context reads as a page count or quantity.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| min | number | 0 | Minimum value of the range. Shown at the left end of the track. |
| max | number | 100 | Maximum value. Shown at the right end of the track. |
| step | number | 1 | Increment between selectable values. Use 100 for currency, 1 for ratings. |
| value | number | — | Controlled current value. When set, parent must handle onChange to update it. |
| defaultValue | number | midpoint | Initial value for uncontrolled usage. Defaults to midpoint between min and max. |
| onChange | (value: number, event: Event) => void | — | Called on every change as the thumb moves. |
| disabled | boolean | false | Disables dragging. Track turns grey, opacity 60%. |
| label | string | — | Visible label on the left of the header row. Associated via htmlFor. |
| showValue | boolean | true | Whether to display the current formatted value on the right of the header. |
| formatValue | (value: number) => string | v => String(v) | Custom formatter for the displayed value and aria-valuetext. e.g. (v) => `£${v}`. |
| error | string | — | Validation error message shown below the track. |
| helpText | string | — | Help text below the track. Hidden when error is set. |
| id | string | 'range-slider' | ID for the native input element. Used by the label htmlFor. |
| className | string | — | Additional Tailwind classes on the root container. |
Accessibility
Native input
RangeSlider renders a native <input type="range"> visually overlapping the custom track. The native element handles all keyboard and pointer interactions natively, ensuring compatibility with assistive technologies.
ARIA attributes
<input
type="range"
aria-valuemin={min}
aria-valuemax={max}
aria-valuenow={current}
aria-valuetext={formatValue(current)} // e.g. "£4,500"
/>
aria-valuetext is critical — without it, screen readers announce the raw number. With it, they announce the formatted string: "Maximum price per person, slider, £4,500".
Keyboard interaction
| Key | Action |
|---|---|
Tab | Focus the slider |
| Arrow Left / Arrow Down | Decrease value by one step |
| Arrow Right / Arrow Up | Increase value by one step |
Home | Jump to minimum value |
End | Jump to maximum value |
Page Down | Decrease by 10% of range |
Page Up | Increase by 10% of range |
Focus ring
Focus ring appears on the thumb via focus-visible:ring-2 focus-visible:ring-teal focus-visible:ring-offset-2.
Related components
- CounterInput — better suited to selecting a precise, specific number (e.g. traveller count) rather than exploring a continuous range.
- Input — use when the user needs to type an exact numeric value directly rather than drag to an approximate one.