lensclear design system

A labelled slider with a mono readout. One thumb over a finite domain, on base-ui.

Overview

Every consumer has a deliberate finite selection domain, and the value gets signed into an instruction. So the exact number renders beside the track, in tabular figures, in the caller's unit.

The slider owns no value. It maps the number it is handed to a thumb position and passes a new number back through onValueChange, so a text input beside it can never disagree.

Card-less: no border on the track, tinted fill only. Progress is not status, so the fill is neutral unless the value is a risk position.

Basic

A program-bounded range. The hint carries the bounds, the readout the unit.

Max LTV
75.00% · 7500 bps

3,000 to 9,500 bps in steps of 50

<ParamSlider
  label="Max LTV"
  min={3000}
  max={9500}
  step={50}
  value={bps}
  onValueChange={setBps}
  formatValue={(bps) => `${bps / 100}% · ${bps} bps`}
  hint="3,000 to 9,500 bps in steps of 50"
  testId="ltv"
/>

Stops

Map a finite index to documented values. The slider steps the index, formatValue shows the stop. labelAction sits beside the label for help.

Market limit
?
$10M

Seven stops, logarithmic. The index is the value, the readout is the stop.

<ParamSlider
  label="Market limit"
  min={0}
  max={STOPS.length - 1}
  step={1}
  value={index}
  onValueChange={setIndex}
  formatValue={(i) => formatUsd(STOPS[i])}
  labelAction={<HelpTooltip />}
  testId="ceiling"
/>

Tones

tone inks the fill and thumb. The borrow slider wears the projected health bucket, so dragging right turns it green through amber to red.

neutral
60%
success
60%
warning
60%
danger
60%
<ParamSlider tone="neutral" ... />
<ParamSlider tone="success" ... />
<ParamSlider tone="warning" ... />
<ParamSlider tone="danger" ... />

Disabled

While the bound is unknown the whole control dims and the hint says why.

Borrow

Waiting for the oracle price and protocol caps

<ParamSlider disabled hint="Waiting for the oracle price" ... />

Props

labelReactNoderequired

The slider's accessible label, rendered above the track.

minnumberrequired

Lower bound of the caller's finite selection domain.

maxnumberrequired

Upper bound of the caller's finite selection domain.

stepnumberrequired

The granularity. min is the origin for valid values.

valuenumberrequired

Controlled. One thumb, one number.

onValueChange(next: number) => voidrequired

The new value on drag, track press, and keyboard.

formatValue(value: number) => stringrequired

The readout and the thumb's aria-valuetext. Show the unit the operator thinks in.

Small muted line under the track: bounds, units, or a caveat.

labelActionReactNode

Interactive help rendered beside, never inside, the label.

toneParamSliderTonedefault: 'neutral'

Ink of the fill and thumb. Risk-position sliders only. A parameter slider stays neutral.

disabledboolean

Dims the whole control and ignores input.

testIdstringrequired

data-testid on the root. The readout gets `${testId}-value`.