Slider
A component for selecting a value from a range using a draggable handle
Basic Usage
Simple Slider
Value: 50
With Tooltip
Hover over the thumb to see the tooltip
1
2<script lang="ts">
3 import { Slider, Badge } from "@kareyes/aether";
4
5 let basicValue = $state(50);
6</script>
7
8<div class="grid gap-8 md:grid-cols-2">
9 <div class="space-y-4">
10 <h3 class="text-lg font-medium">Simple Slider</h3>
11 <Slider type="single" bind:value={basicValue} min={0} max={100} step={1} />
12 <p class="text-sm text-muted-foreground">
13 Value: <Badge variant="secondary">{basicValue}</Badge>
14 </p>
15 </div>
16
17 <div class="space-y-4">
18 <h3 class="text-lg font-medium">With Tooltip</h3>
19 <Slider type="single" value={50} min={0} max={100} showTooltip={true} />
20 <p class="text-sm text-muted-foreground">Hover over the thumb to see the tooltip</p>
21 </div>
22</div>Variants
Default
Primary
Secondary
Success
Warning
Destructive
1
2<script lang="ts">
3 import { Slider } from "@kareyes/aether";
4</script>
5
6<div class="space-y-6">
7 <div class="space-y-2">
8 <h3 class="text-sm font-medium">Default</h3>
9 <Slider type="single" variant="default" value={50} />
10 </div>
11
12 <div class="space-y-2">
13 <h3 class="text-sm font-medium">Primary</h3>
14 <Slider type="single" variant="primary" value={50} />
15 </div>
16
17 <div class="space-y-2">
18 <h3 class="text-sm font-medium">Secondary</h3>
19 <Slider type="single" variant="secondary" value={50} />
20 </div>
21
22 <div class="space-y-2">
23 <h3 class="text-sm font-medium">Success</h3>
24 <Slider type="single" variant="success" value={50} />
25 </div>
26
27 <div class="space-y-2">
28 <h3 class="text-sm font-medium">Warning</h3>
29 <Slider type="single" variant="warning" value={50} />
30 </div>
31
32 <div class="space-y-2">
33 <h3 class="text-sm font-medium">Destructive</h3>
34 <Slider type="single" variant="destructive" value={50} />
35 </div>
36</div>Sizes
Small
Default
Large
1
2<script lang="ts">
3 import { Slider } from "@kareyes/aether";
4</script>
5
6<div class="space-y-6">
7 <div class="space-y-2">
8 <h3 class="text-sm font-medium">Small</h3>
9 <Slider type="single" size="sm" value={50} variant="primary" />
10 </div>
11
12 <div class="space-y-2">
13 <h3 class="text-sm font-medium">Default</h3>
14 <Slider type="single" size="default" value={50} variant="primary" />
15 </div>
16
17 <div class="space-y-2">
18 <h3 class="text-sm font-medium">Large</h3>
19 <Slider type="single" size="lg" value={50} variant="primary" />
20 </div>
21</div>Step Indicators
Step 10
Step 25 (Primary)
Step 5 (Large)
1
2<script lang="ts">
3 import { Slider } from "@kareyes/aether";
4</script>
5
6<div class="space-y-6">
7 <div class="space-y-2">
8 <h3 class="text-sm font-medium">Step 10</h3>
9 <Slider type="single" value={50} min={0} max={100} step={10} showSteps={true} />
10 </div>
11
12 <div class="space-y-2">
13 <h3 class="text-sm font-medium">Step 25 (Primary)</h3>
14 <Slider type="single" value={50} min={0} max={100} step={25} showSteps={true} variant="primary" />
15 </div>
16
17 <div class="space-y-2">
18 <h3 class="text-sm font-medium">Step 5 (Large)</h3>
19 <Slider
20 type="single"
21 value={50}
22 min={0}
23 max={100}
24 step={5}
25 showSteps={true}
26 variant="success"
27 size="lg"
28 />
29 </div>
30</div>Marks
Percentage Marks
Custom Labels
1
2<script lang="ts">
3 import { Slider, SliderPrimitives } from "@kareyes/aether";
4
5 const percentageMarks: SliderPrimitives.SliderMark[] = [
6 { value: 0, label: "0%" },
7 { value: 25, label: "25%" },
8 { value: 50, label: "50%" },
9 { value: 75, label: "75%" },
10 { value: 100, label: "100%" },
11 ];
12</script>
13
14<div class="space-y-6">
15 <div class="space-y-2">
16 <h3 class="text-sm font-medium">Percentage Marks</h3>
17 <Slider type="single" value={50} min={0} max={100} marks={percentageMarks} />
18 </div>
19
20 <div class="space-y-2">
21 <h3 class="text-sm font-medium">Custom Labels</h3>
22 <Slider
23 type="single"
24 value={50}
25 min={0}
26 max={100}
27 marks={[
28 { value: 0, label: "Min" },
29 { value: 25, label: "Low" },
30 { value: 50, label: "Medium" },
31 { value: 75, label: "High" },
32 { value: 100, label: "Max" },
33 ]}
34 variant="primary"
35 />
36 </div>
37</div>Combined Features
Steps + Marks + Tooltip
1
2<script lang="ts">
3 import { Slider, SliderPrimitives } from "@kareyes/aether";
4
5 const percentageMarks: SliderPrimitives.SliderMark[] = [
6 { value: 0, label: "0%" },
7 { value: 25, label: "25%" },
8 { value: 50, label: "50%" },
9 { value: 75, label: "75%" },
10 { value: 100, label: "100%" },
11 ];
12</script>
13
14<div class="space-y-6">
15 <div class="space-y-2">
16 <h3 class="text-sm font-medium">Steps + Marks + Tooltip</h3>
17 <Slider
18 type="single"
19 value={50}
20 min={0}
21 max={100}
22 step={10}
23 showSteps={true}
24 marks={percentageMarks}
25 showTooltip={true}
26 formatTooltip={(val) => `${val}%`}
27 variant="primary"
28 size="lg"
29 />
30 </div>
31</div>Range Slider
Price Range
Price Range: $100 - $500
With Steps and Marks
1
2<script lang="ts">
3 import { Slider, Badge } from "@kareyes/aether";
4
5 let priceRange = $state([100, 500]);
6</script>
7
8<div class="space-y-6">
9 <div class="space-y-4">
10 <h3 class="text-lg font-medium">Price Range</h3>
11 <Slider
12 type="multiple"
13 bind:value={priceRange}
14 min={0}
15 max={1000}
16 step={10}
17 showTooltip={true}
18 formatTooltip={(val) => `$${val}`}
19 variant="success"
20 />
21 <p class="text-sm text-muted-foreground">
22 Price Range:
23 <Badge variant="secondary">${priceRange[0]} - ${priceRange[1]}</Badge>
24 </p>
25 </div>
26
27 <div class="space-y-4">
28 <h3 class="text-lg font-medium">With Steps and Marks</h3>
29 <Slider
30 type="multiple"
31 value={[250, 750]}
32 min={0}
33 max={1000}
34 step={50}
35 showSteps={true}
36 marks={[
37 { value: 0, label: "$0" },
38 { value: 500, label: "$500" },
39 { value: 1000, label: "$1000" },
40 ]}
41 variant="primary"
42 />
43 </div>
44</div>Practical Examples
Volume Control
Volume: 70%
Temperature Control
Temperature: 22°C
Rating Scale
Rating: 3/5 - Good
Brightness
Brightness: 75%
Zoom Level
Zoom: 100%
Progress Indicator
Progress: 0%
1
2<script lang="ts">
3 import { Slider, Badge, SliderPrimitives } from "@kareyes/aether";
4
5 let volumeValue = $state(70);
6 let tempValue = $state(22);
7 let ratingValue = $state(3);
8 let brightnessValue = $state(75);
9 let zoomValue = $state(100);
10 let progressValue = $state(0);
11
12 const volumeMarks: SliderPrimitives.SliderMark[] = [
13 { value: 0, label: "🔇" },
14 { value: 50, label: "🔉" },
15 { value: 100, label: "🔊" },
16 ];
17
18 const ratingMarks: SliderPrimitives.SliderMark[] = [
19 { value: 1, label: "Poor" },
20 { value: 2, label: "Fair" },
21 { value: 3, label: "Good" },
22 { value: 4, label: "Great" },
23 { value: 5, label: "Excellent" },
24 ];
25
26 let progressInterval: ReturnType<typeof setInterval> | undefined;
27 function startProgress() {
28 progressValue = 0;
29 progressInterval = setInterval(() => {
30 if (progressValue < 100) {
31 progressValue = progressValue + 1;
32 } else {
33 if (progressInterval) clearInterval(progressInterval);
34 }
35 }, 50);
36 }
37
38 function resetProgress() {
39 if (progressInterval) clearInterval(progressInterval);
40 progressValue = 0;
41 }
42</script>
43
44<div class="grid gap-8 md:grid-cols-2">
45 <div class="space-y-4">
46 <h3 class="text-lg font-medium">Volume Control</h3>
47 <Slider
48 type="single"
49 bind:value={volumeValue}
50 min={0}
51 max={100}
52 step={5}
53 marks={volumeMarks}
54 showTooltip={true}
55 formatTooltip={(val) => `${val}%`}
56 variant="primary"
57 />
58 <p class="text-sm text-muted-foreground">
59 Volume: <Badge variant="secondary">{volumeValue}%</Badge>
60 </p>
61 </div>
62
63 <div class="space-y-4">
64 <h3 class="text-lg font-medium">Temperature Control</h3>
65 <Slider
66 type="single"
67 bind:value={tempValue}
68 min={16}
69 max={30}
70 step={0.5}
71 showTooltip={true}
72 formatTooltip={(val) => `${val}°C`}
73 variant="warning"
74 size="lg"
75 />
76 <p class="text-sm text-muted-foreground">
77 Temperature: <Badge variant="secondary">{tempValue}°C</Badge>
78 </p>
79 </div>
80
81 <div class="space-y-4">
82 <h3 class="text-lg font-medium">Rating Scale</h3>
83 <Slider
84 type="single"
85 bind:value={ratingValue}
86 min={1}
87 max={5}
88 step={1}
89 marks={ratingMarks}
90 showSteps={true}
91 variant="warning"
92 size="lg"
93 />
94 <p class="text-sm text-muted-foreground">
95 Rating: <Badge variant="secondary">{ratingValue}/5 - {ratingMarks[ratingValue - 1].label}</Badge>
96 </p>
97 </div>
98
99 <div class="space-y-4">
100 <h3 class="text-lg font-medium">Brightness</h3>
101 <Slider
102 type="single"
103 bind:value={brightnessValue}
104 min={0}
105 max={100}
106 step={5}
107 showTooltip={true}
108 formatTooltip={(val) => `${val}%`}
109 variant="primary"
110 />
111 <p class="text-sm text-muted-foreground">
112 Brightness: <Badge variant="secondary">{brightnessValue}%</Badge>
113 </p>
114 </div>
115
116 <div class="space-y-4">
117 <h3 class="text-lg font-medium">Zoom Level</h3>
118 <Slider
119 type="single"
120 bind:value={zoomValue}
121 min={50}
122 max={200}
123 step={10}
124 showSteps={true}
125 showTooltip={true}
126 formatTooltip={(val) => `${val}%`}
127 marks={[
128 { value: 50, label: "50%" },
129 { value: 100, label: "100%" },
130 { value: 200, label: "200%" },
131 ]}
132 variant="primary"
133 />
134 <p class="text-sm text-muted-foreground">
135 Zoom: <Badge variant="secondary">{zoomValue}%</Badge>
136 </p>
137 </div>
138
139 <div class="space-y-4">
140 <h3 class="text-lg font-medium">Progress Indicator</h3>
141 <Slider type="single" value={progressValue} min={0} max={100} disabled={true} variant="success" />
142 <div class="flex gap-2">
143 <button
144 onclick={startProgress}
145 class="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90"
146 >
147 Start
148 </button>
149 <button
150 onclick={resetProgress}
151 class="rounded-md border border-input bg-background px-3 py-1.5 text-sm font-medium hover:bg-accent"
152 >
153 Reset
154 </button>
155 </div>
156 <p class="text-sm text-muted-foreground">
157 Progress: <Badge variant="secondary">{progressValue}%</Badge>
158 </p>
159 </div>
160</div>Vertical Orientation
Default
With Steps
With Tooltip
Volume
1
2<script lang="ts">
3 import { Slider } from "@kareyes/aether";
4</script>
5
6<div class="flex gap-12">
7 <div class="space-y-4">
8 <h3 class="text-sm font-medium text-center">Default</h3>
9 <Slider type="single" value={50} orientation="vertical" class="h-64" />
10 </div>
11
12 <div class="space-y-4">
13 <h3 class="text-sm font-medium text-center">With Steps</h3>
14 <Slider
15 type="single"
16 value={50}
17 orientation="vertical"
18 step={10}
19 showSteps={true}
20 variant="primary"
21 class="h-64"
22 />
23 </div>
24
25 <div class="space-y-4">
26 <h3 class="text-sm font-medium text-center">With Tooltip</h3>
27 <Slider
28 type="single"
29 value={75}
30 orientation="vertical"
31 showTooltip={true}
32 formatTooltip={(val) => `${val}%`}
33 variant="success"
34 size="lg"
35 class="h-64"
36 />
37 </div>
38
39 <div class="space-y-4">
40 <h3 class="text-sm font-medium text-center">Volume</h3>
41 <Slider
42 type="single"
43 value={80}
44 orientation="vertical"
45 step={5}
46 showTooltip={true}
47 formatTooltip={(val) => `${val}%`}
48 variant="primary"
49 class="h-64"
50 />
51 </div>
52</div>With Field Component
Adjust the audio volume (0-100%)
Set the desired temperature (16-30°C)
Filter products by price ($0-$1000)
Select your rating (1-5 stars)
1
2<script lang="ts">
3 import { Slider, Field, SliderPrimitives } from "@kareyes/aether";
4
5 const ratingMarks: SliderPrimitives.SliderMark[] = [
6 { value: 1, label: "Poor" },
7 { value: 2, label: "Fair" },
8 { value: 3, label: "Good" },
9 { value: 4, label: "Great" },
10 { value: 5, label: "Excellent" },
11 ];
12</script>
13
14<div class="max-w-2xl space-y-6">
15 <Field label="Volume" description="Adjust the audio volume (0-100%)">
16 <Slider
17 type="single"
18 value={70}
19 min={0}
20 max={100}
21 step={5}
22 showTooltip={true}
23 formatTooltip={(val) => `${val}%`}
24 variant="primary"
25 />
26 </Field>
27
28 <Field label="Temperature" description="Set the desired temperature (16-30°C)">
29 <Slider
30 type="single"
31 value={22}
32 min={16}
33 max={30}
34 step={0.5}
35 showTooltip={true}
36 formatTooltip={(val) => `${val}°C`}
37 variant="warning"
38 />
39 </Field>
40
41 <Field label="Price Range" description="Filter products by price ($0-$1000)">
42 <Slider
43 type="multiple"
44 value={[100, 500]}
45 min={0}
46 max={1000}
47 step={10}
48 showTooltip={true}
49 formatTooltip={(val) => `$${val}`}
50 variant="success"
51 />
52 </Field>
53
54 <Field label="Rating" description="Select your rating (1-5 stars)">
55 <Slider
56 type="single"
57 value={3}
58 min={1}
59 max={5}
60 step={1}
61 marks={ratingMarks}
62 showSteps={true}
63 variant="warning"
64 size="lg"
65 />
66 </Field>
67</div>Disabled State
Disabled Slider
Disabled with Steps
1
2<script lang="ts">
3 import { Slider } from "@kareyes/aether";
4</script>
5
6<div class="space-y-6">
7 <div class="space-y-2">
8 <h3 class="text-sm font-medium">Disabled Slider</h3>
9 <Slider type="single" value={50} disabled={true} />
10 </div>
11
12 <div class="space-y-2">
13 <h3 class="text-sm font-medium">Disabled with Steps</h3>
14 <Slider type="single" value={50} step={10} showSteps={true} disabled={true} variant="primary" />
15 </div>
16</div>Features
- ✅ Multiple Variants: 6 visual styles (default, primary, secondary, success, warning, destructive)
- ✅ Three Sizes: sm, default, lg
- ✅ Step Indicators: Visual markers for each step value
- ✅ Custom Marks: Add labels at specific values
- ✅ Tooltips: Show current value on hover
- ✅ Orientations: Horizontal and vertical layouts
- ✅ Range Support: Single or multiple thumbs
- ✅ Keyboard Support: Full arrow key navigation
- ✅ Accessibility: ARIA attributes and screen reader support
- ✅ TypeScript: Complete type safety
Simple Slider
<script lang="ts">
import { Slider } from "@kareyes/aether";
let value = $state([50]);
</script>
<Slider bind:value min={0} max={100} step={1} />
With Primitives Import
<script lang="ts">
import { SliderPrimitives } from "@kareyes/aether";
</script>
<SliderPrimitives.Root value={[50]} min={0} max={100} step={1}>
{#snippet children({ thumbs, ticks })}
<SliderPrimitives.Range />
{#each thumbs as thumb}
<SliderPrimitives.Thumb {thumb} />
{/each}
{/snippet}
</SliderPrimitives.Root>
With Custom Range
<script>
let temperature = $state([20]);
</script>
<Slider
bind:value={temperature}
min={-10}
max={40}
step={0.5}
/>
Variants
Default
<Slider variant="default" value={[50]} />
Primary
<Slider variant="primary" value={[50]} />
Secondary
<Slider variant="secondary" value={[50]} />
Success
<Slider variant="success" value={[50]} />
Warning
<Slider variant="warning" value={[50]} />
Destructive
<Slider variant="destructive" value={[50]} />
Sizes
<!-- Small -->
<Slider size="sm" value={[50]} />
<!-- Default -->
<Slider size="default" value={[50]} />
<!-- Large -->
<Slider size="lg" value={[50]} />
Advanced Features
Step Indicators
Show visual markers at each step value:
<Slider
value={[50]}
min={0}
max={100}
step={10}
showSteps={true}
/>
Marks with Labels
Add labeled markers at specific values:
<script>
const marks = [
{ value: 0, label: "Min" },
{ value: 25, label: "Low" },
{ value: 50, label: "Medium" },
{ value: 75, label: "High" },
{ value: 100, label: "Max" },
];
</script>
<Slider
value={[50]}
min={0}
max={100}
marks={marks}
/>
Tooltip
Show current value on hover:
<Slider
value={[50]}
showTooltip={true}
/>
Custom Tooltip Formatter
<Slider
value={[20]}
min={0}
max={100}
showTooltip={true}
formatTooltip={(val) => `${val}°C`}
/>
Combined Features
<script>
let value = $state([50]);
const marks = [
{ value: 0, label: "0%" },
{ value: 50, label: "50%" },
{ value: 100, label: "100%" },
];
</script>
<Slider
bind:value
min={0}
max={100}
step={5}
showSteps={true}
marks={marks}
showTooltip={true}
formatTooltip={(val) => `${val}%`}
variant="primary"
size="lg"
/>
Range Slider
Use multiple thumbs for range selection:
<script>
let range = $state([25, 75]);
</script>
<Slider
bind:value={range}
min={0}
max={100}
step={5}
/>
Vertical Orientation
<Slider
value={[50]}
orientation="vertical"
class="h-64"
/>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value |
number[] |
[0] |
Current value(s) (bindable) |
variant |
"default" | "primary" | "secondary" | "success" | "warning" | "destructive" |
"default" |
Visual variant |
size |
"sm" | "default" | "lg" |
"default" |
Size variant |
orientation |
"horizontal" | "vertical" |
"horizontal" |
Slider orientation |
min |
number |
0 |
Minimum value |
max |
number |
100 |
Maximum value |
step |
number |
1 |
Step increment |
showSteps |
boolean |
false |
Show step indicators |
marks |
SliderMark[] |
[] |
Array of mark objects |
showTooltip |
boolean |
false |
Show tooltip on hover |
formatTooltip |
(value: number) => string |
(val) => String(val) |
Custom tooltip formatter |
disabled |
boolean |
false |
Disable the slider |
class |
string |
undefined |
Additional CSS classes |
ref |
HTMLElement | null |
null |
Reference to root element (bindable) |
SliderMark Type
interface SliderMark {
value: number; // Position on the slider
label?: string; // Optional label text
}
Examples
Volume Control
<script>
let volume = $state([70]);
const volumeMarks = [
{ value: 0, label: "🔇" },
{ value: 50, label: "🔉" },
{ value: 100, label: "🔊" },
];
</script>
<Slider
bind:value={volume}
min={0}
max={100}
step={5}
marks={volumeMarks}
showTooltip={true}
formatTooltip={(val) => `${val}%`}
variant="primary"
/>
Temperature Control
<script>
let temp = $state([22]);
</script>
<Slider
bind:value={temp}
min={16}
max={30}
step={0.5}
showTooltip={true}
formatTooltip={(val) => `${val}°C`}
variant="warning"
size="lg"
/>
Price Range
<script>
let priceRange = $state([100, 500]);
</script>
<Slider
bind:value={priceRange}
min={0}
max={1000}
step={10}
showTooltip={true}
formatTooltip={(val) => `$${val}`}
variant="success"
/>
<p>Price: ${priceRange[0]} - ${priceRange[1]}</p>
Rating Scale
<script>
let rating = $state([3]);
const ratingMarks = [
{ value: 1, label: "Poor" },
{ value: 2, label: "Fair" },
{ value: 3, label: "Good" },
{ value: 4, label: "Great" },
{ value: 5, label: "Excellent" },
];
</script>
<Slider
bind:value={rating}
min={1}
max={5}
step={1}
marks={ratingMarks}
showSteps={true}
variant="primary"
size="lg"
/>
Progress Indicator
<script>
let progress = $state([0]);
$effect(() => {
const interval = setInterval(() => {
progress = [Math.min(progress[0] + 1, 100)];
if (progress[0] >= 100) clearInterval(interval);
}, 100);
return () => clearInterval(interval);
});
</script>
<Slider
value={progress}
min={0}
max={100}
disabled={true}
variant="success"
formatTooltip={(val) => `${val}%`}
/>
Vertical Volume
<Slider
value={[75]}
orientation="vertical"
min={0}
max={100}
step={5}
showSteps={true}
showTooltip={true}
variant="primary"
class="h-64"
/>
Accessibility
- ✅ Keyboard Navigation: Arrow keys adjust value, Home/End for min/max
- ✅ ARIA Attributes: Proper roles, labels, and value announcements
- ✅ Screen Readers: Value changes are announced
- ✅ Focus Management: Clear visual focus indicators
- ✅ Touch Support: Works on touch devices
Keyboard Support
| Key | Action |
|---|---|
Arrow Right/Up |
Increase value by step |
Arrow Left/Down |
Decrease value by step |
Home |
Set to minimum value |
End |
Set to maximum value |
Page Up |
Increase by larger amount |
Page Down |
Decrease by larger amount |
Best Practices
- Choose Appropriate Steps: Use step values that make sense for your use case
- Use Marks Sparingly: Too many marks can clutter the interface
- Provide Tooltips: Help users understand the current value
- Consider Orientation: Vertical sliders work well for volume/height controls
- Format Values: Use formatTooltip to display values in user-friendly formats
- Set Reasonable Ranges: Define min/max that match your requirements
Common Use Cases
Volume Control
Use with tooltip showing percentage, marks for mute/low/high.
Temperature Setting
Use with decimal steps and custom formatting (°C/°F).
Price Range Filter
Use range slider with currency formatting.
Rating/Review
Use with step indicators and labeled marks.
Progress Indicator
Use disabled slider to show read-only progress.
Zoom Level
Use with percentage formatting and step indicators.
Browser Support
Works in all modern browsers with full accessibility support.