Skip to content
View as Markdown

Inputs

Range

Pick a numeric value from a continuous range. Compose it inside a Field for its label, description and error.

Import

TSX
import { Field, Range } from "@loamui/core";

Usage

Every example has a CSS tab. That’s the real, complete stylesheet for the component: plain, static CSS, with nothing running in the browser.

Basic usage

Rendered bare, the control needs an aria-label; a Field.Label (below) is the usual way to name it.

Labelled inside a Field

Wrap the control in Field.Root: it reads its id, description and error wiring from the field, the composition pattern shared by all form controls.

Applies to alerts only.

Steps

Snap to increments with the step prop.

Marks

marks are points on the track: they go to a <datalist> the input references, so the thumb snaps to them, and the stylesheet draws a tick under each.

Marks with labels

A mark's label is written under its tick, aligned to where the thumb sits at that value. Label the ends, or the values that mean something; the ticks in between can stay bare.

Value above the thumb

Range.Root carries the value between the Range and a Range.Output, a native <output for> bound to the input, which the stylesheet places above the thumb. labels.value formats the number.

Bounds and step

min, max and step are the platform's own; the output and the marks read them from the input, so the same anatomy holds for any range.

Disabled

disabled reaches the native input: the track and thumb dim, the value stays readable, and the control leaves the Tab sequence.

Guidance

When to use it

  • For imprecise, pick-a-feel values where the position matters more than the exact number: volume, brightness, intensity.
  • When the effect of the value is visible as it changes, so users steer by the result rather than the figure.

When not to

  • For exact numbers the user already knows (an amount, a year, a reference). Use Input with inputMode="numeric" or "decimal"; landing on one precise value on a track is slow and error-prone, especially on touch. A small count adjusted one at a time is QuantityInput.
  • For choosing among a few discrete options. Use RadioGroup, where every option is visible and labelled.

Accessibility

  • Renders a native <input type="range">: arrow keys adjust the value and Home/End jump to the ends, with the current value announced. There is no custom key handling to maintain.
  • Always give it an accessible name: a Field.Label in the surrounding Field.Root, or an aria-label when rendering it bare.
  • Assistive tech hears the value change as it moves; sighted users have no equivalent unless you render the value visibly: Range.Output, or the value in the label.
  • Range.Output is a native <output for>, so it is bound to the input and announced as a status; marks are a real <datalist>, which the platform snaps to, and the drawn ticks and labels are a picture of it, hidden from assistive technology rather than exposed as a list of options after the slider.

How it works

Show the current value

The thumb shows an approximate position. Display the chosen number with Range.Output, a native <output> bound to the input that follows the thumb. Field.Label accepts any content and the control is stateless, so the value can instead ride in the label, driven by value and onChange.

Steps match the precision users care about

step sets the smallest move a user can make, so match it to differences that actually matter: nobody sets fertiliser to 43 kg. A coarser step makes every reachable value a bigger target: easier with arrow keys, a mouse, or a thumb. If users need finer precision than a comfortable step allows, the value is exact and belongs in an Input.

Parts

Range.Control

The native range input. It self-wires inside Field.Root; Range.Root is optional when composing an output.

PropTypeDefaultDescription
minnumber0Minimum value.
maxnumber100Maximum value.
stepnumber1Increment between valid values.
defaultValuenumber—Initial value for uncontrolled usage.
marksArray<{ value: number; label?: string }>—Points on the track: forwarded to a <datalist> the input references, drawn as ticks under the track with each label beneath its tick.
...othersInputHTMLAttributes—All native <input type="range"> props are forwarded.

Range.Root

The optional <div> wrapper that carries the value between Range and Range.Output; native <div> props are forwarded. Not needed for a range without an output.

Range.Output

The current value as a native <output for> bound to the input, placed above the thumb. Belongs inside Range.Root; native <output> props are forwarded, and children replace the formatted value.

PropTypeDefaultDescription
labels{ value?: (value: number) => string }{ value: (n) => new Intl.NumberFormat().format(n) }Formats the value the output shows.

Custom properties

PropertySyntaxDefaultDescription
--loam-range-thumb-sizeCSS lengthcalc(1.25 * var(--loam-text-sm))The thumb's diameter. The marks and the output read the same property to sit over the thumb, so set it on the Range's ancestor, never on the input alone, and give it a length rather than an em: they read it from a smaller font size.