@mshafiqyajid/react-slider
Headless slider hook and styled component. Single and range (dual thumb) mode, tick marks with snap, logarithmic scale, vertical orientation, value tooltip, label / hint / error / invalid / required, keyboard navigation, ARIA-compliant.
Playground #
committed: 40
Props
TSX
import { SliderStyled } from "@mshafiqyajid/react-slider/styled";
import "@mshafiqyajid/react-slider/styles.css";
<SliderStyled
value={value}
onChange={setValue}
tone="primary"
/>Multi-thumb β 3 independent thumbs
snapToMarks
values: 20 Β· 50 Β· 80
Log scale (min=1, max=10 000)
value: 100
Install #
npm install @mshafiqyajid/react-slider Quick start #
import { SliderStyled } from "@mshafiqyajid/react-slider/styled";
import "@mshafiqyajid/react-slider/styles.css";
const [v, setV] = useState(40);
<SliderStyled value={v} onChange={setV} tone="primary" showValue />
// Range
const [range, setRange] = useState<[number, number]>([20, 80]);
<SliderStyled value={range} onChange={setRange} range /> Marks and snap #
Pass marks={true} to derive ticks from step, an array of numbers, or an array of { value, label? } objects. Add snapToMarks to snap the thumb on release.
// Ticks derived from step
<SliderStyled min={0} max={100} step={25} marks />
// Custom marks with labels
<SliderStyled
min={0} max={100}
marks={[{ value: 0, label: "Low" }, { value: 50, label: "Mid" }, { value: 100, label: "High" }]}
snapToMarks
/> Logarithmic scale #
<SliderStyled
min={1} max={1000}
scale="log"
scaleBase={10}
formatValue={(v) => `${v} Hz`}
showValue
/> Vertical orientation #
<SliderStyled orientation="vertical" style={{ height: 200 }} /> Form field #
Include label, hint, error, required, and name to use as a proper form field. Range mode emits two hidden inputs: name and name-end.
<SliderStyled
name="price-range"
label="Price range"
hint="Set your budget"
required
range
value={range}
onChange={setRange}
/> Headless #
import { useSlider } from "@mshafiqyajid/react-slider";
const { value, trackProps, thumbProps, rangeProps } = useSlider({
defaultValue: 50,
min: 0,
max: 100,
});
return (
<div className="slider">
<div {...trackProps} className="track">
<div {...rangeProps} className="range" />
{thumbProps.map((thumb, i) => (
<button key={i} {...thumb} className="thumb" />
))}
</div>
<span>{Array.isArray(value) ? value.join("β") : value}</span>
</div>
); API #
| Prop | Type | Default | Description |
|---|---|---|---|
| value | number | [number, number] | β | Controlled value |
| defaultValue | number | [number, number] | min (range: [min, max]) | Uncontrolled initial value |
| onChange | (v: SliderValue) => void | β | Called on every change |
| onCommit | (v: SliderValue) => void | β | Fires only on pointer release / keyboard commit, not on every step |
| min | number | 0 | Minimum value |
| max | number | 100 | Maximum value |
| step | number | 1 | Step increment |
| range | boolean | false | Dual thumb range mode |
| size | "sm" | "md" | "lg" | "md" | Track height |
| tone | "neutral" | "primary" | "success" | "danger" | "neutral" | Color |
| orientation | "horizontal" | "vertical" | "horizontal" | Slider orientation |
| showValue | boolean | false | Always show value bubble on thumb |
| showValueOnInteraction | boolean | β | Show value bubble only while thumb is hovered/active |
| formatValue | (v: number) => ReactNode | β | Format the number shown in the value bubble |
| marks | boolean | number[] | SliderMark[] | false | Tick marks. true derives from step; array sets custom positions with optional labels |
| snapToMarks | boolean | false | Snap thumb to nearest mark on drag release |
| scale | "linear" | "log" | "linear" | Map the track to a logarithmic scale |
| scaleBase | number | 10 | Base for the log scale |
| disabled | boolean | false | Disable interaction |
| label | ReactNode | β | Label rendered above the slider |
| hint | ReactNode | β | Helper text below the slider |
| error | ReactNode | β | Error text β flips tone to danger, sets aria-invalid |
| invalid | boolean | false | Force invalid state without inline error text |
| required | boolean | β | Mark as required (hidden inputs inherit this) |
| name | string | β | Form name. Renders hidden input(s); range emits name and name-end |
| id | string | β | Override the generated wrapper id |
| className | string | β | Extra class on the root element |
| style | CSSProperties | β | Inline style override |