0.1.0

Slider

Sliders let users pick a numeric value or range along a track. They work well when the approximate value matters more than precise typing.

Try it

Usage

The live value property is always a number[]. The HTML attribute is comma-separated (value="50" or value="25,75"). JSX may pass a number or an array. Two numbers are range mode; variant="range" only seeds [25, 75] when value is not already a pair.

Set min, max, and step for the numeric domain. Set orientation="vertical" for a vertical track.

import { RuiSlider } from '@ecopages/radiant-ui/slider';
import { RuiField } from '@ecopages/radiant-ui/field';
import { RuiLabel } from '@ecopages/radiant-ui/label';
 
<RuiField name="volume">
  <RuiLabel>Volume</RuiLabel>
  <RuiSlider variant="single" value={50} min={0} max={100} step={1} />
</RuiField>

Custom markup

<rui-slider> coordinates any light-DOM tree that matches its query contract. The RuiSlider helper stamps these targets; it is not required.

import '@ecopages/radiant-ui/slider';
 
<rui-slider value="50" min={0} max={100} label="Volume">
  <div class="rui-slider rui-slider--single" data-ref="root">
    <div class="rui-slider__header" data-ref="header">
      <span class="rui-slider__label" data-ref="label">Volume</span>
    </div>
    <div class="rui-slider__range">
      <div class="rui-slider__range-track" data-ref="rangeTrack">
        <div class="rui-slider__range-fill" />
        <button
          type="button"
          class="rui-slider__thumb"
          data-ref="singleThumb"
          data-thumb="value"
          role="slider"
        />
      </div>
    </div>
  </div>
</rui-slider>

BEM classes are presentation-only. The host owns thumb aria-* and track CSS variables. Set name on the host to submit with a native form.

Range selection

Pass value={[25, 75]} for minimum/maximum filters. Set minDistance to prevent the thumbs from overlapping.

Step size and readout

Match step to meaningful increments. valuePrecision only formats the readout, tooltips, and aria-valuetext. It defaults to the decimal places in step, so a stored 0.30000000000000004 still displays as 0.3. Round committed values in application code when you need a canonical number.

<RuiSlider min={0} max={1} step={0.1} value={0.3} showValue />
 
<RuiSlider min={0} max={1} step={0.001} value={0.343} valuePrecision={2} showValue />

Theming

Slider surfaces map to semantic roles, never Tailwind palette steps:

PartCSS roles
Track (.rui-slider__range-track)--rui-track-fill (--rui-track-mix of --on-background)
Fill (.rui-slider__range-fill)primary
Thumb (.rui-slider__thumb)background surface, primary border, --shadow-control (--rui-slider-thumb-shadow)
Value readout (.rui-slider__value)on-surface
Focus ringfocus-ring

Range thumb positions come from --rui-slider-min / --rui-slider-max. The RuiSlider view seeds those inline variables (and the value readout) during SSR; the host updates them while dragging.

Unfilled track contrast is shared with knobs. Set the mix or a solid color on an ancestor:

:root {
  --rui-track-mix: 28%;
}
 
.panel {
  --rui-track-color: var(--surface-container-high);
}

Override --rui-slider-track-color on rui-slider when only the slider should change.

Range mode also accepts presentation variables on rui-slider. Set track and thumb corner radii independently — they follow shape tokens such as --radius-control and --radius-container:

rui-slider {
  --rui-slider-track-radius: var(--radius-container);
  --rui-slider-thumb-radius: var(--radius-control);
}

Switching the radius pack (sharp, default, soft) updates both when they reference shape tokens.

API

RuiSlider owns the light-DOM surface. Pass showValue for the default readout, valueTitle for hover tooltips, or compose a custom readout with RuiSliderValue.

Attributes

