Inputs
Slider
Range input built on Bits UI with a single thumb or two thumbs, plus min, max and step.
<script>
import { Slider } from "@codeatlasdev/ui";
let volume = $state(60);
let range = $state([20, 75]);
</script>
<Slider bind:value={volume} />
<Slider bind:values={range} />
value and values are independent: bind one or the other. The slider has no built-in label or value readout, so render those next to it as the demos do. Arrow keys move by step, Home and End jump to the bounds.
Single value
Binds a plain number. Default range is 0 to 100.
Code
<script lang="ts">
import { Slider } from '@codeatlasdev/ui';
let volume = $state(60);
let brightness = $state(40);
</script>
<div class="col">
<div class="row">
<span class="label">Volume</span>
<Slider bind:value={volume} min={0} max={100} />
<span class="val">{volume}</span>
</div>
<div class="row">
<span class="label">Brightness</span>
<Slider bind:value={brightness} min={0} max={100} />
<span class="val">{brightness}%</span>
</div>
</div>
<style>
.col {
display: flex;
flex-direction: column;
gap: var(--ca-space-5);
width: 100%;
max-width: 480px;
}
.row {
display: flex;
align-items: center;
gap: 14px;
}
.label {
flex-shrink: 0;
min-width: 76px;
font-size: var(--ca-font-size-body2);
color: var(--ca-text-secondary);
}
.val {
flex-shrink: 0;
min-width: 64px;
text-align: right;
font-family: var(--ca-font-mono);
font-size: var(--ca-font-size-body2);
font-weight: 600;
color: var(--ca-brand-text);
}
</style>
Range
Bind a [min, max] tuple to values for two thumbs.
Code
<script lang="ts">
import { Slider } from '@codeatlasdev/ui';
let range = $state<[number, number]>([20, 75]);
</script>
<div class="row">
<span class="label">Price</span>
<Slider bind:values={range} min={0} max={100} />
<span class="val">${range[0]} – ${range[1]}</span>
</div>
<style>
.row {
display: flex;
align-items: center;
gap: 14px;
width: 100%;
max-width: 480px;
}
.label {
flex-shrink: 0;
min-width: 76px;
font-size: var(--ca-font-size-body2);
color: var(--ca-text-secondary);
}
.val {
flex-shrink: 0;
min-width: 88px;
text-align: right;
font-family: var(--ca-font-mono);
font-size: var(--ca-font-size-body2);
font-weight: 600;
color: var(--ca-brand-text);
}
</style>
Step and disabled
step={10} snaps to increments of 10.
Code
<script lang="ts">
import { Slider } from '@codeatlasdev/ui';
let stepped = $state(50);
</script>
<div class="col">
<div class="row">
<span class="label">Step 10</span>
<Slider bind:value={stepped} min={0} max={100} step={10} />
<span class="val">{stepped}</span>
</div>
<div class="row">
<span class="label">Disabled</span>
<Slider value={35} disabled />
<span class="val">35</span>
</div>
</div>
<style>
.col {
display: flex;
flex-direction: column;
gap: var(--ca-space-5);
width: 100%;
max-width: 480px;
}
.row {
display: flex;
align-items: center;
gap: 14px;
}
.label {
flex-shrink: 0;
min-width: 76px;
font-size: var(--ca-font-size-body2);
color: var(--ca-text-secondary);
}
.val {
flex-shrink: 0;
min-width: 64px;
text-align: right;
font-family: var(--ca-font-mono);
font-size: var(--ca-font-size-body2);
font-weight: 600;
color: var(--ca-brand-text);
}
</style>
Props
| Prop | Type | Default | Description |
|---|
value | number | – | Single-value mode: bind a plain number. Defaults to the midpoint when neither value nor values is set. |
values | [number, number] | – | Range mode: bind a [min, max] tuple. |
min | number | 0 | Minimum value. |
max | number | 100 | Maximum value. |
step | number | 1 | Step increment. |
disabled | boolean | false | Disables the slider. |
class | string | – | Extra classes on the root. |
onchange | (value: number[]) => void | – | Called on change. Always receives an array: one number in single mode, two in range mode. |