Skip to main content

Slider

Info:Controls
50

A draggable range control for choosing a single value between a min and max, with full keyboard support.

range range input track value picker volume brightness

Live demo

live · @xtyle/astro

Slider

A settings panel

Volume Brightness Locked

Value readout

Volume Opacity

Fine-tuning & overflow

Drag or arrow for coarse steps; hold Shift for the fine step. Click a value to type it; the scale accepts a value past its max.

Angle Scale

Sizes

Small Medium Large

Every tone

Accents

accent accent-2 accent-3 accent-4 neutral

Statuses

success info warn danger

Named hues

red orange yellow green blue purple brown pink cyan gray white black

Slider picks one number across a range. It renders a rail with a fill showing the chosen portion and a role="slider" thumb carrying aria-valuemin/aria-valuemax/aria-valuenow, so pointer drag, click-to-position, and the full arrow/Page/Home/End keyboard set all move it.

Values snap to step and clamp to [min, max]. Holding the modifier (Shift by default) while stepping or dragging swaps in alt-step for a coarser or finer jump, the same fine-tune contract the number field carries. With show-value, the readout is a click-to-edit numeric field that steps on the same keys; add overflow and a typed value may pass the rail while the thumb pins at the edge. It is form-associated: give it a name and it contributes its current value to form data. Three sizes (sm, the default md, and lg) vary the thumb and rail thickness. It is the primitive the hue and alpha tracks of a color picker compose from.

When to use

How this component composes with the rest of the set.

Pair with Field or a form to capture the value; give it a name so it contributes to submitted data.
Use a tight step for coarse adjustments (a 0–10 rating) or step="1" over a wide range for fine ones.
Give a coarse step a fine alt-step (e.g. step="15" alt-step="1") so a drag snaps to big increments but the modifier unlocks precision; pair with overflow on a bounded rail whose value should occasionally exceed the slider (a scale past 200%).
It is the building block for a color picker's hue and alpha tracks: same rail, fill, and thumb mechanics with a gradient rail.

Props

17 props, straight from the manifest.

PropTypeDefaultBindingsDescription
value number min
html svelte astro
The current value, snapped to `step` and clamped to `[min, max]`. Two-way bindable in Svelte; reflected to `aria-valuenow`.
min number 0
html svelte astro
The lower bound of the range.
max number 100
html svelte astro
The upper bound of the range.
step number 1
html svelte astro
The base granularity: an arrow key and a drag snap to `step`. The finest grid the slider lands on is the smaller of `step` and `alt-step`, so a typed or fine-modifier value can sit between coarse steps.
alt-step number step * 10
html svelte astro
The step taken while the modifier is held during an arrow press or a drag (and by Page keys): set it larger than `step` for a broad jump or smaller for fine-tuning. Mirrors the number field's alt step.
alt-default boolean false
html svelte astro
Inverts the modifier: `alt-step` becomes the unmodified default and the base `step` needs the modifier held.
modifier "shift" | "alt" | "ctrl" | "meta"
shift alt ctrl meta
shift
html svelte astro
Which key swaps `step` for `alt-step` on a keyboard press or a drag. Same contract as the number field, so a form's slider and stepper fine-tune on the same key.
overflow boolean false
html svelte astro
Lets a typed value in the inline editor pass `min`/`max`: the thumb pins at the rail edge while the true value is kept, emitted, and announced (the reported range widens to include it). Drag and arrow-stepping still stay on the rail.
disabled boolean false
html svelte astro
Disables interaction; mutes the fill and thumb, drops the thumb out of the tab order, and sets `aria-disabled`.
size Size
sm md lg
md
html svelte astro
Control size (`sm`, `md`, or `lg`) varying the thumb and rail thickness.
tone FullTone
accent neutral danger success warn info accent-2 accent-3 accent-4 red orange yellow green blue purple brown pink cyan gray white black
accent
html svelte astro
Color of the rail fill and thumb. Any of the semantic roles, accent variants, or named hues.
label string
html svelte astro
Visible label, also wired as the accessible name via `aria-labelledby`.
labelledby string
html svelte astro
ID of an external element that names the slider. Takes precedence over `label`.
name string
html svelte astro
Form field name; the slider contributes its current value to submitted form data.
show-value boolean false
html svelte astro
Renders the current value inline beside the label. Clicking it opens an inline numeric editor that types an exact value and steps on the arrow/Page keys (honoring `modifier` and `alt-step`). The readout is `aria-hidden` since the thumb's `aria-valuenow` already announces it. Format it with the `format` property.
hide-label boolean false
html svelte astro
Visually hides the `label` text while still using it to name the control for assistive tech. Use it when the host already renders its own visible label but the slider still needs an accessible name.
format (value: number) => string
html svelte
A JS property (not an attribute) on the element: a function that formats the `show-value` readout. Defaults to the raw number. Settable in the HTML binding and via `bind:format` in Svelte; not available in the static Astro binding.