AttributeTypeDefaultDescription
variantsingle · rangesingleSingle-thumb or dual-thumb range.
orientationhorizontal · verticalhorizontalTrack axis.
valuestring50Comma-separated thumb values (50 or 25,75). The JS property is number[].
minnumber0Range minimum.
maxnumber100Range maximum.
stepnumber1Arrow-key and pointer snap interval.
value-precisionnumberdecimal places in stepMaximum fraction digits in the value readout.
min-distancenumber0Minimum gap enforced between range thumbs.
disabledbooleanfalseDisables interaction.
read-onlybooleanfalsePrevents value changes while leaving thumbs focusable.
labelstring''Accessible name for the slider.
namestring''Form field name on this host. Range mode also submits {name}-max.
show-valuebooleanfalseShows the default value readout below the track.
value-titlebooleanfalseMirrors the live value in the control title on hover.

Light-DOM contract

TargetRequiredHost writesAuthor owns
[data-ref="root"]yesrui-slider--* layout classesthe root node
[data-ref="rangeTrack"]yesinline --rui-slider-*, optional titlethe track node; view seeds geometry
[data-thumb]yeshidden, disabled, tabindex, aria-* value attrsthumb elements (value, min, or max); view seeds aria-valuenow
[data-ref="header"]nohiddenheader row
[data-ref="label"]nohidden, textContentlabel text
[data-ref="value"]notextContentreadout node; view seeds the formatted value
[data-default-value]nohidden (via showValue)default readout when no custom value child

Do not set thumb tabindex. Nested hosts: none. The RuiSlider view seeds readout text, track CSS variables, and aria-valuenow so the first paint matches the hydrated control.

Events

EventDetailDescription
rui-change{ value: number[] }Emitted as the value moves; [50] in single mode, [25, 75] in range mode.

View helpers

ComponentTarget stampedNotes
RuiSliderfull [data-ref] tree under [data-ref="root"]Supplies default RuiSliderValue with [data-default-value] when children omitted. Seeds readout text and track geometry for SSR.
RuiSliderValue[data-ref="value"]Live readout; view seeds the formatted value, host updates textContent while dragging.

CSS classes

Public BEM classes (documented via @cssclass on the element):

ClassDescription
.rui-sliderRoot; wraps the label, track, and value readout.
.rui-slider--rangeRange-mode surface.
.rui-slider--verticalVertical track layout.
.rui-slider__labelOptional visible label.
.rui-slider__valueLive numeric readout.
.rui-slider__rangeTrack wrapper.
.rui-slider__range-trackTrack surface behind the thumb(s).
.rui-slider__range-fillFilled span from the origin to the current value (single) or between thumbs (range).
.rui-slider__thumbThumb button (role="slider").

Theme roles

PartCSS variables consumed
Track--rui-track-color / --rui-track-mix
Fill / thumb--primary
Thumb surface--background
Value readout--on-surface
Focus--focus-ring

Component CSS variables

Set on rui-slider. Defaults shown; all accept any length or shape token.

VariableDefaultApplies to
--rui-slider-track-size0.375remTrack thickness
--rui-slider-track-length12remMax track length (vertical / horizontal cap)
--rui-slider-track-color--rui-track-color or --rui-track-fillTrack background
--rui-slider-fill-color--primarySelected range fill
--rui-slider-track-radius--radius-controlTrack and fill corner radius
--rui-slider-thumb-size1.25remThumb width and height
--rui-slider-thumb-radius--radius-controlThumb corner radius
--rui-slider-thumb-border-width2pxThumb border
--rui-slider-thumb-border-color--primaryThumb border color
--rui-slider-thumb-background--backgroundThumb fill
--rui-slider-thumb-shadow0 2px 8px rgb(0 0 0 / 0.12)Thumb shadow

Accessibility

  • Sliders expose role="slider" with aria-valuenow, aria-valuemin, aria-valuemax, and a formatted aria-valuetext.
  • Pair with a visible label and optionally a live value readout.
  • Arrow keys adjust the value; Page Up/Down jump by larger increments.