RangeSlider
Install: npm install @mantine/core@9.7.1 @mantine/hooks@9.7.1
Version and compatibility
Pinned Mantine Core 9.7.1 requires React and React DOM ^19.2.0 and matching @mantine/hooks@9.7.1, from the installed npm package's peerDependencies. Do not force it into React 18 or another incompatible version. Explain upgrade impact and agree on a plan with the project owner; do not hide conflicts with --force/--legacy-peer-deps. The native Provider enables theme.respectReducedMotion and uses forceColorScheme for light/dark.
Use case
Edit a pair of numeric range boundaries.
Native props used by this example
These props are extracted from the local typechecked JSX and grouped by their owning native component. This is not an exhaustive prop list; see pinned source signatures and inheritance below.
| Component prop | Explanation |
|---|---|
RangeSlider.defaultValue | Initial uncontrolled value, not a live controlled update. |
RangeSlider.w | Mantine width style prop. |
Interaction and state checks
Current scenarios: Default. Check actual behavior after selecting supported disabled/error/read-only scenarios; components without those native states do not receive invented universal props. Verify keyboard focus and exits, then connect changed values through the native callback signature.
Business integration boundary
value is a pair, unlike Slider's single number. Label each thumb for assistive technology.
Host setup
Install pinned @mantine/core and @mantine/hooks, import @mantine/core/styles.css at the entry and use MantineProvider. The example's theme/variant are JGuang-authored host props, not universal native component APIs; forceColorScheme synchronizes the app theme. Native implementation source is a reading reference: use npm exports rather than copying internal engines. This batch covers Core, not dates/charts/forms extension packages. Detailed upstream prose remains English.
Runnable usage
import { useState } from 'react';
import * as M from '@mantine/core';
import '@mantine/core/styles.css';
function ComponentPreview({ variant = 'Default' }: { variant?: string }) {
return <M.RangeSlider defaultValue={[20, 70]} w={300} />;
}
export default function Example({ variant = 'Default', theme = 'light' }: { variant?: string; theme?: 'light' | 'dark' }) {
return <M.MantineProvider forceColorScheme={theme} theme={{ respectReducedMotion: true }}><ComponentPreview variant={variant} /></M.MantineProvider>;
}
Preview states
Default
The example uses the native Mantine API. For supported input demos, change the local variant to Disabled, Invalid or Read only; these are example labels, not new component props. Keep the documented data, controlled values, stores and compound children when adapting the example.
Usage
Controlled
import { useState } from 'react';
import { RangeSlider } from '@mantine/core';
function Demo() {
const [value, setValue] = useState<[number, number]>([20, 80]);
return <RangeSlider value={value} onChange={setValue} />;
}
Uncontrolled
RangeSlider can be used with uncontrolled forms the same way as a native input element.
Set the name attribute to include range slider value in FormData object on form submission.
To control the initial value in uncontrolled forms, use the defaultValue prop.
Example usage of uncontrolled RangeSlider with FormData:
import { RangeSlider } from '@mantine/core';
function Demo() {
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
console.log('Range slider value:', formData.get('range'));
}}
>
<RangeSlider
name="range"
defaultValue={[20, 80]}
min={0}
max={100}
/>
<button type="submit">Submit</button>
</form>
);
}
Disabled
Control label
To change the label behavior and appearance, set the following props:
label– formatter function, accepts value as an argument, set to null to disable the label, defaults tof => flabelAlwaysOn– if true, the label will always be displayed; by default the label is visible only when the user is dragginglabelTransitionProps– props passed down to the Transition component, can be used to customize the label animation
Min, max and step
Domain
By default, min and max values define the possible range of values.
The domain prop allows setting the possible range of values independently of the
min and max values:
Decimal values
To use RangeSlider with decimal values, set the min, max, and step props:
minRange
Use the minRange prop to control the minimum range between from and to values
in RangeSlider. The default value is 10. This ensures the thumbs must be at least
the specified distance apart:
maxRange
Use the maxRange prop to control the maximum range between from and to values.
This limits how wide the selection can be. By default, maxRange is set to Infinity:
pushOnOverlap
The pushOnOverlap prop controls whether the thumbs should push each other when they overlap.
By default, pushOnOverlap is true. If you want to disable this behavior, set it to false.
Example of pushOnOverlap={false}:
Marks
Add any number of marks to the slider by setting the marks prop to an array of objects:
const marks = [
{ value: 20 }, // -> displays mark on slider track
{ value: 40, label: '40%' }, // -> adds mark label below slider track
];
Note that mark value is relative to slider value, not width:
Restrict selection to marks
Set restrictToMarks prop to restrict slider value to marks only. Note that in
this case step prop is ignored:
Inverted
You can invert the track with the inverted prop:
Hidden marks
Hidden marks allow you to snap to specific values without displaying them visually on the track.
This is useful when you want to create a "sticky" snapping behavior to certain values that
you don't want to show to the user. Use this feature together with restrictToMarks prop:
Accessibility
RangeSlider component is accessible by default:
- Thumbs are focusable
- When the user uses mouse to interact with the slider, focus is moved to the slider track, when the user presses arrows focus is moved to the thumb
- Value can be changed with arrows with step increment/decrement
To label component for screen readers, add labels to thumbs:
import { RangeSlider } from '@mantine/core';
function Demo() {
return (
<RangeSlider
thumbFromLabel="First thumb aria-label"
thumbToLabel="Second thumb aria-label"
/>
);
}
When scale is used or the displayed value is formatted (for example as a currency or
percentage), set thumbValueText to provide a human-readable value for screen readers.
It is rendered as aria-valuetext on both thumbs. When a function is provided, it receives
the scaled value of the corresponding thumb:
import { RangeSlider } from '@mantine/core';
function Demo() {
return (
<RangeSlider
scale={(v) => v * 10}
thumbValueText={(value) => `${value}%`}
/>
);
}
Keyboard interactions
Source-backed parameter reference
Implementation signatures and types are generated from the pinned local source. Optional props, native inherited types, union branches and never exclusions are preserved. A forwardRef implementation's ref is a React reference, not an additional business prop.
RangeSlider(_props)
export type RangeSliderValue = [number, number];
export interface RangeSliderProps
extends
BoxProps,
StylesApiProps<RangeSliderFactory>,
ElementProps<'div', 'onChange' | 'value' | 'defaultValue'> {
/** Key of `theme.colors` or any valid CSS color, controls color of track and thumb @default theme.primaryColor */
color?: MantineColor;
/** Key of `theme.radius` or any valid CSS value to set `border-radius`, numbers are converted to rem @default 'xl' */
radius?: MantineRadius;
/** Controls size of the track @default 'md' */
size?: MantineSize | (string & {}) | number;
/** Minimal possible value @default 0 */
min?: number;
/** Maximum possible value @default 100 */
max?: number;
/** Domain of the slider, defines the selectable value range independently of min/max. Useful when you want to display a wider track range (min/max) but restrict actual selection to a subset (domain). @default [min, max] */
domain?: [number, number];
/** Number by which value will be incremented/decremented with thumb drag and arrows @default 1 */
step?: number;
/** Number of significant digits after the decimal point */
precision?: number;
/** Controlled component value */
value?: RangeSliderValue;
/** Uncontrolled component default value */
defaultValue?: RangeSliderValue;
/** Called when value changes */
onChange?: (value: RangeSliderValue) => void;
/** Called when user stops dragging slider or changes value with arrows */
onChangeEnd?: (value: RangeSliderValue) => void;
/** Hidden input name, use with uncontrolled component */
name?: string;
/** Marks displayed on the track */
marks?: SliderMark[];
/** Function to generate label or any react node to render instead, set to null to disable label */
label?: React.ReactNode | ((value: number) => React.ReactNode);
/** Props passed down to the `Transition` component @default { transition: 'fade', duration: 0 } */
labelTransitionProps?: TransitionOverride;
/** Determines whether the label should be visible when the slider is not being dragged or hovered @default false */
labelAlwaysOn?: boolean;
/** Determines whether the label should be displayed when the slider is hovered @default true */
showLabelOnHover?: boolean;
/** Content rendered inside thumb */
thumbChildren?: React.ReactNode;
/** Disables slider */
disabled?: boolean;
/** Thumb `width` and `height`, by default value is computed based on `size` prop */
thumbSize?: number | string;
/** A transformation function to change the scale of the slider */
scale?: (value: number) => number;
/** Determines whether track values representation should be inverted @default false */
inverted?: boolean;
/** Slider orientation @default 'horizontal' */
orientation?: 'horizontal' | 'vertical';
/** Minimal range interval between the two thumbs. Consider this value relative to the total range (max - min). @default 10 */
minRange?: number;
/** Maximum range interval @default Infinity */
maxRange?: number;
/** `aria-label` for both thumbs (overridden by thumbFromLabel/thumbToLabel if provided) */
thumbLabel?: string;
/** `aria-valuetext` for both thumbs. When a function is provided, it receives the scaled value. */
thumbValueText?: string | ((value: number) => string);
/** First thumb `aria-label` */
thumbFromLabel?: string;
/** Second thumb `aria-label` */
thumbToLabel?: string;
/** Props passed down to the hidden input */
hiddenInputProps?: React.ComponentProps<'input'>;
/** Determines whether the selection should be only allowed from the given marks array @default false */
restrictToMarks?: boolean;
/** Props passed down to thumb element based on the thumb index */
thumbProps?: (index: 0 | 1) => React.ComponentProps<'div'>;
/** Determines whether the other thumb should be pushed by the current thumb dragging when `minRange`/`maxRange` is reached @default true */
pushOnOverlap?: boolean;
}
export type RangeSliderFactory = Factory<{
props: RangeSliderProps;
ref: HTMLDivElement;
stylesNames: SliderStylesNames;
vars: SliderCssVariables;
}>;
export type Mod = Record<string, any> | string;
export type BoxMod = Mod | Mod[] | BoxMod[];
export interface BoxProps extends MantineStyleProps {
/** Class added to the root element, if applicable */
className?: string | undefined;
/** Inline style added to root component element, can subscribe to theme defined on MantineProvider */
style?: MantineStyleProp;
/** CSS variables defined on root component element */
__vars?: CssVarsProp;
/** `size` property passed down the HTML element */
__size?: string;
/** Breakpoint above which the component is hidden with `display: none` */
hiddenFrom?: MantineBreakpoint;
/** Breakpoint below which the component is hidden with `display: none` */
visibleFrom?: MantineBreakpoint;
/** Determines whether component should be hidden in light color scheme with `display: none` */
lightHidden?: boolean;
/** Determines whether component should be hidden in dark color scheme with `display: none` */
darkHidden?: boolean;
/** Element modifiers transformed into `data-` attributes, for example, `{ 'data-size': 'xl' }`, falsy values are removed */
mod?: BoxMod;
}
export type ElementProps<
ElementType extends React.ElementType,
PropsToOmit extends string = never,
> = Omit<React.ComponentProps<ElementType>, 'style' | PropsToOmit>;
export interface CSSProperties extends React.CSSProperties {
[key: string]: any;
}
type MantineStyle = CSSProperties | ((theme: MantineTheme) => CSSProperties);
export type MantineStyleProp = MantineStyle | MantineStyle[] | MantineStyleProp[] | undefined;
export type CssVariable = `--${string}`;
export type CssVariables<Variable extends string = CssVariable> = Partial<Record<Variable, string>>;
export type CssVars<Variable extends string = CssVariable> =
| CssVariables<Variable>
| ((theme: MantineTheme) => CssVariables<Variable>)
| CssVars<Variable>[];
export type CssVarsProp<Variable extends string = CssVariable> =
| CssVars<Variable>
| CssVars<Variable>[];
Native and external types
External types remain defined by React or native dependencies, not manually expanded into guessed props. The installed version's TypeScript definitions are authoritative.
Factory<{
props: RangeSliderProps;
ref: HTMLDivElement;
stylesNames: SliderStylesNames;
vars: SliderCssVariables;
}>
MantineStyleProps
React.CSSProperties
MantineTheme
Partial<Record<Variable, string>>
Record<Variable, string>
Variable
MantineBreakpoint
Record<string, any>
StylesApiProps<RangeSliderFactory>
React.ElementType
Omit<React.ComponentProps<ElementType>, 'style' | PropsToOmit>
React.ComponentProps<ElementType>
ElementType
PropsToOmit
MantineColor
MantineRadius
MantineSize
SliderMark
React.ReactNode
TransitionOverride
React.ComponentProps<'input'>
React.ComponentProps<'div'>
HTMLDivElement
SliderStylesNames
SliderCssVariables