Slider
PortedPick a number, or a range between two numbers, by dragging a thumb along a track. Pass an array to value or defaultValue for a range. Arrow keys step by step, Shift with them and Page Up and Down by largeStep, and Home and End go to min and max. format takes Intl.NumberFormat options. Native <div> attributes and ref pass through.
import { Slider } from "@etched/monet/slider";
export function Preview() {
return (
<div className="grid" style={{ inlineSize: "16rem" }}>
<Slider aria-label="Fan speed" defaultValue={40} />
</div>
);
}Installation
import { Slider } from "@etched/monet/slider";Examples
One value
Drag the thumb, or use the arrow keys: Shift or Page Up and Down take bigger steps, and Home and End go to the ends.
import { Slider } from "@etched/monet/slider";
export function OneValue() {
return (
<div className="grid">
<Slider label="Fan speed" defaultValue={40} />
</div>
);
}Range
An array value has a thumb for each end. getAriaLabel names each thumb.
import { Slider } from "@etched/monet/slider";
export function Range() {
return (
<div className="grid">
<Slider
label="Salary band"
defaultValue={[160000, 220000]}
min={100000}
max={300000}
step={5000}
format={{ style: "currency", currency: "USD", notation: "compact" }}
getAriaLabel={(index) => (index === 0 ? "Lowest salary" : "Highest salary")}
/>
</div>
);
}Steps and formats
step sets the stops. format takes Intl.NumberFormat options; a percent is a fraction.
Share of runs kept for review.
import { Slider } from "@etched/monet/slider";
export function StepsAndFormats() {
return (
<div className="grid">
<Slider label="Interview rounds" defaultValue={2} min={1} max={5} />
<Slider label="Sampling rate" defaultValue={0.25} min={0} max={1} step={0.05} format={{ style: "percent" }} description="Share of runs kept for review." />
</div>
);
}Sizes
import { Slider } from "@etched/monet/slider";
export function Sizes() {
return (
<div className="grid">
<Slider size="sm" aria-label="Volume (small)" defaultValue={30} />
<Slider aria-label="Volume" defaultValue={30} />
</div>
);
}Controlled
onValueChange runs while the thumb moves; onValueCommitted runs when it stops.
Candidates above 70 show in the shortlist.
import { useState } from "react";
import { Slider } from "@etched/monet/slider";
export function Controlled() {
const [threshold, setThreshold] = useState(70);
const [saved, setSaved] = useState(70);
return (
<div className="grid">
<Slider
label="Match threshold"
value={threshold}
onValueChange={setThreshold}
onValueCommitted={setSaved}
description={`Candidates above ${saved} show in the shortlist.`}
/>
</div>
);
}Disabled
import { Slider } from "@etched/monet/slider";
export function Disabled() {
return (
<div className="grid">
<Slider label="Bench load (locked)" defaultValue={70} disabled />
</div>
);
}Accessibility
- Arrow keys step by
step.Shiftwith an arrow, andPageUp/PageDown, step bylargeStep.Home/Endgo tominandmax. - Each thumb is a
slider(a native range input), named bylabeloraria-label.getAriaLabelcomes first, and tells a range's two thumbs apart. - Screen readers hear the value as
formatwrites it, anddescriptionorerroras its description. A range's thumbs add "start range" and "end range". - Give a range
getAriaLabel, such as "Lowest salary" and "Highest salary".
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
| label | ReactNode | – | Visible label. Without one, give the control an aria-label. |
| labelTooltip | ReactNode | – | More about the field, behind an info button after the label. |
| labelTooltipLabel | string | "More information" | Names the info button. |
| description | ReactNode | – | Help text below the control. Hidden while an error shows. |
| error | FieldError | – | |
| size | "sm" | "base" | "base" | Track height: sm is 28 px, for toolbars and filters; base is 36 px, as Input. |
| getAriaLabel | (index: number) => string | – | Names each thumb. Use it without a visible label, or to tell the two thumbs of a range apart. |
| className | string | – | Class on the outer element, for layout. |