Slider
Numeric slider with single and range modes, step snapping, tick marks, and touch support.
Playground
<Slider
label="Volume"
showValue
/>01 Examples
Price filter (range mode)
<div class="border-border-subtle bg-surface-elevated w-full space-y-3 rounded-2xl border p-5">
<Slider
label="Price Range"
range
bind:value={priceRange}
min={0}
max={1000}
step={25}
showValue
intent="success"
formatValue={(v) => {
if (Array.isArray(v)) return `$${v[0]} – $${v[1]}`;
return `$${v}`;
}}
/>
</div>With Marks
step snaps the thumb to whole increments.<Slider
label="Temperature"
bind:value={temperature}
min={16}
max={30}
step={1}
showValue
formatValue={(v) => `${v}°C`}
marks={[
{ value: 16, label: '16°' },
{ value: 20, label: '20°' },
{ value: 24, label: '24°' },
{ value: 28, label: '28°' },
{ value: 30, label: '30°' }
]}
/>Valid & Recommended Range
<Slider
label="Consumption-based share of heating costs"
bind:value={consumptionShare}
min={0}
max={100}
step={5}
validRange={[50, 100]}
recommendedRange={[60, 80]}
showValue
formatValue={(v) => `${v} %`}
rangeStatusText={{
insideRecommended: 'Billing-regulation standard (recommended)',
insideValidOnly: 'Compliant with the billing regulation, but outside the recommendation',
outsideValid: 'Billing-regulation violation: at least 50 % must be consumption-based'
}}
/>
<Slider
label="Hot water temperature"
bind:value={waterTemperature}
min={40}
max={80}
step={1}
validRange={[60, 80]}
showValue
formatValue={(v) => `${v} °C`}
rangeStatusText={{
insideRecommended: 'Legionella protection satisfied',
outsideValid: 'Legionella risk: at least 60 °C recommended'
}}
/>
<Slider
label="Payback period"
bind:value={amortYears}
min={0}
max={30}
step={1}
recommendedRange={[10, 20]}
outOfValidRangeIntent="warning"
showValue
formatValue={(v) => `${v} years`}
rangeStatusText={{
insideRecommended: 'Economically viable corridor',
insideValidOnly: 'Outside the typical corridor'
}}
/>Helper & Error
error overrides helper when both are set.<Slider
label="Brightness"
bind:value={brightness}
showValue
formatValue={(v) => `${v}%`}
helper="Adjust screen brightness"
/>
<Slider
label="Budget"
value={0}
showValue
formatValue={(v) => `$${v}`}
error="Please set a budget above $0"
/>02 Customization
Slot Overrides
<Slider
label="Opacity"
value={40}
showValue
formatValue={(v) => `${v}%`}
slotClasses={{
track: 'h-1 bg-primary/15',
range: 'bg-primary',
thumb: 'size-5 border-2'
}}
/>unstyled removes all default classes while role="slider", pointer capture, and keyboard stepping
keep working — rebuild track and thumb through slotClasses. A control skin shared across sliders (e.g.
a media-player look) belongs in a BlocksProvider preset (presets.Slider) — see Customization.
03 Accessibility
ARIA Slider
Each thumb uses role="slider" with aria-valuemin, aria-valuemax, aria-valuenow, and aria-label. In range mode, thumbs are labelled
"minimum" and "maximum" for clear identification.
Keyboard
Arrow Right/Up increases by step, Arrow Left/Down decreases. Page Up/Down moves by 10x step. Home/End jump to min/max.
Touch Support
Uses Pointer Events for unified mouse, touch, and pen support. The touch-none CSS property prevents browser scroll interference
during thumb dragging.
Focus & Color
Focus rings use focus-visible: for keyboard-only visibility.
Intent colors are paired with shape (filled track vs. outlined thumb) so the control remains usable
without color perception.
04 API Reference
Prop | Type | Default | Description | |
|---|---|---|---|---|
class | string | — | Extra classes merged onto the root wrapper. | |
disabled | boolean | false | Whether the Slider is disabled and non-interactive | |
error | string | — | Error message below the slider. Overrides helper. | |
formatValue | (value: number | [number, number]) => string | — | Format function for the displayed value. | |
helper | string | — | Helper text below the slider. Hidden when error is set. | |
intent variant | dangerneutralprimarysecondary +2 more | primary | Controls the color theme and semantic meaning of the Slider. Affects the overall appearance and user perception. Available options: danger, neutral, primary, and 3 more. | |
label | string | — | Text label displayed above the slider. | |
marks | SliderMark[] | — | Tick marks along the track. | |
max | number | 100 | Maximum allowed value. | |
messageType variant | errorhelper | helper | Controls the messageType behavior and appearance of the Slider component. Available options: error, helper. | |
min | number | 0 | Minimum allowed value. | |
mint | MintProp | 'none' | Micro-interaction preset applied to the slider's interactive area (the
base slot — not the visual track slot). Only applies while not
disabled. | |
name | string | — | Shared name for hidden inputs for form submission. | |
onValueChange | (value: number | [number, number]) => void | — | Fires after the value changes. Receives the new value. | |
outOfValidRangeIntent | dangerwarning | 'danger' | Intent applied outside the validRange. 'warning' for softer limits
(recommendation, not a violation), 'danger' for hard limits. | |
preset | string | — | Apply a named preset registered via <BlocksProvider presets={{ Slider: {...} }}>.
Prefer this over class overrides when the requested look falls outside the
semantic intent palette — presets keep hover/active/dark-mode logic coherent
and make the custom look reusable across the project. | |
range | boolean | false | Enable range mode with two thumbs. | |
rangeStatusText | SliderRangeStatusText | — | Custom status texts for the three zones. Defaults to the UIB i18n
localization (bt('slider.rangeStatus.*')). | |
recommendedRange | [number, number] | — | Recommended value range (UX recommendation, softer than validRange).
Values inside appear green, values outside yellow (warning). Typically
recommendedRange ⊂ validRange, but this is not enforced. | |
showValue | boolean | false | Show the current value next to the label. | |
size variant | lgmdsm | md | Controls the dimensions, padding, and text size of the Slider. Affects the component's physical footprint. Available options: lg, md, sm. | |
slotClasses | Partial<Record<SliderSlots, string>> | — | Per-slot class overrides merged with tv() styles. Slots: wrapper (root —
what class also targets) | header | label | valueText | base (the
interactive track container) | track | range | thumb | mark | boundaryTick
| rangeStatus | rangeStatusIcon | message. | |
step | number | 1 | Snap to increments of this value. | |
unstyled | boolean | — | Remove all default tv() classes. | |
validRange | [number, number] | — | Valid value range (e.g. a legal limit). Values outside it style track and
thumb in the outOfValidRangeIntent color (default: danger). Status
changes are announced via an ARIA live region. If the range lies outside
[min, max], a console warning is emitted — the visible min/max are
NOT shifted automatically. | |
value | number | [number, number] | — | Current value. Number for single, [min, max] tuple for range. Supports bind:value. | |
variant variant | defaultrail | default | Controls the visual style and presentation of the Slider. Determines the component's visual treatment. Available options: default, rail. | |
...HTMLAttributes<HTMLDivElement> inherited | HTMLAttributes | — | HTML attributes (excluding: 'children' | 'class') | |
...SliderVariants variant | VariantProps | — | Styling variants from SliderVariants |
05 Types
Local type definitions used by this component.
Name | Kind | Category | Used by | Description | |
|---|---|---|---|---|---|
SliderMark | interface | helper | 1 | A labelled tick mark on the slider track. | |
SliderRangeStatusText | interface | helper | 1 | Display texts for the three range status zones (validRange/recommendedRange).
Only shown when validRange and/or recommendedRange are set. Missing
texts fall back to the UIB i18n localization. | |
SliderProps | interface | props | 0 | — | |
SliderVariants | type | variant | 0 | — | |
SliderSlots | type | variant | 0 | Slot names derived from the tv() config above — single source of truth for slotClasses. | |
MintProp | type | helper | 1 | — | |
MintName | type | helper | 0 | A mint name: a built-in (autocompleted), 'none' to disable, or any
consumer-registered name. (string & {}) keeps the registry open — a
custom name still type-checks, it just isn't suggested. A typo therefore
also still compiles (it resolves like an unregistered custom name and
warns at runtime); the union buys completion and docs, not validation. | |
MintConfig | interface | helper | 0 | — | |
BuiltinMintName | type | helper | 0 | Built-in mint names as a literal union, so the mint prop autocompletes
across every component — the single list the hand-curated playground knobs
and docs used to drift away from. |
06 Installation
Import
import { Slider } from '@urbicon-ui/blocks';