Forms

Slider

Single- or two-thumb slider implementing the WAI-ARIA slider pattern for picking a value or range along a numeric scale.

import { Slider } from '@lostgradient/cinder';
formnumeric
01

Overview

Reference usage

Drag handle input for selecting a numeric value within a bounded range.

Usage

svelte
<script lang="ts">
  import { Slider } from '@lostgradient/cinder';
</script>

<div style="display: flex; flex-direction: column; gap: 1rem; max-width: 24rem;">
  <Slider label="Volume" value={40} disabled />
</div>

Layout

Slider's root fills its container's inline size (width: 100%), and its outer border box always matches the space you give it — the header row spans that full width, and an equal-width sibling control lines up with the root's edges exactly.

The thumb, track fill, and tick marks do not: they travel along an interval inset by half the rendered thumb's width on each side, so a thumb centered at min or max still keeps its own border box inside the root — it never overhangs past the root's inline edges the way a naive left: 0%/left: 100% placement would. That inset is computed from the actual rendered .cinder-slider__thumb size (--_cinder-slider-thumb-size, 1.125rem by default), so it scales with font-size instead of assuming a fixed pixel diameter.

Pointer interaction follows the same interval: clicking or dragging anywhere in the reserved endpoint margin — including at the track's physical edges — still resolves to min or max. You don't need to add your own padding or a click handler to reach the ends of the range.

Compact headers and formatted values

headerVisible?: boolean (default true) hides the header row's label span. The value span always keeps rendering — hiding the label never leaves an empty gap in its place, and it never changes a thumb's accessible name, which always comes from label regardless of what the header displays.

displayValue replaces only that value span's text: (value: number) => string in single mode, (value: [number, number]) => string in range mode (called once with the full tuple, not once per thumb). It's independent of valueText, which formats aria-valuetext for assistive technology — set both when the visible text and the announced text should differ, or just displayValue to restyle what's shown while keeping the default aria-valuetext behavior.

svelte
<Slider label="Scale" min={0} max={12} value={7} displayValue={(v) => `${v} notes · C4–B4`} />
<Slider
  label="Octave range"
  mode="range"
  min={0}
  max={22}
  value={[0, 22]}
  displayValue={([low, high]) => `${low}–${high}`}
/>

Composing with FormField. Slider already has an automatic mechanism for this: rendered inside <FormField>, it detects the field's label via context and omits its own label span, letting <FormField> own the label through aria-labelledby instead (see Accessible name). headerVisible doesn't replace that mechanism — it composes with it. The label renders only when both are true: headerVisible is true (the default) and the Slider isn't inside a FormField. Set headerVisible={false} for a compact standalone Slider; inside a FormField it's redundant (the label is already suppressed) but harmless, and the value span keeps rendering either way.

Live preview

Single-value slider

Volume 40

Value: 40

02

When to use

Use when
  • Picking a value within a continuous range where visual position communicates magnitude.
  • Selecting a low and high bound together via the range mode.
Avoid when
  • Entering a precise numeric value typed by the user — use number-input instead.
  • Displaying read-only completion — use progress instead.
03

Examples

Single-value slider

A simple slider for one numeric value. Keyboard, mouse, and touch all work.

Disabled slider

A disabled slider does not respond to keyboard or pointer input and is excluded from tab order.

Slider inside FormField

Compose `Slider` with `FormField` for label, helper text, and error wiring.

Range slider

Two thumbs constrained so the low value never exceeds the high value.

Slider with tick marks

Discrete tick marks. When `ticks` is an array, arrow keys step between adjacent ticks.

Slider with formatted value text

Use `valueText` to format the value for screen readers — percentages, currency, dates.

04

Props

Props for slider
Name
Type
Default
Description
mode discriminated-union 'single' Slider mode. "single" renders one thumb and emits a scalar value; "range" renders two thumbs and emits a [low, high] tuple. Default "single".
min number 0 Minimum value. Default 0.
max number 100 Maximum value. Default 100.
value bindable discriminated-union
step number 1 Step increment for arrow keys. Default 1. Must be a positive finite number.
pageStep number Step increment for Page Up/Down. Default step * 10.
label required text Visible label / accessible name for the slider. Required.
valueText (value: number) => string Formats the numeric value for aria-valuetext.
unit text Optional unit displayed with the current value, such as % or ms.
ticks boolean Optional tick marks. true renders one per step; an array snaps to those values.
disabled boolean false Disables interaction.
name text Form field name. Renders hidden inputs for form submission.
onValueChange discriminated-union
headerVisible boolean true Whether the header row renders the visible label span. Default true. Hides only the label — the visible value text always stays, with no layout gap left behind — and never affects the thumbs' accessible names, which come from label regardless. This composes with, rather than replaces, the automatic label suppression a Slider already performs inside <FormField> (the field owns the label there via aria-labelledby, so Slider's own label span is omitted independent of this prop). Setting headerVisible={false} inside a FormField is a no-op for the label — it's already hidden — but still governs the value span the same way it does standalone.
displayValue discriminated-union Formats the visible value text shown in the header. Replaces only the value display — the valueText ARIA formatter is untouched. Absent a formatter, the value renders with the current unit-based formatting.