Forms

Slider

A range input with its value shown beside the label and the track filled up to the thumb.

#forms#input#no-js

Demo

Preview
60%
5 km

How far from the address to look.

$120

Showing hotels under $120 a night.

30

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/slider.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/slider.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/slider.qwe
component SliderDemoLive() {    state price = 120    <div.demo-stack>        <Slider name="price" label="Max price" min={10} max={500} step={10} value={price} prefix="$"                on_change={(v) => { price = v }}/>        <p.demo-note>{price >= 300 ? "Showing everything." : `Showing hotels under $${price} a night.`}</p>    </div>}view SliderDemo() =    <div.demo-stack.demo-narrow>        <Slider name="volume" label="Volume" value={60} format="%"/>        <Slider name="radius" label="Search radius" min={1} max={50} value={5} format=" km"                hint="How far from the address to look."/>        <SliderDemoLive/>        <Slider name="locked" label="Locked" value={30} disabled={true}/>    </div>

Source

ui/slider.qwe
// Slider: a labelled range, on the browser's own <input type="range">, showing// its value as it moves. It works in a plain <form> and with the arrow keys, Home// and End; the track is filled up to the thumb.////   <Slider name="volume" label="Volume" value={60} format="%"/>//   <Slider name="price" label="Max price" min={10} max={500} step={10} value={120} prefix="$"//           on_change={(v) => { max_price = v }}/>//// min, max, step: as on the input (0, 100, 1). value: where it starts.// prefix / format: text before / after the number shown ("$", "%", " kg").// show_value: false hides the number. hint, disabled and field (the id, default// "slider-" + name) as in TextField. on_change(value): inside one of your// components, given the number, as it moves.import ui/theme.qwe use ui_clslet slider_css = css`.ui-slider { display: grid; gap: 6px; min-width: 0; font: 14px/1.4 var(--ui-font); color: var(--ui-fg); }.ui-slider-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }.ui-slider-label { font-size: 13px; font-weight: 500; }.ui-slider-value { font-size: 13px; color: var(--ui-muted); font-variant-numeric: tabular-nums; }.ui-slider input {  --ui-slider-track: var(--ui-subtle);  appearance: none; display: block; width: 100%; height: 22px; margin: 0; background: transparent; cursor: pointer;}.ui-slider input:focus { outline: none; }.ui-slider input::-webkit-slider-runnable-track {  height: 6px; border-radius: 999px; box-shadow: inset 0 0 0 1px var(--ui-border);  background: linear-gradient(to right, var(--ui-accent) var(--ui-slider-fill, 0%), var(--ui-slider-track) var(--ui-slider-fill, 0%));}.ui-slider input::-moz-range-track { height: 6px; border-radius: 999px; background: var(--ui-slider-track); box-shadow: inset 0 0 0 1px var(--ui-border); }.ui-slider input::-moz-range-progress { height: 6px; border-radius: 999px; background: var(--ui-accent); }.ui-slider input::-webkit-slider-thumb {  appearance: none; width: 18px; height: 18px; margin-top: -6px; border-radius: 50%;  background: var(--ui-surface); border: 2px solid var(--ui-accent); box-shadow: var(--ui-shadow);  transition: transform .12s, box-shadow .15s;}.ui-slider input::-moz-range-thumb {  width: 14px; height: 14px; border-radius: 50%; background: var(--ui-surface);  border: 2px solid var(--ui-accent); box-shadow: var(--ui-shadow);}.ui-slider input:hover::-webkit-slider-thumb { transform: scale(1.1); }.ui-slider input:focus-visible::-webkit-slider-thumb { box-shadow: var(--ui-focus); }.ui-slider input:focus-visible::-moz-range-thumb { box-shadow: var(--ui-focus); }.ui-slider-hint { margin: 0; font-size: 13px; color: var(--ui-muted); }.ui-slider-disabled { opacity: .55; }.ui-slider-disabled input { cursor: not-allowed; }.ui-slider-disabled input:hover::-webkit-slider-thumb { transform: none; }@media (prefers-reduced-motion: reduce) { .ui-slider input::-webkit-slider-thumb { transition: none; } }`component Slider(name: str? = null, label: str? = null, value: num = 50, min: num = 0, max: num = 100,                 step: num = 1, prefix: str = "", format: str = "", show_value: bool = true,                 hint: str? = null, disabled: bool = false, field: str? = null, on_change = null,                 class: str? = null) {    style global slider_css    state v = value    let id = field ?? `slider-${name ?? re.replace(lower(label ?? "range"), "[^a-z0-9]+", "-")}`    let fill = max > min ? round((v - min) * 100 / (max - min), 2) : 0    let shown = `${prefix}${v}${format}`    <div class={ui_cls(["ui-slider", disabled && "ui-slider-disabled", class])}>        {(label != null || show_value) && <div.ui-slider-head>            {label != null && <label.ui-slider-label for={id}>{label}</label>}            {show_value && <output.ui-slider-value for={id} id={`${id}-out`}>{shown}</output>}        </div>}        <input type="range" id={id} name={name} min={min} max={max} step={step} value={v}               disabled={disabled} style={`--ui-slider-fill: ${fill}%`}               aria-valuetext={prefix != "" || format != "" ? shown : null}               aria-describedby={hint != null ? `${id}-hint` : null}               @input={(e) => {                   v = float(e.value)                   on_change && on_change(v)               }}/>        {hint != null && <p.ui-slider-hint id={`${id}-hint`}>{hint}</p>}    </div>}
Thread
55Useful? Like it, or add to its thread below.

Thread 0 posts

On Slider: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.