Appearance

Sizes

sm

.xtyle-slider--sm

Compact: thin rail, small thumb.

md

default
.xtyle-slider

Default.

lg

.xtyle-slider--lg

Large: thicker rail, bigger thumb for touch.

States

hover

.xtyle-slider__thumb:hover::after

Pointer over the thumb. Overlay paints the hover tint.

active

.xtyle-slider__thumb:active::after

Thumb pressed or dragging. Overlay paints the press tint.

focus-visible

.xtyle-slider__thumb:focus-visible

Keyboard focus on the thumb: a token-colored ring, plus a transparent outline that becomes real in forced-colors mode.

disabled

.xtyle-slider--disabled

Non-interactive: muted fill and thumb, thumb removed from the tab order.

Anatomy

The named parts that make up the component, with their selectors.

slider

.xtyle-slider

The column wrapper carrying the size and disabled classes and stacking the optional label above the rail.

--font-sans --text-body --leading-tight --fg-0 --space-2

rail

.xtyle-slider__rail

The interactive track the thumb travels along; its ::before paints the unfilled groove.

--space-5 --space-2 --radius-full --neutral-bg --border-thin --line-2

fill

.xtyle-slider__fill

The accent-colored portion of the rail from the minimum to the current value.

--accent --radius-full

thumb

.xtyle-slider__thumb

The draggable role="slider" knob positioned at the current value.

--space-5 --radius-full --bg-0 --border-normal --accent --elevation-1

header

.xtyle-slider__header

The row above the rail that lays out the label and value readout on opposite ends when either is shown.

--space-2

label

.xtyle-slider__label

The optional visible label that names the slider and is referenced as its accessible name.

--fg-1 --text-sm

value

.xtyle-slider__value

The optional inline readout of the current value, shown when show-value is set and formatted by the format property.

--fg-1 --text-sm

overlay

.xtyle-slider__thumb::after

The pseudo-element on the thumb that paints hover and active state tints.

--state-hover --state-press

Tokens & coverage

What the component consumes, checked live against what the algorithm produces.

Success:fully covered 50/50 consumed tokens produced default register: 299 tokens

Live coverage check against the xtyle-default register (derive(xtyleDefault, { anchors })coverComponent(manifest, register)). Every token this component consumes must be a key the algorithm produces.

--accent --accent-2 --accent-3 --accent-4 --bg-0 --black --blue --border-normal --border-thick --border-thin --brown --cyan --danger --duration-fast --ease-standard --elevation-1 --fg-0 --fg-1 --fg-disabled --field-bg --field-border --font-sans --gray --green --info --leading-tight --line-2 --neutral --neutral-bg --orange --pink --purple --radius-full --radius-sm --red --ring --space-1 --space-2 --space-4 --space-5 --space-6 --state-disabled --state-hover --state-press --success --text-body --text-sm --warn --white --yellow

Accessibility

