Slider

A hand-drawn range slider for selecting a numeric value.

Overview

A Slider selects a numeric value from a continuous or stepped range by dragging a thumb along a track. Use Input type="number" instead when a precise typed value matters more than a quick visual adjustment.

Anatomy

A sketchy rail (a thin rectangle) with a filled portion (from the start to the thumb) and a round thumb — all three shapes computed directly from @ghds/sketch-core, sharing one measured box and seed. On React and Web Components, a real, invisible <input type="range"> spans the full track and carries every interaction (dragging, clicking the track, and native Arrow/Home/End/PageUp/ PageDown keyboard behavior) with zero custom pointer/keydown code. React Native has no such native primitive, so dragging is hand-rolled with PanResponder (built into React Native core — no new gesture-library dependency).

Variants & States

State Status Notes
Default Implemented
Hover Implemented The filled portion and thumb darken slightly (CSS/native pseudo-states — no JS-tracked hover flag needed).
Focus Implemented A focus ring appears around the thumb.
Disabled Implemented
Two-thumb range Not implemented Not in v1 — "range" in the ticket names a possible future dual-thumb mode, not a v1 requirement.
Vertical orientation Not implemented
Value tooltip while dragging Not implemented A consumer wanting a live readout derives it from a controlled value.

Usage

Do

  • Use Slider for a value with a clear, visible min/max range (e.g. volume, rating, brightness).
  • Label the value being set ("Volume"), not the current reading.

Don't

  • Don't use Slider when the exact value must be typed precisely — use Input type="number" instead.
  • Don't expect a two-thumb range mode in v1 — a single thumb only.

Accessibility

Content

The label names the value being adjusted (“Volume”, “Rating”), not the current reading or an instruction.

Props API

React@ghds/react

PropTypeDefaultDescription
labelstringVisible label, associated via Radix Label.
valuenumberControlled value.
defaultValuenumberInitial value when uncontrolled.
minnumber0Minimum value.
maxnumber100Maximum value.
stepnumber1Increment step.
disabledbooleanfalseDisables interaction.
...restInputHTMLAttributesAll other native input attributes pass through (e.g. onChange, aria-valuetext, name).

Web Components@ghds/web-components

PropTypeDefaultDescription
valuenumber0Reflected attribute. Mirrored to the form value.
minnumber0Minimum value.
maxnumber100Maximum value.
stepnumber1Increment step.
disabledbooleanfalseDisables interaction and form participation.
namestringSubmitted control name.
labelstringOptional visible label, also the accessible name.

React Native@ghds/react-native

PropTypeDefaultDescription
labelstringVisible, accessible label — required.
valuenumberControlled value.
defaultValuenumberInitial value when uncontrolled.
minnumber0Minimum value.
maxnumber100Maximum value.
stepnumber1Increment step.
onValueChange(value: number) => voidFires with the next value while dragging.
disabledbooleanfalseDisables interaction.
testIDstringTest handle for queries.

Code examples

// React — @ghds/react (real <input type="range">; read event.target.value)
import { Slider } from '@ghds/react/slider';
import { useState } from 'react';

const [volume, setVolume] = useState(30);
<Slider label="Volume" value={volume} onChange={(event) => setVolume(Number(event.target.value))} />;
<Slider label="Rating" min={0} max={10} step={1} defaultValue={7} />;
<!-- Web Components — @ghds/web-components -->
<script type="module">
  import '@ghds/web-components/slider';
</script>
<gh-slider label="Volume" value="30"></gh-slider>
<gh-slider label="Rating" min="0" max="10" step="1" value="7"></gh-slider>
// React Native — @ghds/react-native
// Drag only — no arrow-key stepping on React Native. Value arrives via onValueChange.
import { Slider } from '@ghds/react-native/slider';

<Slider label="Volume" value={volume} onValueChange={setVolume} />;

Live Demo

React and Web Components render live below. React Native can’t run in a browser without additional react-native-web wiring (not set up in this site), so its usage is shown as a code sample instead.

React @ghds/react

Web Components @ghds/web-components