Range

PreviousNext

A dual-handle range slider for selecting values within a defined range, with single or dual cursor modes

$100$0
'use client';

import { Range } from '@/ui/forms/Range';

export function RangeDemo() {
  return (
    <Range
      options={[
        { value: 0, label: '$0' },
        { value: 25, label: '$25' },
        { value: 50, label: '$50' },
        { value: 75, label: '$75' },
        { value: 100, label: '$100' },
      ]}
      ariaLabel="Price range"
      className="max-w-md"
    />
  );
}

Installation

npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/range.json

Usage

'use client';
 
import { Range } from '@/docs/lib/ui/forms/range';
import { useState } from 'react';
 
export function Component() {
  const [values, setValues] = useState<number[]>([0, 4]);
 
  const options = [
    { value: 0, label: '$0' },
    { value: 25, label: '$25' },
    { value: 50, label: '$50' },
    { value: 75, label: '$75' },
    { value: 100, label: '$100' },
  ];
 
  return (
    <Range options={options} onChange={(name, value) => setValues(value)} ariaLabel="Price range" />
  );
}

API Reference

Range

PropTypeDefaultDescription
options{ value: number; label: string }[]RequiredArray of option objects defining the selectable values and their labels for the range slider
onChange(name: string, value: number[]) => void-Callback function triggered when slider values change, receives name and array of selected values
singleCursorModebooleanfalseWhen true, displays only one slider handle instead of two for single value selection
minnumber0Minimum value for the range slider (index in options array)
ariaLabelstring"Range"Accessible label for the range input elements, important for screen readers
classNamestring-Additional CSS classes to apply to the range container
dataTestIdstring"range"Test ID for the range container element, useful for automated testing
stepnumber1Step increment for the slider (inherited from input[type="range"])
disabledbooleanfalseWhen true, disables both slider handles and prevents user interaction
readOnlybooleanfalseWhen true, prevents onChange from firing but doesn't visually disable the sliders
idstringAutoCustom ID for the range inputs (auto-generated with useId if not provided)
namestringAutoName attribute for the range inputs (defaults to id value)
...restInputHTMLAttributes<HTMLInputElement>-All standard HTML input attributes (except onChange which is overridden)

Notes

  • Dual-handle slider: By default, the Range component displays two slider handles for selecting a range of values. The first handle (valueA) starts at the maximum index and the second (valueB) starts at the minimum.
  • Single cursor mode: Set singleCursorMode={true} to display only one slider handle for single value selection instead of a range.
  • Options-based: Unlike traditional range sliders that work with continuous numeric values, this component uses an array of options with discrete values and labels. The slider positions correspond to indices in the options array.
  • Visual feedback: Each handle has an associated output element that displays the label of the currently selected option, positioned dynamically based on the slider value.
  • ResizeObserver integration: The component uses ResizeObserver to measure the container width and adjust CSS custom properties for accurate slider positioning and handle placement.
  • CSS custom properties: The component uses CSS variables (--min, --max, --valueA, --valueB, --inputWidth, --thumbWidth) to control the visual appearance and positioning of the range slider and handles.
  • State management: Internal state tracks both slider values (valueA and valueB) independently. Changes to either slider trigger the onChange callback with both values as an array.
  • Read-only behavior: When readOnly is true, the sliders remain interactive visually but the onChange handler is not called, preventing state updates.
  • Accessibility: Use the ariaLabel prop to provide descriptive labels for screen readers. Each input element receives this label for proper accessibility support.
  • Data attributes: The component sets data-name="Range" and data-testid attributes on the container for testing and debugging purposes.
  • Client component: This is a client component that uses hooks (useState, useId, useMeasure) and requires the "use client" directive in Next.js App Router.