Skip to content
cennge-ui
GitHubv0.3.1, changelog

Slider

A thumb on a track for one number, or two thumbs for a range.

Deploy window09:00 – 18:00
Parallel jobs4
Coverage threshold80%

cennge-ui deploys between 09:00 and 18:00, runs 4 jobs at a time and fails a build under 80% coverage.

  1. Drag a thumb, or click a label under a track: the nearest thumb moves there.
  2. Arrows step by one; Page Up, Page Down or Shift with an arrow step by ten; Home and End go to the ends.
  3. Parallel jobs stops only on its marks: the arrows go 1, 2, 4, 8, 16.
Live: the component itself, not a picture of it.

Field marks

Import
import { Slider } from "cennge-ui";
Size
3.0 KB gzip for this import, its dependencies aside
Pattern
WAI-ARIA slider, one per thumb (Radix Slider)
Keyboard
Arrow left Arrow right Arrow up Arrow down PageUpPageDownHomeEnd
State
Controlled with value and onValueChange, a number or an array for a range; or uncontrolled with defaultValue
SSR
Rendered on the server in the Next.js check; hydrates without a warning
Range
Each thumb is named after the label plus “Minimum” or “Maximum”; thumbLabels changes those words
Commit
onValueCommit fires when a drag ends, and on each key press or label click
Tests
Unit tests; end-to-end in Chromium, Firefox and WebKit, on desktop and phone viewports: slider

When to use#

A Slider suits a value where the position matters more than the exact digits: a threshold, a time window, a level. People can drag it, tap a mark, or step it from the keyboard, and the current value shows next to the label. When people know the exact number they want, a NumberInput is quicker.

Similar#

  • NumberInput is for exact numbers that are typed.
  • Radio shows a handful of named options as a list; a Slider with named marks keeps them on one scale.
  • Progress shows a value but takes no input.

One value#

A number in value gives one thumb. formatValue sets how the value reads next to the label and to screen readers. onValueChange fires on every step of a drag; onValueCommit fires once when the drag ends, and on each key press, which suits saving.

Request timeout30 s

Saved: 30 s

single.tsx
import { useState } from "react";
import { Slider } from "cennge-ui";

export default function TimeoutSlider() {
  const [seconds, setSeconds] = useState(30);
  const [saved, setSaved] = useState(30);

  return (
    <div className="flex w-full max-w-96 flex-col gap-3">
      <Slider
        label="Request timeout"
        value={seconds}
        onValueChange={setSeconds}
        onValueCommit={setSaved}
        min={5}
        max={120}
        step={5}
        formatValue={(value) => `${value} s`}
      />
      <p className="text-sm text-muted">Saved: {saved} s</p>
    </div>
  );
}

A range#

An array gives a thumb per item. The thumbs are named after the label, "Changed lines Minimum" and "Changed lines Maximum"; thumbLabels renames or translates the part after the label.

Changed lines50 – 400

Pull requests that change 50 to 400 lines

range.tsx
import { useState } from "react";
import { Slider } from "cennge-ui";

export default function ChangedLinesFilter() {
  const [lines, setLines] = useState([50, 400]);
  const [from = 0, to = 1000] = lines;

  return (
    <div className="flex w-full max-w-96 flex-col gap-3">
      <Slider label="Changed lines" value={lines} onValueChange={setLines} min={0} max={1000} step={10} />
      <p className="text-sm text-muted">
        Pull requests that change {from} to {to} lines
      </p>
    </div>
  );
}

Marks#

Each mark puts a dot on the track; a mark with a label also writes it under the track, and a click on that label moves the thumb there. A plain number, like 90 here, is a dot without a label. Dots on the filled part of the track change colour.

Coverage threshold80%
marks.tsx
import { Slider } from "cennge-ui";

const percents = [0, 25, 50, 75, 100].map((value) => ({ value, label: `${value}%` }));

export default function CoverageSlider() {
  return (
    <Slider
      label="Coverage threshold"
      defaultValue={80}
      marks={[...percents, 90]}
      formatValue={(value) => `${value}%`}
      className="w-full max-w-96"
    />
  );
}

Only on the marks#

restrictToMarks makes the marks the only values: a drag snaps to the nearest one and the arrow keys go from mark to mark, so steps need not be even.

Parallel jobs4
restrict.tsx
import { Slider } from "cennge-ui";

const jobs = [1, 2, 4, 8, 16].map((value) => ({ value, label: String(value) }));

export default function ParallelJobs() {
  return (
    <Slider
      label="Parallel jobs"
      defaultValue={4}
      min={1}
      max={16}
      marks={jobs}
      restrictToMarks
      color="secondary"
      className="w-full max-w-96"
    />
  );
}

Named steps#

When every value the slider can take has a text label, the label becomes the value's name: the readout and screen readers say "Warning", not "1".

Log levelWarning
named.tsx
import { Slider } from "cennge-ui";

const levels = ["Error", "Warning", "Info", "Debug"].map((label, value) => ({ value, label }));

export default function LogLevel() {
  return <Slider label="Log level" defaultValue={1} min={0} max={3} marks={levels} className="w-full max-w-96" />;
}

Accessibility#

Each thumb is a slider with its value, minimum and maximum, and a text value from formatValue or a mark's label. A single thumb takes its name from label, or from aria-label when there is no visible label. The labels under the track are hidden from screen readers: they repeat what the thumbs already say, and the keyboard reaches every value without them. A disabled slider ignores clicks on its labels.

Props#

PropTypeDefault
label
React.ReactNode
–
value
VA number for one thumb, an array for a range.
–
defaultValue
V
–
onValueChange
(value: V) => void
–
onValueCommit
(value: V) => voidFires once the user releases the thumb.
–
min
number
0
max
number
100
step
number
1
marks
Array<number | SliderMark>Points on the scale: a dot on the track, plus a label under it when given. A click on a label moves the nearest thumb there. Plain numbers are dots without labels.
–
restrictToMarks
booleanThumbs stop only on the marks: dragging snaps to the nearest one, arrow keys go mark to mark.
–
showValue
booleanShow the current value next to the label.
true when there is a label
formatValue
(value: number) => stringFormat the shown value, e.g. (v) => ${v}%``.
–
thumbLabels
string[]Names of a range's thumbs, read after the label: "Deploy window Minimum".
["Minimum", "Maximum"]
color
"default""primary""secondary""success""warning""danger""info"
"primary"
size
"sm""md""lg"
"md"
isDisabled
boolean
–
name
string
–
className
string
–
aria-label
string
–