Slider
Accessible, unstyled native range slider with controlled and uncontrolled state.
| Package | @vizejs/ui/slider |
| Maturity | stable |
| Own the source | vize lib pull slider |
| Requires | controllable-state, id |
| Aliases | range input, single-thumb slider, volume slider |
| Covers | HTML range input, WAI-ARIA Slider, React Aria Slider |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/ui
Add the public import below to <script setup lang="ts">. Components provide behavior without styles; the preview uses optional Paper styles.
import { Slider } from "@vizejs/ui/slider";
Or copy the source into your project with vize lib pull slider (see Source Distribution).
Try it
This is the basic example maintained with the component source, using the public package imports. The preview adds the optional Paper styles.
Open the interactive example · Styling these components
Copy the example
<!-- Controlled range slider labelled by a native label element. -->
<script setup lang="ts">
import { ref, useId } from "vue";
import { Slider } from "@vizejs/ui/slider";
const volume = ref(40);
const sliderId = useId();
</script>
<template>
<div>
<label :for="sliderId">Volume</label>
<Slider :id="sliderId" v-model="volume" name="volume" :step="5" />
<output :for="sliderId">{{ volume }}%</output>
</div>
</template>
API
Slider
Source: src/families/form/slider/slider.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string | null |
undefined |
Consumer-owned control id. null and undefined select a deterministic fallback. |
name |
string |
undefined |
Native form field name submitted by the range input. |
modelValue |
number |
undefined |
Controlled numeric value. undefined selects uncontrolled behavior. |
defaultValue |
number |
undefined |
Initial value for uncontrolled use and the value restored by form reset. |
min |
number |
0 |
Native lower bound. |
max |
number |
100 |
Native upper bound. Values less than or equal to min are repaired to min + 1. |
step |
SliderStep |
1 |
Native positive step, or "any" for browser-owned arbitrary precision. |
disabled |
boolean |
false |
Disable editing, focus, and native form submission. |
readOnly |
boolean |
false |
Keep the slider focusable while preventing user value changes. |
required |
boolean |
false |
Mark the slider as required for native constraint validation. |
orientation |
SliderOrientation |
"horizontal" |
Logical orientation exposed to ARIA and data attributes. |
dir |
SliderDirection |
"ltr" |
Text direction applied to the native range input. |
ariaLabel |
string |
undefined |
Accessible name when no label or aria-labelledby supplies one. |
ariaLabelledby |
string |
undefined |
Space-separated ids that label the slider. |
ariaDescribedby |
string |
undefined |
Space-separated ids that describe the slider. |
ariaErrormessage |
string |
undefined |
Id of the validation error message used while invalid. |
ariaValueText |
string |
undefined |
Human-readable value text for assistive technology. |
ariaInvalid |
SliderAriaInvalid |
false |
Invalid state announced to assistive technology. |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue |
[value: number] |
Fired when the value requests a new controlled number. |
input |
[value: number, nativeEvent: Event] |
Fired after a native input event with the next number and native Event. |
change |
[value: number, nativeEvent: Event] |
Fired after native change/commit with the current number and native Event. |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
SliderSlotState |
Renders optional marks or output with the normalized Slider state. |
Exposed
| Member | Type | Description |
|---|---|---|
value |
number |
Current normalized numeric value. |
min |
number |
Normalized lower bound. |
max |
number |
Normalized upper bound. |
step |
SliderStep |
Normalized positive step, or "any" for browser-owned precision. |
percent |
number |
Current position from 0 to 100. |
orientation |
SliderOrientation |
Logical orientation. |
direction |
SliderDirection |
Text direction used by the native range input. |
disabled |
boolean |
Whether native activation, focus, and form submission are disabled. |
readOnly |
boolean |
Whether the slider remains focusable while user value changes are locked. |
required |
boolean |
Whether native constraint validation marks the field required. |
invalid |
boolean |
Whether assistive technology should announce the slider as invalid. |
state |
SliderState |
Stable state token for styling and tests. |
root |
HTMLSpanElement | null |
Rendered root element that owns the data and CSS custom property contract. |
element |
HTMLInputElement | null |
Rendered native range input. |
focus |
(options?: FocusOptions) => void |
Move focus to the native range input. |
setValue |
(value: number) => boolean |
Request a value update and report whether it differs. |
stepUp |
(steps?: number) => boolean |
Increase the value by one or more normalized steps. |
stepDown |
(steps?: number) => boolean |
Decrease the value by one or more normalized steps. |
reset |
() => boolean |
Restore the current default value and report whether it changed. |
Behavior
Normative state x input -> outcome table for slider.vue (@vizejs/ui/slider).
Every row is proven by the named mounted-DOM or SSR test; a row without a
passing test is a contract violation.
| # | State | Input | Outcome | Proven by |
|---|---|---|---|---|
| S1 | named, bounded | render | headless root with native <input type="range">, deterministic id, form attributes, ARIA field state, parts, data attributes, and CSS vars |
renders a named native range input with form and accessibility hooks |
| S2 | uncontrolled | native input | clamps/snaps the next value, emits update:modelValue before input, updates form value, data attributes, CSS vars, slot state, and expose |
uncontrolled slider updates native form value and slot state |
| S3 | controlled | native input | emits the requested value and input; rendered value returns to modelValue until the parent accepts the update |
controlled value wins until the parent accepts the request |
| S4 | uncontrolled, seeded | form reset | defaultValue seeds initial state and form reset restores it without request-global state |
defaultValue seeds state and native form reset restores it |
| S5 | focusable | keyboard | native range keyboard behavior remains available for editable sliders while the exposed API can focus and step the value | exposes focus, setValue, stepUp, stepDown, reset, and normalized state |
| S6 | disabled | Tab / form | native disabled, data-state="disabled", no sequential focus, and no submitted form value |
disabled and read-only sliders keep availability semantics |
| S7 | read-only | pointer / key | remains focusable with aria-readonly and form value, while user pointer/key/input/change attempts are prevented or restored |
disabled and read-only sliders keep availability semantics |
| S8 | vertical RTL, invalid | render / SSR | orientation, dir, aria-orientation, aria-invalid, aria-valuetext, and repaired numeric bounds are stable across SSR and hydration |
renders byte-identical native slider markup across isolated SSR requests |
Public extension contract
| Surface | Contract |
|---|---|
| Parts | root on the host <span>; control on the native range input. |
| Data attributes | data-vize-ui, data-state, data-orientation, data-dir, data-value, data-min, data-max, data-step, and data-percent. |
| Boolean data hooks | data-disabled, data-readonly, data-required, and data-invalid are present as "true" only while active. |
| CSS custom properties | --vize-slider-value, --vize-slider-min, --vize-slider-max, --vize-slider-step, and --vize-slider-percent are set on the root. |
| Slot | The default slot receives SliderSlotState for optional output, marks, and native CSS authored by consumers. |
The subpath remains tree-shakable and retains no packaged CSS; those package
contracts are pinned by distribution.test.ts, check:size, and
check:tree-shaking.