Slider
On this page
This is a real <input type="range"> — arrow keys, Home and End, and the correct announcement all come from the browser. Only the track and thumb are styled.
Basic slider
sliderField({ label: 'Quality', name: 'quality', value: 70 })Range and step
stack({ gap: 'lg' },
sliderField({ label: 'Volume', name: 'volume', min: 0, max: 100, value: 40 }),
sliderField({ label: 'Columns', name: 'columns', min: 1, max: 6, step: 1, value: 3 }),
sliderField({ label: 'Scale', name: 'scale', min: 0.5, max: 2, step: 0.25, value: 1 }),
)Showing the value
showValue puts an <output> beside the track carrying the value the page was built with, and the input fetches its own handler on the first drag, so the number follows the thumb. There is nothing to import: a value that silently went stale would be worse than no value at all, so this one is not left to you.
sliderField({
label: 'Image quality',
name: 'jpeg-quality',
min: 40,
max: 100,
value: 82,
showValue: true,
help: 'Higher is larger and slower to build.',
})Setting it from your own code
A slider is a form control, so the reader owns it — but a preset, a reset button, or a value arriving over the network still has to be able to move it. Give it an id and setSlider does, taking the <output> with it.
import { setSlider } from 'sitelo/ui/client'
setSlider('volume', 50)Or reach the module the way the components reach theirs, and skip the bundle entirely:
button({ onclick: "import('/su/slider.js').then(m=>m.set('volume',50))" }, 'Half')The browser clamps to min and max and snaps to step, so what comes back is where the slider landed rather than what it was handed. input and change follow, because a preview listening for the drag has no other way to hear a move it did not cause. getSlider() reads the value back.
Try it
This page loads the runtime, so the buttons below really do move the slider.
stack({ gap: 'md' },
slider({ id: 'demo-slider', value: 40, showValue: true, 'aria-label': 'Demo' }),
stack({ direction: 'row', gap: 'sm', wrap: true },
button({ size: 'sm', variant: 'outline', onclick: "import('/su/slider.js').then(m=>m.set('demo-slider',0))" }, 'Min'),
button({ size: 'sm', variant: 'outline', onclick: "import('/su/slider.js').then(m=>m.set('demo-slider',50))" }, 'Half'),
button({ size: 'sm', variant: 'outline', onclick: "import('/su/slider.js').then(m=>m.set('demo-slider',100))" }, 'Max'),
),
)Colors
stack({ gap: 'lg' },
slider({ value: 70, color: 'primary', 'aria-label': 'Primary' }),
slider({ value: 55, color: 'success', 'aria-label': 'Success' }),
slider({ value: 35, color: 'warning', 'aria-label': 'Warning' }),
slider({ value: 20, color: 'danger', 'aria-label': 'Danger' }),
)Disabled
sliderField({ label: 'Locked', name: 'locked', value: 50, disabled: true })Without a label
A bare slider() is the control on its own — give it an aria-label when there is no visible label to point at it.
Aa
Aa
stack({ direction: 'row', gap: 'md', align: 'center' },
text({ variant: 'small', tone: 'muted' }, 'Aa'),
slider({ min: 12, max: 24, value: 16, 'aria-label': 'Text size' }),
text({ tone: 'muted' }, 'Aa'),
)In a form
card(
cardBody(
stack({ gap: 'lg' },
sliderField({ label: 'Max image width', name: 'max-width', min: 640, max: 2560, step: 160, value: 1280, showValue: true }),
sliderField({ label: 'Quality', name: 'q', min: 40, max: 100, value: 82, showValue: true }),
),
),
cardFooter({ divided: true, style: 'justify-content: flex-end' },
button({ type: 'submit' }, 'Save'),
),
)Props
| Prop | Type | Default | Description |
|---|---|---|---|
min | number | string | 0 | Lower bound. |
max | number | string | 100 | Upper bound. |
step | number | string | — | Increment. Omit for the browser default of 1. |
value | number | string | — | Initial value. |
showValue | boolean | false | Adds an <output> with the build-time value. |
color | 'primary' | 'neutral' | 'success' | 'warning' | 'danger' | 'primary' | Thumb colour. |
name | string | — | Form field name; the id is derived from it. |
disabled | boolean | false | Disables the control. |
sliderField() additionally takes label, help, error and required — see textField().