Back to Prisma

Slider

apps/eclipse/content/design-system/components/slider.mdx

latest7.3 KB
Original Source

import { Slider } from "@prisma/eclipse";

Usage

Basic Slider

tsx
import { Slider } from "@prisma/eclipse";

export function BasicSlider() {
  return <Slider defaultValue={[50]} max={100} step={1} />;
}

Live Example:

<div className="w-full max-w-md my-6"> <Slider defaultValue={[50]} max={100} step={1} /> </div>

Controlled Slider

tsx
import { Slider } from "@prisma/eclipse";
import { useState } from "react";

export function ControlledSlider() {
  const [value, setValue] = useState([25]);

  return (
    <div>
      <Slider value={value} onValueChange={setValue} max={100} step={1} />
      <p>Value: {value[0]}</p>
    </div>
  );
}

Range Slider

Use multiple values to create a range selector:

tsx
import { Slider } from "@prisma/eclipse";

export function RangeSlider() {
  return <Slider defaultValue={[25, 75]} max={100} step={1} />;
}

Live Example:

<div className="w-full max-w-md my-6"> <Slider defaultValue={[25, 75]} max={100} step={1} /> </div>

Custom Step Size

tsx
import { Slider } from "@prisma/eclipse";

export function SteppedSlider() {
  return <Slider defaultValue={[50]} max={100} step={10} />;
}

Live Example:

<div className="w-full max-w-md my-6"> <Slider defaultValue={[50]} max={100} step={10} /> </div>

With Min and Max Values

tsx
import { Slider } from "@prisma/eclipse";

export function CustomRangeSlider() {
  return <Slider defaultValue={[0]} min={-50} max={50} step={5} />;
}

Live Example:

<div className="w-full max-w-md my-6"> <Slider defaultValue={[0]} min={-50} max={50} step={5} /> </div>

Disabled State

tsx
import { Slider } from "@prisma/eclipse";

export function DisabledSlider() {
  return <Slider defaultValue={[50]} max={100} step={1} disabled />;
}

Live Example:

<div className="w-full max-w-md my-6"> <Slider defaultValue={[50]} max={100} step={1} disabled /> </div>

Error State

Show an error state with the isErrored prop:

tsx
import { Slider } from "@prisma/eclipse";

export function ErrorSlider() {
  return <Slider defaultValue={[50]} max={100} step={1} isErrored />;
}

Live Example:

<div className="w-full max-w-md my-6"> <Slider defaultValue={[50]} max={100} step={1} isErrored /> </div>

With Labels

tsx
import { Slider } from "@prisma/eclipse";
import { useState } from "react";

export function LabeledSlider() {
  const [value, setValue] = useState([50]);

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <label htmlFor="volume">Volume</label>
        <span className="text-sm text-muted-foreground">{value[0]}%</span>
      </div>
      <Slider
        id="volume"
        value={value}
        onValueChange={setValue}
        max={100}
        step={1}
      />
    </div>
  );
}

Slider Props

  • defaultValue - The initial value(s) when uncontrolled (number[], optional)
  • value - The controlled value(s) (number[], optional)
  • onValueChange - Callback when value changes ((value: number[]) => void, optional)
  • min - Minimum value (number, default: 0)
  • max - Maximum value (number, default: 100)
  • step - Step increment (number, default: 1)
  • disabled - Whether the slider is disabled (boolean, default: false)
  • isErrored - Whether the slider is in an error state (boolean, default: false)
  • orientation - Slider orientation: "horizontal" or "vertical" (default: "horizontal")
  • className - Additional CSS classes (optional)
  • All standard Radix UI Slider props are supported

Features

  • ✅ Single value and range selection
  • ✅ Controlled and uncontrolled modes
  • ✅ Customizable min, max, and step values
  • ✅ Disabled state support
  • ✅ Horizontal and vertical orientations
  • ✅ Keyboard navigation (arrow keys)
  • ✅ Touch and mouse support
  • ✅ Eclipse design system styling
  • ✅ Built on Radix UI primitives
  • ✅ Accessible with ARIA attributes

Best Practices

  • Use single values for simple selections (volume, brightness, etc.)
  • Use range values for filtering (price ranges, date ranges, etc.)
  • Provide clear labels to indicate what the slider controls
  • Display the current value(s) near the slider for user feedback
  • Choose appropriate step sizes based on the value range
  • Use disabled state to indicate unavailable or locked settings
  • Consider showing min/max labels for clarity
  • Ensure sufficient contrast for the slider track and thumb
  • Test touch interactions on mobile devices

Common Use Cases

Volume Control

tsx
<Slider defaultValue={[70]} max={100} step={1} aria-label="Volume" />

Price Range Filter

tsx
<Slider defaultValue={[0, 1000]} min={0} max={5000} step={50} aria-label="Price range" />

Opacity Adjustment

tsx
<Slider defaultValue={[100]} max={100} step={1} aria-label="Opacity" />

Zoom Level

tsx
<Slider defaultValue={[100]} min={50} max={200} step={10} aria-label="Zoom level" />

Rating Selection

tsx
<Slider defaultValue={[3]} min={1} max={5} step={1} aria-label="Rating" />

Accessibility

  • The slider is keyboard accessible using arrow keys:
    • Right/Up Arrow: Increase value by step
    • Left/Down Arrow: Decrease value by step
    • Home: Set to minimum value
    • End: Set to maximum value
    • Page Up: Increase by larger increment
    • Page Down: Decrease by larger increment
  • Screen readers announce the current value and range
  • Use aria-label or associated labels for screen reader context
  • Focus states are clearly visible
  • Touch targets meet minimum size requirements
  • Disabled sliders are not keyboard focusable

Keyboard Navigation

KeyAction
/ Decrease value by step
/ Increase value by step
HomeJump to minimum value
EndJump to maximum value
Page UpIncrease by larger step
Page DownDecrease by larger step

Integration Example

Complete example with state management and value display:

tsx
import { Slider } from "@prisma/eclipse";
import { useState } from "react";

export function SettingsPanel() {
  const [volume, setVolume] = useState([75]);
  const [brightness, setBrightness] = useState([50]);
  const [priceRange, setPriceRange] = useState([0, 1000]);

  return (
    <div className="space-y-6 w-full max-w-md">
      <div className="space-y-2">
        <div className="flex justify-between">
          <label>Volume</label>
          <span className="text-sm text-muted-foreground">{volume[0]}%</span>
        </div>
        <Slider value={volume} onValueChange={setVolume} max={100} />
      </div>

      <div className="space-y-2">
        <div className="flex justify-between">
          <label>Brightness</label>
          <span className="text-sm text-muted-foreground">{brightness[0]}%</span>
        </div>
        <Slider value={brightness} onValueChange={setBrightness} max={100} />
      </div>

      <div className="space-y-2">
        <div className="flex justify-between">
          <label>Price Range</label>
          <span className="text-sm text-muted-foreground">
            ${priceRange[0]} - ${priceRange[1]}
          </span>
        </div>
        <Slider
          value={priceRange}
          onValueChange={setPriceRange}
          min={0}
          max={5000}
          step={50}
        />
      </div>
    </div>
  );
}