Skip to content
kerfjsGitHub

Slider

Pick a number or a range by dragging, when about right is good enough.

SourcePackage @kerf-js/veneerTry it

Preview

tsx
import { state } from '@kerf-js/core'import { Slider } from '@kerf-js/veneer'export function Basic() {  const copies = state(3)  return (    <Slider      label="Copies"      value={copies.value}      min={1}      max={8}      onChange={(v) => (copies.value = v)}    />  )}const min = 60_000

Installation

npm install @kerf-js/veneer

Try it

Change the controls: the preview and its code update together. The address keeps what you set, so you can link to it.

Live preview
Controls
Min1
Max12
Step1
Codeupdates as you change the controls
import { Slider } from '@kerf-js/veneer'<Slider value={v.value} onChange={next => (v.value = next)} label="Copies" min={1} max={12} />

Usage

tsx
import { Slider } from '@kerf-js/veneer'

Formatted value

format draws the number with its unit.

tsx
import { state } from '@kerf-js/core'import { Slider } from '@kerf-js/veneer'export function Format() {  const memory = state(4)  return (    <Slider      label="Memory"      value={memory.value}      min={1}      max={32}      format={gigabytes}      onChange={(v) => (memory.value = v)}    />  )}const min = 60_000const gigabytes = (v: number) => `${v} GB`

Steps

Use step to snap the value to fixed jumps, here every 25.

tsx
import { state } from '@kerf-js/core'import { Slider } from '@kerf-js/veneer'export function Step() {  const rollout = state(25)  return (    <Slider      label="Rollout"      value={rollout.value}      step={25}      format={percent}      onChange={(v) => (rollout.value = v)}    />  )}const percent = (v: number) => `${v}%`

A range

Two numbers make two thumbs. names tells screen readers which is which.

tsx
import { state } from '@kerf-js/core'import { Slider } from '@kerf-js/veneer'export function Range() {  const copies = state<[number, number]>([2, 6])  return (    <Slider      label="Copies"      value={copies.value}      min={1}      max={12}      names={['Fewest copies', 'Most copies']}      onChange={(v) => (copies.value = v)}    />  )}const min = 60_000

Disabled

Use disabled to show a value that cannot be changed.

tsx
import { Slider } from '@kerf-js/veneer'export function Disabled() {  return (  <Slider    label="Copies"    value={3}    min={1}    max={8}    disabled    onChange={() => {}}  />  )}const min = 60_000

Autoscale limits

Pass a pair of numbers as value for a range with a low and a high end, and names to label each end.

tsx
import { state } from '@kerf-js/core'import { Row, Slider, Stack, Text } from '@kerf-js/veneer'export function Autoscale() {  const copies = state<[number, number]>([2, 6])  return (    <Stack gap="group">      <Slider        label="Keep between"        value={copies.value}        min={1}        max={12}        names={['Fewest copies', 'Most copies']}        onChange={(v) => (copies.value = v)}      />      <Stack gap="tight">        <Row justify="between">          <Text subtle>When quiet</Text>          <Text>            €{copies.value[0] * COPY_COST} a month          </Text>        </Row>        <Row justify="between">          <Text subtle>At full load</Text>          <Text>            €{copies.value[1] * COPY_COST} a month          </Text>        </Row>      </Stack>    </Stack>  )}const min = 60_000const COPY_COST = 42

When to use

Use it for

  • A value in a known range where the feel matters more than the digit

Reach for something else

Accessibility

←→
One step down or up
PageUpPageDown
A bigger step
HomeEnd
The minimum or maximum
  • Each thumb has the slider role and is named by the label.
  • People who can't drag can tap the track or use the keys.

API Reference

PropTypeDefaultDescription
labelstring—Its accessible name. Fields show it; icon-only controls speak it.
valueV—One number, or two for a range.
minnumber0The lowest allowed value.
maxnumber100The highest allowed value.
stepnumber1How far one key press moves it.
format((v: number) => string)StringTurns the number into the text shown and read out.
names[string, string]—What each thumb of a range means, for screen readers.
disabledbooleanfalseTurns it off, and takes it out of the tab order.
namestring—Posts with a form: one entry per thumb.
EventTypeDefaultDescription
onChange(value: V) => void—Called with the new number or pair.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="range-head"] [data-part="track"]

trackrangethumb

RelatedNumber fieldSegmented