Slider
Native <input type="range"> with two-way binding via data-model. The fill bar percentage is derived; min/max/step come from props. Keyboard, touch, and screen reader support are inherited from the platform.
Live preview
Markup
<div class="slider"
data-component="slider-demo"
data-label="Volume"
data-min="0"
data-max="100"
data-step="5"
data-value="50">
<div class="slider-row">
<span class="slider-label" data-text="label"></span>
<input class="slider-input"
type="range"
data-model="value"
data-bind="min:min, max:max, step:step,
style:'--fill:' + percent() + '%'" />
<span class="slider-value" data-text="value"></span>
</div>
</div>
Definition
Micra.define('slider-demo', {
state: {
label: '',
value: 0,
min: 0,
max: 100,
step: 1,
suffix: '',
},
onCreate() {
// this.prop() auto-casts numeric strings to Number — no manual cast needed.
this.state.label = this.prop('label', '')
this.state.suffix = this.prop('suffix', '')
this.state.min = this.prop('min', 0)
this.state.max = this.prop('max', 100)
this.state.step = this.prop('step', 1)
this.state.value = this.prop('value', this.state.min)
},
// derived percentage for the WebKit fill track
percent() {
const { value, min, max } = this.state
if (max === min) return 0
return Math.round(((value - min) / (max - min)) * 100)
},
})
Integration
- Native input for accessibility and platform behavior — keyboard (Arrow / PageUp / Home / End), screen reader announcements, and touch drag work without custom code.
- WebKit fill bar uses a CSS custom property: style:'--fill:' + percent() + '%' writes --fill on the input, and the ::-webkit-slider-runnable-track rule reads it. Firefox uses ::-moz-range-progress, which fills automatically.
- Props in, value out. Initial config comes from data-* attributes. To listen to changes elsewhere, emit on input: <input @input="emit"> + emit() { Micra.emit('slider:change', this.state.value) }.
- Numeric two-way binding. data-model on type="range" / type="number" writes the input's valueAsNumber, not a string — so state.value stays numeric without manual casting. this.prop() auto-casts numeric strings too, so min/max/step from data-* attributes arrive as numbers as well.
Pitfalls
- Don't reinvent the slider with mousedown/move handlers — you lose keyboard, touch, ARIA, RTL, and high-contrast support all at once. The native input is the right primitive.
- Don't store percent in state. It's a pure function of three other fields — derive on read.
- Don't bind style: as a concatenated string when the element has other inline styles. applyBind calls setAttribute('style', …), which replaces the entire attribute and wipes any pre-existing inline rules. For mixing with other inline styles, pass an object — style:{ '--fill': percent() + '%' } — which Micra applies via Object.assign(el.style, val) and merges instead of replacing.