The thumb is role="slider" with aria-valuemin, aria-valuemax, and aria-valuenow kept in sync, never conveying value by position alone.
Full keyboard support: arrows move by step (by alt-step with the modifier held), PageUp/PageDown by alt-step, Home/End jump to min/max; the keys' default scroll is prevented.
Under overflow, a typed value past the rail keeps aria-valuenow valid by widening the announced aria-valuemin/aria-valuemax to include it, rather than misreporting a pinned value.
Requires an accessible name: labelledby wins, then label; the binding warns at runtime when neither is present. hide-label keeps the label as the accessible name while visually hiding its text, so a host that renders its own label avoids announcing the name twice.
The show-value readout is aria-hidden so screen readers hear the value once via the thumb's aria-valuenow, not twice.
Pointer drag uses pointer capture so the thumb keeps tracking even when the cursor leaves the rail.
Focus is shown with a token ring and a transparent outline the forced-colors base rule promotes to a real system outline.
disabled blocks interaction, mutes the visuals, and pulls the thumb out of the tab order with aria-disabled.

Code

Ranges, sizes, and form association

A labeled slider, a stepped range, the compact size, a form-bound slider, and a disabled one.

<xtyle-slider label="Volume" value="60"></xtyle-slider>

<xtyle-slider label="Brightness" min="0" max="100" step="5" value="40"></xtyle-slider>

<xtyle-slider size="sm" label="Compact" value="25"></xtyle-slider>

<xtyle-slider label="Opacity" name="opacity" value="80"></xtyle-slider>

<xtyle-slider label="Volume" value="60" show-value></xtyle-slider>

<xtyle-slider id="pct" label="Opacity" value="80" show-value></xtyle-slider>
<script>
	document.getElementById("pct").format = (v) => v + "%";
</script>

<xtyle-slider label="Volume" value="60" hide-label></xtyle-slider>

<xtyle-slider label="Locked" value="50" disabled></xtyle-slider>
<script lang="ts">
	import { Slider } from "@xtyle/svelte";

	let volume = $state(60);
</script>

<Slider label="Volume" bind:value={volume} />

<Slider label="Brightness" min={0} max={100} step={5} value={40} />

<Slider size="sm" label="Compact" value={25} />

<Slider label="Opacity" name="opacity" value={80} />

<Slider label="Volume" value={60} showValue />

<Slider label="Opacity" value={80} showValue format={(v) => `${v}%`} />

<Slider label="Volume" value={60} hideLabel />

<Slider label="Locked" value={50} disabled />
---
import { Slider } from "@xtyle/astro";
---

<Slider label="Volume" value={60} />

<Slider label="Brightness" min={0} max={100} step={5} value={40} />

<Slider size="sm" label="Compact" value={25} />

<Slider label="Opacity" name="opacity" value={80} />

<Slider label="Volume" value={60} showValue />

<Slider label="Volume" value={60} hideLabel />

<Slider label="Locked" value={50} disabled />

Fine-tuning and overflow

A coarse-step angle that fine-tunes to 1° while Shift is held, and a scale whose editable readout accepts a value past the rail's max.

<!-- Coarse 15° steps; hold Shift while dragging or arrowing for 1° fine-tuning. -->
<xtyle-slider label="Angle" min="-180" max="180" step="15" alt-step="1" value="45" show-value></xtyle-slider>

<!-- overflow: type a scale past 200 in the readout; the thumb pins at the rail edge. -->
<xtyle-slider label="Scale" min="10" max="200" step="5" alt-step="1" value="100" show-value overflow></xtyle-slider>
<script lang="ts">
	import { Slider } from "@xtyle/svelte";
</script>

<!-- Coarse 15° steps; hold Shift while dragging or arrowing for 1° fine-tuning. -->
<Slider label="Angle" min={-180} max={180} step={15} altStep={1} value={45} showValue format={(v) => `${v}°`} />

<!-- overflow: type a scale past 200 in the readout; the thumb pins at the rail edge. -->
<Slider label="Scale" min={10} max={200} step={5} altStep={1} value={100} showValue overflow format={(v) => `${v}%`} />
---
import { Slider } from "@xtyle/astro";
---

<Slider label="Angle" min={-180} max={180} step={15} altStep={1} value={45} showValue />

<Slider label="Scale" min={10} max={200} step={5} altStep={1} value={100} showValue overflow />