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
<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
<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:
<SSlider v-model="value" :step="25" show-ticks />
Color
<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):
<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:
<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:
<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
<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:
<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
<SSlider v-model="value" controls />
Side labels
Plain text either side of the track composes with no extra API:
<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:
<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):
<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:
<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:
Props
| Prop | Type | Default |
|---|---|---|
modelValue | number | number[] | - |
defaultValue | number | number[] | - |
min | number | 0 |
max | number | 100 |
step | number | 1 |
minStepsBetweenThumbs | number | - |
disabled | boolean | false |
orientation | 'horizontal' | 'vertical' | 'horizontal' |
inverted | boolean | false |
showTicks | boolean | false |
size | 'sm' | 'md' | 'lg' | md |
color | 'primary' | 'neutral' | 'secondary' | 'success' | 'danger' | 'info' | 'warning' | primary |
thumbVariant | 'circle' | 'bar' | circle |
tooltip | boolean | false |
controls | boolean | false |
ariaLabel | string | string[] | - |
name | string (submitted via a hidden input Reka renders internally - only takes effect inside a real <form>) | - |
ui | Partial<Record<SliderSlot, string | object>> | - |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | number | number[] | Fires continuously while dragging |
valueCommit | number | number[] | Fires once, when a drag finishes with a changed value |
Slots
| Slot | Props | Description |
|---|---|---|
start | - | Content flanking the start of the track |
end | - | Content flanking the end of the track |