Slider
Picks a number from a range by dragging or with the arrow keys.
import '@usezeno/tokens/css';
import '@usezeno/core/web-components';
Examples
Basic
min, max and step set the range. The input event fires while the value moves and change fires when it is set. Both carry the number in event.detail.value.
Value: 16
<zeno-slider label="Font size" min="12" max="24" step="2" value="16"></zeno-slider>
<p data-result>Value: 16</p>
document.querySelector('zeno-slider').addEventListener('input', event => {
document.querySelector('[data-result]').textContent = 'Value: ' + event.detail.value;
});
Sizes
<zeno-slider label="Small" size="sm" value="25"></zeno-slider>
<zeno-slider label="Medium" size="md" value="50"></zeno-slider>
<zeno-slider label="Large" size="lg" value="75"></zeno-slider>
Marks
show-marks draws a tick at the minimum and at the maximum. The marks property takes a list of values, each with an optional label. The labels are drawn below the element’s own box, so this example leaves space under each slider.
<div style="padding-bottom: 2rem">
<zeno-slider label="Brightness" value="30" show-marks></zeno-slider>
</div>
<div style="padding-bottom: 2rem">
<zeno-slider label="Quality" value="50" step="50"></zeno-slider>
</div>
document.querySelectorAll('zeno-slider')[1].marks = [
{ value: 0, label: 'Low' },
{ value: 50, label: 'Medium' },
{ value: 100, label: 'High' },
];
States
The error text shows below the slider and colours the fill.
<zeno-slider label="Disabled" value="60" disabled></zeno-slider>
<zeno-slider label="With an error" value="90" error="Choose 80 or less."></zeno-slider>
In a form
A slider always has a value, so it is always sent with the form. With no value it sends the minimum.
<form>
<zeno-slider name="volume" label="Volume" value="40"></zeno-slider>
<zeno-button type="submit">Save</zeno-button>
<zeno-button type="reset" variant="ghost">Reset</zeno-button>
<p data-result>Nothing submitted yet.</p>
</form>
const form = document.querySelector('form');
form.addEventListener('submit', event => {
event.preventDefault();
const sent = [...new FormData(form)].map(([name, value]) => name + '=' + value);
document.querySelector('[data-result]').textContent = 'Submitted: ' + sent.join('&');
});
Attributes and properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
min | min | number | 0 | |
max | max | number | 100 | |
step | step | number | 1 | |
size | sizereflects | 'sm' | 'md' | 'lg' | 'md' | |
showTooltip | show-tooltipreflects | boolean | false | |
showMarks | show-marksreflects | boolean | false | |
marks | marks | Array<{ value: number; label?: string }> | ||
formatTooltip | (_value: number) => string | |||
formatValue | (_value: number) => string | |||
value | value | FormValue | '' | From FormFieldMixin. |
name | namereflects | string | From FormFieldMixin. | |
required | requiredreflects | boolean | false | From FormFieldMixin. |
disabled | disabledreflects | boolean | false | From FormFieldMixin. |
readonly | readonlyreflects | boolean | false | From FormFieldMixin. |
error | error | string | An error to show, for example one a server returned. From FormFieldMixin. | |
label | label | string | A visible label. An outside <label for> works as well. From FormFieldMixin. | |
hideRequiredIndicator | hide-required-indicator | boolean | false | From FormFieldMixin. |
touched | boolean | false | True once the user has left the control or a submit was refused. From FormFieldMixin. | |
dirty | boolean | false | True once the user has changed the value. From FormFieldMixin. | |
defaultValue | FormValue | '' | The value the control goes back to when its form is reset. From FormFieldMixin. | |
formread only | HTMLFormElement | null | From FormFieldMixin. | ||
labelsread only | NodeList | From FormFieldMixin. | ||
validityread only | ValidityState | From FormFieldMixin. | ||
validationMessageread only | string | From FormFieldMixin. | ||
willValidateread only | boolean | From FormFieldMixin. | ||
isDisabledread only | boolean | True when the element or an ancestor fieldset disables it. From FormFieldMixin. | ||
invalidread only | boolean | True when the control should look invalid. From FormFieldMixin. | ||
testId | string | Test ID for automated testing From ZenoElement. |
Methods
| Method | Description |
|---|---|
focus(options?: FocusOptions): void | Focus the component or its first focusable element From ZenoElement. |
blur(): void | Blur the component or its focused element From ZenoElement. |
checkValidity(): boolean | Reports whether the value is valid without showing anything. Use reportValidity() or validate() to show the result as well. From FormFieldMixin. |
reportValidity(): boolean | From FormFieldMixin. |
setCustomValidity(message: string): void | From FormFieldMixin. |
validate(): boolean | Checks validity and shows the result on the control. From FormFieldMixin. |
Events
| Event | Detail | Description |
|---|---|---|
input | { value: number } | The value changed while dragging. |
change | { value: number } | The value was committed. |
Slots
This element has no slots.
CSS parts
| Part |
|---|
base |
error |
fill |
label |
marks |
thumb |
tooltip |
track |
CSS custom properties
This element documents no custom properties of its own. Style it through its parts and through the tokens it reads.
The element's own source reads no tokens.
Types
type FormValue = string | number | boolean | Date | null | undefined;
Accessibility
Keyboard
| Key | What it does |
|---|---|
| Tab | Moves focus to the slider. |
| ArrowRightArrowUp | Raises the value by one step. |
| ArrowLeftArrowDown | Lowers the value by one step. |
| HomeEnd | Sets the value to the minimum or the maximum. |
| PageUpPageDown | Raises or lowers the value by a larger amount. The browser sets the amount. |
Forms
- With a
name, the element adds its value to the data of the form it is in, and is left out while it is disabled. - It is labelled by its
labelattribute or by a<label for>that points at itsid. - It takes part in validation:
checkValidity(),reportValidity()andsetCustomValidity()work, and an invalid element blocks the submit and matches:invalid. - It follows a
<fieldset disabled>around it and goes back to its first value when the form is reset. - The messages it writes itself, such as “Please fill out this field.”, are in English only.
Notes
- The control is a native
<input type="range">. It lies over the drawn track and is transparent, so pointer and keyboard input go to the native input. All keys in the table come from it. - The drawn thumb has
role="presentation". The track, fill and marks are plain elements with no role. - The
labelattribute renders a<label>for the input. Without it, the name comes from an outside<label for>or fromaria-labelon the element. - The input has
aria-valuetextwith the value as text. Set theformatValueproperty to a function to read the value with a unit. - When the slider is invalid, the input has
aria-invalid="true"andaria-describedbypoints at the error text.
Tests and known gaps
- Tested in a real browser by
slider.test.ts. - Checked with axe-core in the light and the dark theme.
- Has no Storybook story.
30 of the 44 properties, methods, events, slots and parts above have no description in the source
- the property
min - the property
max - the property
step - the property
size - the property
showTooltip - the property
showMarks - the property
marks - the property
formatTooltip - the property
formatValue - the property
value - the property
name - the property
required - the property
disabled - the property
readonly - the property
hideRequiredIndicator - the property
form - the property
labels - the property
validity - the property
validationMessage - the property
willValidate - the method
reportValidity() - the method
setCustomValidity() - the part
base - the part
error - the part
fill - the part
label - the part
marks - the part
thumb - the part
tooltip - the part
track
Known gaps:
- The thumb and the
show-tooltipbubble are inside the track, and the track hasoverflow: hidden. They are cut off at the edge of the track, so the round thumb and the tooltip do not show. - Keyboard focus has no visible indicator. The focus ring is a shadow on the thumb, which the track cuts off, and the native input is transparent.
- The row of marks has no height, because every mark is positioned absolutely. Mark labels overlap the content that follows the slider.
- The
readonlyattribute does nothing. A read-only slider can still be moved. - A
valueoutsideminandmaxis not clamped. The element submits the value as it is. The native input inside it is limited to the range, so the two do not agree.