Sliders
A slider is an input where the user selects a value from within a given range. Sliders typically have a slider thumb that can be moved along a bar, rail, or track to change the value of the slider.
Features
- Labeling, descriptions, and error message displays are automatically linked to input and label elements with
aria-*
attributes. v-model
support for binding the value of the slider and the individual thumbs.- Multi-thumb support with auto value clamping.
- Support for
min
,max
, andstep
attributes. - Support for both horizontal and vertical orientations.
- Support for both LTR and RTL directions.
- Validation with Standard Schema.
- Interactive behaviors:
- Clicking the track element sets the value of the slider or the nearest suitable thumb to the clicked position.
- Dragging the thumb element changes the value of the slider.
- Supported keyboard interactions:
Key | Description |
---|---|
→Right | Increments the slider value of the currently focused thumb. In RTL, it decrements instead. |
←Left | Decrements the slider value of the currently focused thumb. In RTL, it increments instead. |
↑Up | Increments the slider value of the currently focused thumb. |
↓Down | Decrements the slider value of the currently focused thumb. |
Home | Sets the slider value of the currently focused thumb to the minimum possible value. |
End | Sets the slider value of the currently focused thumb to the maximum possible value. |
⇞Page Up | Increments the slider value of the currently focused thumb by a large step. |
⇟Page Down | Decrements the slider value of the currently focused thumb by a large step. |
Anatomy
Building a thumb component
Every slider needs at least one thumb to represent the current value of the slider. This means the slider in Formwerk is a compound component similar to radio buttons.
First, let’s build a thumb component that will be used in the slider later. We will keep styling to a minimum by using a simple circle SVG.
You will be using the useSliderThumb
composable to build the thumb component.
There is nothing to show yet because we need to build the slider component.
Building a slider component
You will be using the useSlider
composable to build the slider component.
The useSlider
composable returns binding objects for the elements shown in the anatomy. You will use v-bind
to bind them to the corresponding DOM elements.
The Slider is what we consider a fully custom component, meaning it doesn’t have an underlying input
base element that you can use. While the input[type="range"]
may be a suitable candidate, it doesn’t scale to support the wide range (pun intended) of use-cases that developers expect of slider inputs today.
Notice that in order to model the slider progress visually, we used the utility composable useThumbMetadata
to calculate the percentage of the thumb position.
Validation
Because sliders in Formwerk are a fully custom component, they don’t support any HTML validation attributes. You can, however, use Standard Schema to validate the value of the slider.
Standard Schema
The useSlider
composable accepts a schema
prop that is an instance of a Standard Schema. This includes multiple providers like Zod, Valibot, Arktype, and more.
Usage
Multiple Thumbs
You can have as many thumbs as you want inside a slider. Just add another <Thumb />
component, and this will be automatically handled for you:
- Min/Max clamping for each thumb.
- Value conversion to an array instead of a single number.
Note that we did change some CSS from the previous examples in order to color the track properly, but it is up to you how you want to do that in any way you want.
Disabled
Use disabled
to mark sliders as non-interactive. Disabled sliders are not validated and are not submitted.
You can also disable any individual Thumb
by passing disabled
to it as well. But it won’t prevent validation/submission of the slider.
Readonly
Readonly sliders are validated and submitted, but they do not accept user input. The slider thumbs would still be focusable. For more info, check the MDN.
RTL
The useSlider
composable accepts a dir
property. You can set it to RTL
, and it will handle thumb positioning automatically along with inverting the horizontal arrow keys (left/right arrows).
Orientation
useSlider
also accepts an orientation
prop. You can set it to either horizontal
(default) or vertical
.
Formwerk will handle most things in either orientation in terms of interaction and thumb positioning. But slider layout is left to you to do.
Here is an example that uses the [aria-orientation]
attribute that is applied automatically. We will use it to flip the slider we initially created with some custom styles.
Discrete Slider Values
You can also use discrete slider values by passing an options
prop to the slider. This is useful for non-numeric values like a rating slider.
When doing this, the slider min/max will be set to the first and last option, and the step will be set to the difference between the first and last option divided by the number of options you want to show. This also means the step
prop is ignored when options
is used.
Generic Types
The slider’s SliderProps
accepts a generic type parameter that allows you to build generically typed slider components.
This gives you auto type inference for the slider’s value even when using the options
prop for any type of value.
Styling
You probably have noticed that the trackProps
and thumbProps
contain some minor styling properties. These are the bare minimum to get the slider working, and they are automatically added for you.
If you are interested in knowing what properties are added, here is a list:
trackProps
style properties:container-type
: is set tosize
orinline-size
depending on the orientation. You should NOT override this property.position
: is set torelative
. You can override this to anything butstatic
.
thumbProps
style properties:position
: is set toabsolute
. You should NOT override this property.translate
: used to position the thumb. You should NOT override this property.will-change
: is set totranslate
. You should NOT override this property.- Any inset position properties like
top
,left
,right
,bottom
are set to0
. You should NOT override these properties.
We were very careful to not add any easily overridden properties to the trackProps
and thumbProps
to avoid any conflicts with your custom styles.
Other than all of that, you can use any styling solution you want, whether it’s TailwindCSS or plain CSS.
Thumb attributes
The thumb element will receive the aria-orientation
attribute, which is the same as the slider’s orientation, so you can style tooltips or other UI elements according to the slider’s orientation.
Slider attributes
The slider element will receive the aria-orientation
attribute, which is the prop you pass to the slider.
API
Thumb
Props
These are the properties that can be passed to the useSliderThumb
composable.
Name | Type | Description |
---|---|---|
disabled | Whether the slider thumb is disabled. | |
formatValue | A function to format the value text of the slider thumb. Used for setting the `aria-valuetext` attribute. | |
label | The label text for the slider thumb. | |
modelValue | The v-model value of the slider thumb. |
Returns
These are the properties in the object returned by the useSliderThumb
composable.
Name | Type | Description |
---|---|---|
currentText | The current formatted value of the thumb. | |
currentValue | The current value of the thumb. | |
isDisabled | Whether the thumb is disabled. | |
isDragging | Whether the thumb is currently being dragged. | |
thumbEl | Reference to the thumb element. | |
thumbProps | Props for the thumb element. |
Slider
Props
These are the properties that can be passed to the useSlider
composable.
Name | Type | Description |
---|---|---|
dir | The text direction of the slider (ltr or rtl). | |
disabled | Whether the slider is disabled. | |
label | The label text for the slider. | |
max | The maximum value allowed for the slider. Ignored if `options` is provided. | |
min | The minimum value allowed for the slider. Ignored if `options` is provided. | |
modelValue | The v-model value of the slider. | |
name | The name attribute for the slider input. | |
options | Discrete values that the slider can accept. | |
orientation | The orientation of the slider (horizontal or vertical). | |
readonly | Whether the slider is readonly. | |
schema | Schema for slider validation. | |
step | The step increment between values. Ignored if `options` is provided. | |
value | The value attribute of the slider input. |
Returns
These are the properties in the object returned by the useSlider
composable.
Name | Type | Description |
---|---|---|
displayError | Display the error message for the field. | |
errorMessage | The error message for the field. | |
errorMessageProps | Ref<{ 'aria-live': "polite"; 'aria-atomic': boolean; id: string; }> | Props for the error message element. |
errors | The errors for the field. | |
fieldValue | The value of the field. | |
groupProps | Ref<{ id: string; role: string; dir: Direction; 'aria-label'?: string; 'aria-labelledby'?: string; }> | Props for the root element for the slider component. |
isDirty | Whether the field is dirty. | |
isDisabled | Whether the field is disabled. | |
isTouched | Whether the field is touched. | |
isValid | Whether the field is valid. | |
labelProps | Props for the label element. | |
outputProps | Props for the output element. | |
setErrors | (messages: Arrayable<string>) => void | Sets the errors for the field. |
setTouched | Sets the touched state for the field. | |
setValue | Sets the value for the field. | |
trackEl | Reference to the track element. | |
trackProps | Ref<{ style: CSSProperties; onMousedown(e: MouseEvent): void; }> | Props for the track element. |
useThumbMetadata |
useThumbMetadata
returns
Additionally, useThumbMetadata
returns a computed object with the following properties:
Name | Type | Description |
---|---|---|
max | The maximum value of the slider. | |
min | The minimum value of the slider. | |
percent | The percent of the slider that the thumb is at. | |
sliderMax | The maximum value of the slider. | |
sliderMin | The minimum value of the slider. | |
sliderPercent | The percent of the slider that the thumb is at. | |
value | The current value of the thumb. |