Dial
A value chosen by turning a knob, with a press on the ring to jump, a hold to turn by finger, Escape to undo a turn and the keys of a slider.
Rendering Dial…
Installation
Copy the source into your project with the CLI. It lands under @/components/ui and is yours to edit.
npx mlola-ui add dialUsage
import { Dial } from "@/components/ui/dial";
export default function Example() {
return <Dial label="Temperature" min={10} max={30} step={0.5} defaultValue={21} format={(value) => `${value} °C`} />;
}Styling comes from the engine stylesheet and the nearest theme. Set it once at the root:
<html data-theme="graphite" data-mode="light">Examples
A thermostat
format says the value in a unit, and caption and tone follow what the value means.
Rendering A thermostat…
In a form
With a name, the dial submits its value like a native input.
Rendering In a form…
HTML
Without React, write this markup and load @mlola-ui/behavior once, with @mlola-ui/behavior/dial beside it: a module of its own, so pages without one keep the small core. It runs the keyboard, focus and state for every element marked data-ml="dial", including markup added later, and needs no build step.
<div class="ml-dial-field" data-ml="dial" data-size="md" data-tone="warning" data-ml-step="0.5" data-ml-unit=" °C">
<span class="ml-dial-label" id="thermostat-label">Thermostat</span>
<div class="ml-dial" id="thermostat" role="slider" tabindex="0"
aria-labelledby="thermostat-label" aria-describedby="thermostat-caption"
aria-valuemin="10" aria-valuemax="30" aria-valuenow="21.5" aria-valuetext="21.5 °C"
style="--ml-dial-angle: 20.25deg">
<svg class="ml-dial-arc" viewBox="0 0 100 100" aria-hidden="true" focusable="false">
<path class="ml-dial-ticks" d="M 16.77 83.23 L 14.64 85.36 M 11.50 76.96 L 10.27 77.82 M 7.40 69.86 L 6.04 70.50 M 4.60 62.16 L 3.15 62.55 M 3.18 54.10 L 1.68 54.23 M 3.18 45.90 L 1.68 45.77 M 4.60 37.84 L 3.15 37.45 M 7.40 30.14 L 6.04 29.50 M 11.50 23.04 L 10.27 22.18 M 16.77 16.77 L 14.64 14.64 M 23.04 11.50 L 22.18 10.27 M 30.14 7.40 L 29.50 6.04 M 37.84 4.60 L 37.45 3.15 M 45.90 3.18 L 45.77 1.68 M 54.10 3.18 L 54.23 1.68 M 62.16 4.60 L 62.55 3.15 M 69.86 7.40 L 70.50 6.04 M 76.96 11.50 L 77.82 10.27 M 83.23 16.77 L 85.36 14.64 M 88.50 23.04 L 89.73 22.18 M 92.60 30.14 L 93.96 29.50 M 95.40 37.84 L 96.85 37.45 M 96.82 45.90 L 98.32 45.77 M 96.82 54.10 L 98.32 54.23 M 95.40 62.16 L 96.85 62.55 M 92.60 69.86 L 93.96 70.50 M 88.50 76.96 L 89.73 77.82 M 83.23 83.23 L 85.36 85.36" />
<path class="ml-dial-track" d="M 20.302 79.698 A 42 42 0 1 1 79.698 79.698" />
<path class="ml-dial-range" d="M 20.302 79.698 A 42 42 0 0 1 64.537 10.596" />
</svg>
<span class="ml-dial-knob" aria-hidden="true"></span>
<span class="ml-dial-readout" aria-hidden="true"><span class="ml-dial-value">21.5 °C</span></span>
</div>
<span class="ml-dial-caption" id="thermostat-caption">Heating from 19.5 °C</span>
</div><script type="module">
import { observe } from "@mlola-ui/behavior";
import "@mlola-ui/behavior/dial";
observe();
</script>Options
| Prop | Values | Default | Description |
|---|---|---|---|
size | smmdlg | md | — |
tone | primaryinfosuccesswarningdanger | primary | The arc's color, as the shared vocabulary names it. |
Every prop with a fixed set of values, read from the exported TypeScript types with its doc comment. Open the Code tab above for the rest of the API.
Classes and attributes
A class names each element; data-* and aria-* attributes carry its variant and state. The values listed are the ones the stylesheet draws; the default needs no attribute.
| Class | Attributes |
|---|---|
ml-dial-field | data-disableddata-size="lg | sm"data-tone="danger | info | success | warning" |
ml-dial-label | — |
ml-dial-caption | — |
ml-dial | data-turning |
ml-dial-arc | — |
ml-dial-ticks | — |
ml-dial-track | — |
ml-dial-range | — |
ml-dial-knob | — |
ml-dial-readout | — |
ml-dial-value | — |
Accessibility and theming
- Semantic elements, accessible names and state relationships are part of the contract.
- Keyboard, pointer and touch paths are operable; focus stays visible in every theme.
- Light and dark modes pass WCAG AA contrast in all 5 canonical themes.
- Reduced motion and forced colors keep meaning and operation.
Dependencies
Installed alongside this component. No third-party UI runtime is ever added.
- input
@mlola-ui/behavior