Skip to main content

Slider

Customizable slider component.

Source Style
Loading...
function App() {
  const [value, setValue] = useState(64)

  return (
    <div
      style={{
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        gap: 8,
      }}
    >
      <Slider.Root
        className={sliderTheme.root}
        value={value}
        min={0}
        max={100}
        onChange={(v) => setValue(v)}
      >
        <Slider.Track className={sliderTheme.track}>
          <Slider.Thumb className={sliderTheme.thumb} aria-label="Level" />
        </Slider.Track>
      </Slider.Root>
      <span
        style={{
          width: '2rem',
        }}
      >
        {value}
      </span>
    </div>
  )
}

Import​

import { Slider } from '@tremolo-ui/react'

API Reference​

Each part lists the props of its own. It also takes the attributes of the element it renders, such as className and style.

In Svelte and Vue the props are the same, written their way — class rather than className, bind:value or v-model, snippets or slots for content. See Svelte and Vue.

State is on the element as a data attribute, so it is a selector away — see Styling. An attribute is only there while its state is on.

Root​

Holds the value and the settings, and passes them to the parts inside.

PropTypeDefault
value*number—
min*number—
max*number—
stepnumber1
scaleScalelinearScale
orientation"horizontal" | "vertical"'horizontal'
reversebooleanfalse
dragCursorCursor'pointer'
wheelModifierValue<InputEventOption> | null['raw', 1]
dragSensitivityModifierValue<number>{ default: 1, shift: 0.1 }
keyboardModifierValue<InputEventOption> | null{ default: ['raw', 1], shift: ['raw', 0.1] }
disabledboolean—
readOnlyboolean—
onChange(value: number) => void—
onChangeStart(value: number, source: ChangeSource) => void—
onChangeEnd(value: number, source: ChangeSource) => void—
changeEndDelaynumber500
children*ReactNode—
actionsRefRef<SliderMethods>—

Full reference: SliderProps

Data attributeValues
[data-orientation]"horizontal" | "vertical"
[data-disabled]Present when disabled is set
[data-readonly]Present when readonly is set

Track​

The bar the value runs along. It sets --percent to where the value is, so the theme can fill the part below it. Slider.Thumb goes inside it.

PropTypeDefault
lengthstring | number—
thicknessstring | number—
activeColorstring—
inactiveColorstring—

Full reference: SliderTrackProps

Custom propertyWritten byWhat it sets
--lengthlengthHow long the track is along the axis the slider runs.
--thicknessthicknessHow thick the track is across that axis.
--active-coloractiveColorColour of the part from min to the value.
--inactive-colorinactiveColorColour of the rest of the track.
--percentthe componentWhere the value sits, as a percentage.

--percent is the one number CSS cannot work out on its own, and it is why the track draws nothing of its own: the fill is a rule in the theme rather than something the package paints for you.

.track {
background: linear-gradient(
var(--axis),
var(--active-color) var(--percent),
var(--inactive-color) var(--percent)
);
}

Replace that rule and the track can be anything — a second colour stop, an image, a dotted scale that fills in.

Data attributeValues
[data-orientation]"horizontal" | "vertical"
[data-disabled]Present when disabled is set
[data-flipped]Present when the value grows from the far end: vertical or reverse, but not both

Thumb​

The handle. A visually hidden range input inside it takes the focus and carries the ARIA.

Its children are drawn inside it. The thumb is one element either way, so what is passed there is decoration on top of it rather than a replacement for it — className and style are how its own appearance is changed.

PropTypeDefault
colorstring—
actionsRefRef<SliderThumbMethods>—

Full reference: SliderThumbProps

Custom propertyWritten byWhat it sets
--colorcolorColour of the thumb.
Data attributeValues
[data-disabled]Present when disabled is set
[data-readonly]Present when readonly is set

Marks​

A row of marks along the track, built from options or from Slider.MarksOption children, one per mark. The children are ignored while options is set.

PropTypeDefault
gapstring | number—
optionsMarksOptions—

Full reference: SliderMarksProps

Custom propertyWritten byWhat it sets
--gapgapSpace between the marks and the track.
Data attributeValues
[data-orientation]"horizontal" | "vertical"

MarksOption​

One mark and its label, placed at value.

PropTypeDefault
value*number—
markbooleantrue
labelstring | number | null—
thicknessstring | number—
lengthstring | number—
gapstring | number—
classes{ mark?: string; label?: string }—
styles{ mark?: CSSProperties; label?: CSSProperties }—

Full reference: SliderMarksOptionProps

Custom propertyWritten byWhat it sets
--thicknessthicknessThickness of the mark.
--lengthlengthLength of the mark.
--gapgapSpace between the mark and the label.

Set the label's width through styles.label or its class in classes.label.

Data attributeValues
[data-orientation]"horizontal" | "vertical"

The mark inside the option carries [data-orientation] too.