Slider
A range input control built on Base UI. Two visual variants (discrete and continuous), five intents, three sizes, horizontal and vertical orientation, range mode, tick marks, value tooltip, and RTL support.
Installation
pnpm add @tessinaui/uiUsage
import { Slider } from "@tessinaui/ui";
<Slider defaultValue={40} />Playground
Preview
Showcase
Preview
Variants
| Variant | Description |
|---|---|
discrete | Classic thin-track slider with a pill-shaped thumb. Default. |
continuous | Large capsule/pill fill-style slider with a circular knob inside. |
Intents
| Intent | Color token | Use case |
|---|---|---|
none | bg-primary | Default brand color |
error | bg-error | Error or danger state |
warning | bg-warning | Warning or caution state |
success | bg-success | Success or confirmation state |
info | bg-info | Informational state |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | readonly number[] | — | Controlled value. Pass an array for range mode. |
defaultValue | number | readonly number[] | 40 | Initial uncontrolled value. Pass an array for range mode. |
min | number | 0 | Minimum allowed value |
max | number | 100 | Maximum allowed value |
step | number | 1 | Step increment |
largeStep | number | — | Step for Page Up/Down or Shift+Arrow |
onValueChange | (value: number | readonly number[]) => void | — | Fires on every change |
onValueCommitted | (value: number | readonly number[]) => void | — | Fires on pointer up / key up |
variant | "discrete" | "continuous" | "discrete" | Visual style |
size | "sm" | "md" | "lg" | "md" | Scale |
intent | "none" | "error" | "warning" | "success" | "info" | "none" | Semantic color intent |
orientation | "horizontal" | "vertical" | "horizontal" | Layout direction |
disabled | boolean | false | Disable all interaction |
rounded | "none" | "sm" | "md" | "lg" | "xl" | "full" | "full" | Border radius of track, indicator, and thumb |
marks | boolean | SliderMark[] | false | true = auto-generate at every step (capped at 50). Array = custom positions with optional labels. |
minLabel | ReactNode | — | Label at the min end (left for horizontal, bottom for vertical) |
maxLabel | ReactNode | — | Label at the max end (right for horizontal, top for vertical) |
showValue | boolean | false | Show current value as a floating tooltip above/beside the thumb |
label | ReactNode | — | Accessible label (rendered sr-only) |
leadingIcon | ReactNode | — | Icon at the leading end (left for horizontal, bottom for vertical) |
trailingIcon | ReactNode | — | Icon at the trailing end (right for horizontal, top for vertical) |
getAriaLabel | (index: number) => string | — | Accessible label per thumb (range mode) |
getAriaValueText | (formatted, value, index) => string | — | Accessible value text per thumb |
name | string | — | Form field name |
format | Intl.NumberFormatOptions | — | Number format for the value tooltip |
dir | "ltr" | "rtl" | "ltr" | Text direction |
className | string | — | Extra classes on the root element |
SliderMark
| Field | Type | Description |
|---|---|---|
value | number | Value at which to render the tick dot |
label | ReactNode | Optional text label beside the dot |
Range Slider
Pass an array to defaultValue or value to enable range (two-thumb) mode:
<Slider defaultValue={[20, 80]} />Accessibility
- Built on Base UI's
Sliderprimitive — keyboard navigation (Arrow keys, Page Up/Down, Home, End) is handled automatically. - Each thumb renders an
<input type="range">with a proper accessible role. - Use
getAriaLabelin range mode to provide distinct labels for each thumb (e.g. "Minimum price", "Maximum price"). - Tick mark labels are
aria-hidden— they are visual decorations; usegetAriaValueTextfor screen-reader value descriptions. - Focus ring:
has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-offset-2scoped to the thumb container. - All interactive areas meet the WCAG AA 44×44 px minimum touch target.