Monet
@etched/monet 0.0.1

Slider

Ported

Pick a number, or a range between two numbers, by dragging a thumb along a track. Pass an array to value or defaultValue for a range. Arrow keys step by step, Shift with them and Page Up and Down by largeStep, and Home and End go to min and max. format takes Intl.NumberFormat options. Native <div> attributes and ref pass through.

Kumo source
import { Slider } from "@etched/monet/slider";

export function Preview() {
  return (
    <div className="grid" style={{ inlineSize: "16rem" }}>
      <Slider aria-label="Fan speed" defaultValue={40} />
    </div>
  );
}

Installation

import { Slider } from "@etched/monet/slider";

Examples

One value

Drag the thumb, or use the arrow keys: Shift or Page Up and Down take bigger steps, and Home and End go to the ends.

Fan speed
import { Slider } from "@etched/monet/slider";

export function OneValue() {
  return (
    <div className="grid">
      <Slider label="Fan speed" defaultValue={40} />
    </div>
  );
}

Range

An array value has a thumb for each end. getAriaLabel names each thumb.

Salary band
import { Slider } from "@etched/monet/slider";

export function Range() {
  return (
    <div className="grid">
      <Slider
        label="Salary band"
        defaultValue={[160000, 220000]}
        min={100000}
        max={300000}
        step={5000}
        format={{ style: "currency", currency: "USD", notation: "compact" }}
        getAriaLabel={(index) => (index === 0 ? "Lowest salary" : "Highest salary")}
      />
    </div>
  );
}

Steps and formats

step sets the stops. format takes Intl.NumberFormat options; a percent is a fraction.

Interview rounds
Sampling rate

Share of runs kept for review.

import { Slider } from "@etched/monet/slider";

export function StepsAndFormats() {
  return (
    <div className="grid">
      <Slider label="Interview rounds" defaultValue={2} min={1} max={5} />
      <Slider label="Sampling rate" defaultValue={0.25} min={0} max={1} step={0.05} format={{ style: "percent" }} description="Share of runs kept for review." />
    </div>
  );
}

Sizes

import { Slider } from "@etched/monet/slider";

export function Sizes() {
  return (
    <div className="grid">
      <Slider size="sm" aria-label="Volume (small)" defaultValue={30} />
      <Slider aria-label="Volume" defaultValue={30} />
    </div>
  );
}

Controlled

onValueChange runs while the thumb moves; onValueCommitted runs when it stops.

Match threshold

Candidates above 70 show in the shortlist.

import { useState } from "react";
import { Slider } from "@etched/monet/slider";

export function Controlled() {
  const [threshold, setThreshold] = useState(70);
  const [saved, setSaved] = useState(70);

  return (
    <div className="grid">
      <Slider
        label="Match threshold"
        value={threshold}
        onValueChange={setThreshold}
        onValueCommitted={setSaved}
        description={`Candidates above ${saved} show in the shortlist.`}
      />
    </div>
  );
}

Disabled

Bench load (locked)
import { Slider } from "@etched/monet/slider";

export function Disabled() {
  return (
    <div className="grid">
      <Slider label="Bench load (locked)" defaultValue={70} disabled />
    </div>
  );
}

Accessibility

  • Arrow keys step by step. Shift with an arrow, and PageUp/PageDown, step by largeStep. Home/End go to min and max.
  • Each thumb is a slider (a native range input), named by label or aria-label. getAriaLabel comes first, and tells a range's two thumbs apart.
  • Screen readers hear the value as format writes it, and description or error as its description. A range's thumbs add "start range" and "end range".
  • Give a range getAriaLabel, such as "Lowest salary" and "Highest salary".

API reference

PropTypeDefaultDescription
labelReactNode–Visible label. Without one, give the control an aria-label.
labelTooltipReactNode–More about the field, behind an info button after the label.
labelTooltipLabelstring"More information"Names the info button.
descriptionReactNode–Help text below the control. Hidden while an error shows.
errorFieldError–
size"sm" | "base""base"Track height: sm is 28 px, for toolbars and filters; base is 36 px, as Input.
getAriaLabel(index: number) => string–Names each thumb. Use it without a visible label, or to tell the two thumbs of a range apart.
classNamestring–Class on the outer element, for layout.