Slider
A labeled slider row: the label and its value badge beside a track you drag, click or step with the keyboard.
import { Slider } from "@butteryui/react";Demo
When to use it
Use it for
- A continuous value you judge by eye: rotation, scale, blur, opacity
- Inspector rows, where the live value shows in the badge
Not for
- An exact number people type: use NumberField
- A few named levels: use SegmentedControl
Examples
Beside a field
A slider with its label on top, beside a number field with its label on top, so the two controls start on one line.
Exports at 1600 px wide and 80% quality
Locked layer
A disabled slider: the logo's opacity holds while its layer is locked and moves again once it's unlocked.
Opacity row
An opacity in percent, saved when a drag ends or a key press lands rather than on every frame.
Saved at 80%
Picture section
Slider rows in an inspector section, whose Reset puts every row back to its default.
Picture
Rotation row
A rotation from -180° to 180° that catches at 0° while dragging and goes back to 0° on a double-click or Backspace.
Variants and states
Rotation
Drag past 0° and it catches there. Double-click the label or the badge to reset; Shift and an arrow key moves ten degrees.
Formats, a filled range and disabled
Props
Slider
| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | string | What the slider sets, shown beside its value and used as its name. | |
value | number | The value. Pair with onValueChange to control it. | |
defaultValue | number | min | The starting value when uncontrolled. Defaults to min. |
onValueChange | ((value: number) => void) | Called on every change, frame by frame while dragging. | |
onValueCommit | ((value: number) => void) | Called once the user lets go of the thumb or finishes a key press. | |
min | number | 0 | The lowest value. Defaults to 0. |
max | number | 100 | The highest value. Defaults to 100. |
step | number | 1 | The smallest change. Arrow keys move one step, Shift and an arrow ten. Defaults to 1. |
resetValue | number | What a double-click on the label or the badge, or Backspace or Delete on the thumb, resets to. Defaults
to defaultValue, then min. | |
detents | readonly number[] | Values a drag snaps to when it passes within 2% of the range, such as 0 for a rotation. | |
format | SliderFormat | How the badge and screen readers write the value: "%", "°", "px" or a function. | |
showRange | boolean | Fills the track up to the thumb. Off by default. | |
disabled | boolean | Keeps the value from changing. | |
labelPosition | "side" | "top" | "side" | Where the label and its value sit: "side" (the default), before a 160px track, as in an inspector
row, or "top", on a line above a track that fills the column, as a field's label sits. |
It also takes Omit<ComponentPropsWithRef<"div">, "defaultValue" | "onChange" | "dir" | "children">.
Accessibility
Radix's slider: the thumb is role=slider, named by the label, with the formatted value as aria-valuetext. Arrow keys step, Shift and an arrow or Page Up and Page Down step ten, Home and End go to the ends, and Backspace or Delete resets, like a double-click on the label or badge. A press on the thumb focuses it and keeps the value; a press on the track moves the value there and focuses the thumb. Dragging updates the value every frame with no easing.
| Keys | What they do |
|---|---|
| Arrow Right or Arrow Up | Moves the value up one step |
| Arrow Left or Arrow Down | Moves the value down one step |
| Shift and an arrow, Page Up or Page Down | Moves the value ten steps |
| Home or End | Moves the value to min or max |
| Backspace or Delete | Resets to resetValue, else defaultValue, else min |
Motion
It doesn't move.
With reduced motion: Nothing changes.
Layout
It fills its container's width: the label and its value badge at the start, the label truncating with an ellipsis and showing in full as its title, and the track at --bt-w-row-control (160px) at the end. Its height is its 24px thumb's, and the thumb's hit area is 36px square; the badge keeps room for the formatted min and max, so it never changes width.
Related
See it in the Deckhand demo.