RangeSlider

Molecule

Numeric slider input, distinct from Slider (a carousel). Single mode renders one native `<input type="range">` with a server-computed token gradient fill. Range (dual-handle) mode overlays two native range inputs with a shared fill bar and a small inline script that clamps the handles against each other and keeps the fill in sync while dragging.

Single value

Preview
Volume 65
Code
<%- include('modules/ui/RangeSlider', {
  label: 'Volume',
  value: 65,
  min: 0,
  max: 100,
  name: 'volume',
}) %>

Dual-handle range

Preview
Price range 20 – 80
Code
<%- include('modules/ui/RangeSlider', {
  label: 'Price range',
  range: true,
  value: [20, 80],
  min: 0,
  max: 100,
  nameMin: 'priceMin',
  nameMax: 'priceMax',
}) %>

Commit on release (one write per gesture)

Preview
Fan speed 40

Commits: none yet

Code
<%- include('modules/ui/RangeSlider', { id: 'fan', label: 'Fan speed', value: 40, step: 5 }) %>
<script>
  // 'input' still fires per step (live label); the commit fires once per gesture:
  // pointer up, 400 ms of keyboard idle, or blur.
  document.getElementById('fan').addEventListener('kui:rangeslider-commit', (e) => api.setFan(e.detail.value));
</script>

Pending (a write is in flight)

Preview
Fan speed 40
Code
<%- include('modules/ui/RangeSlider', { id: 'fan', label: 'Fan speed', value: 40, step: 5, pending: true }) %>
<!-- at runtime: document.getElementById('fan').__rangeslider.setPending(false) -->
Source modules/ui/RangeSlider.ejs