Forms
Slider
Picks a number from a range by dragging or with the keyboard.
Installation
npx sinaui add sliderCopy src/lib/ui/Slider.svelte and tokens.css. No dependencies.
Examples
Basic
The House of Wisdom
<script lang="ts">
import Slider from '#lib/ui/Slider.svelte';
let size = $state(18);
</script>
<!-- A fixed box, so the slider stays put while the text grows under it. -->
<div class="demo">
<Slider label="Reading size" min={12} max={32} bind:value={size} format={(v) => `${v}px`} />
<p style:font-size="{size}px">The House of Wisdom</p>
</div>
<style>
.demo {
display: grid;
gap: 0.75rem;
inline-size: 20rem;
max-inline-size: 100%;
}
p {
min-block-size: 5rem;
margin: 0;
line-height: 2.5rem;
}
</style>With units and a hint
Arrow keys move one day; Page Up and Page Down move faster.
<script lang="ts">
import Slider from '#lib/ui/Slider.svelte';
let days = $state(40);
</script>
<Slider
label="Loan length"
min={7}
max={90}
step={1}
bind:value={days}
format={(v) => `${v} days`}
hint="Arrow keys move one day; Page Up and Page Down move faster."
/>A range
Give value a pair for two thumbs. Drag either; a bubble shows its value over your finger.
From the founding of Baghdad to its fall.
<script lang="ts">
import Slider from '#lib/ui/Slider.svelte';
let years = $state<[number, number]>([830, 1060]);
</script>
<div class="demo">
<Slider
label="Copied between"
min={750}
max={1258}
step={1}
bind:value={years}
format={(v) => `${v} CE`}
thumbLabels={['From year', 'To year']}
hint="From the founding of Baghdad to its fall."
/>
</div>
<style>
.demo {
inline-size: min(24rem, 100%);
}
</style>With marks
Ticks on the track; press a label to jump there.
<script lang="ts">
import Slider from '#lib/ui/Slider.svelte';
let lamp = $state(60);
</script>
<div class="demo">
<Slider
label="Reading lamp"
bind:value={lamp}
step={5}
format={(v) => `${v}%`}
marks={[
{ value: 0, label: 'Off' },
{ value: 25, label: '25%' },
{ value: 50, label: '50%' },
{ value: 75, label: '75%' },
{ value: 100, label: 'Full' }
]}
/>
</div>
<style>
.demo {
inline-size: min(24rem, 100%);
}
</style>Props
| Prop | Type | Default |
|---|---|---|
label | string (required) | |
value | number | [number, number], bindable: a pair is a range | 50 |
min | number | 0 |
max | number | 100 |
step | number | 1 |
format | (value) => string | number |
hint | string | |
marks | (number | { value, label? })[]: labeled ones can be pressed | |
thumbLabels | [string, string]: names of a range's two thumbs | “Lowest …”, “Highest …” |
Accessibility
- A native
<input type="range">: keyboard, touch and forms for free. - Screen readers hear the formatted value (
aria-valuetext), e.g. “40 days”, not just “40”. - The grab area is taller than the track, and 44px on touch screens.
- A range is a group named by the label, with each thumb its own slider; the two can't cross.
- The value bubble and marks are for sight only: the thumbs carry the value.
| Key | Action |
|---|---|
| → / ↑, ← / ↓ | One step up / down. |
| PageUp / PageDown | A larger jump. |
| Home / End | Minimum / maximum. |