Skip to content

Slider

A draggable control for picking a number (or a range) within a min/max, built on Reka UI's Slider primitive.

Usage

v-model is a plain number for a single handle:

30

vue
<script setup lang="ts">
const value = ref(30)
</script>

<template>
  <SSlider v-model="value" aria-label="Volume" />
</template>

Range

Pass an array instead to get a range slider with one handle per entry - minStepsBetweenThumbs keeps them from crossing (or getting closer than that many steps apart). The value you get back always matches the shape you passed in - an array in, an array out:

$20 - $80

vue
<script setup lang="ts">
const priceRange = ref([20, 80])
</script>

<template>
  <SSlider v-model="priceRange" :min-steps-between-thumbs="5" />
</template>

Min, max, and step

min/max (default 0/100) bound the value, step (default 1) controls the increment - both the drag and the arrow keys snap to it.

Ticks

show-ticks marks every step along the track - a Selaras addition, not part of Reka's own primitive:

vue-html
<SSlider v-model="value" :step="25" show-ticks />

Color

vue-html
<SSlider :model-value="60" color="danger" />

Vertical

orientation="vertical" needs a real height to size against - the theme gives it a sensible default (override via :ui.root for a taller/shorter one):

vue-html
<SSlider v-model="value" orientation="vertical" />

Inverted

inverted visually (and directionally) flips the slider - the max end renders where the min end normally would, and dragging is reversed to match:

vue-html
<SSlider v-model="value" inverted aria-label="Volume (inverted)" />

Thumb variant

thumb-variant="bar" swaps the default circular thumb for a thin bar, sized off the track's own size and orientation:

vue-html
<SSlider v-model="value" thumb-variant="bar" />

Start and end slots

#start/#end render content flanking the track - an icon, an emoji, a unit label:

😞 😄

Okay

vue-html
<SSlider v-model="value">
  <template #start>😞</template>
  <template #end>😄</template>
</SSlider>

Tooltip

tooltip wraps each thumb in a tooltip showing its current value on hover or focus:

vue-html
<SSlider v-model="value" tooltip />

Controls

controls adds -/+ buttons flanking the track that step the value by step, disabling at min/max - only rendered for a single-value slider, since stepping two independent range thumbs with one shared button pair has no obvious single meaning:

105 credits/mo

vue-html
<SSlider v-model="value" controls />

Side labels

Plain text either side of the track composes with no extra API:

LowHigh
vue-html
<div class="flex items-center gap-3">
  <span>Low</span>
  <SSlider v-model="value" />
  <span>High</span>
</div>

Paired with a number input

SSlider and SInputNumber sharing one v-model gives an exact, typeable value alongside the drag control:

vue-html
<div class="flex items-center gap-3">
  <SSlider v-model="value" />
  <SInputNumber v-model="value" :min="0" :max="100" />
</div>

Accessible labeling

A slider thumb has no visible text of its own, so it needs an accessible name from somewhere. aria-label (a single string) applies to every thumb - fine for a single-handle slider. For a range slider, Reka's own primitive already falls back to "Minimum"/"Maximum" for a two-thumb slider with no label at all; pass an array to aria-label to say something more specific instead (['Low priority', 'High priority'], for one):

vue-html
<SSlider v-model="priceRange" :aria-label="['Minimum price', 'Maximum price']" />

Committing vs. continuous updates

update:model-value (what v-model uses) fires continuously while dragging. value-commit fires once, only when a drag finishes with an actually-changed value - useful for anything that shouldn't run on every intermediate frame, like a debounced request:

vue-html
<SSlider v-model="value" @value-commit="(v) => fetchResultsFor(v)" />

Custom :ui

To see exactly what you'd be overriding - the current default classes for every slot and variant - here's Slider's own theme file:

Theme source "slider" not found

Props

PropTypeDefault
modelValuenumber | number[]-
defaultValuenumber | number[]-
minnumber0
maxnumber100
stepnumber1
minStepsBetweenThumbsnumber-
disabledbooleanfalse
orientation'horizontal' | 'vertical''horizontal'
invertedbooleanfalse
showTicksbooleanfalse
size'sm' | 'md' | 'lg'md
color'primary' | 'neutral' | 'secondary' | 'success' | 'danger' | 'info' | 'warning'primary
thumbVariant'circle' | 'bar'circle
tooltipbooleanfalse
controlsbooleanfalse
ariaLabelstring | string[]-
namestring (submitted via a hidden input Reka renders internally - only takes effect inside a real <form>)-
uiPartial<Record<SliderSlot, string | object>>-

Events

EventPayloadDescription
update:modelValuenumber | number[]Fires continuously while dragging
valueCommitnumber | number[]Fires once, when a drag finishes with a changed value

Slots

SlotPropsDescription
start-Content flanking the start of the track
end-Content flanking the end of the track
Edit this page