# Slider

A control for a value in a range, with one thumb or, when the value has two numbers, a range. Pass `aria-label` (or `aria-labelledby`) to name a single thumb, or `thumbLabels` for each thumb of a range. Arrow keys step, Page keys and Home/End jump. The thumb starts at `min` unless the app gives `defaultValue`; leave it there for a choice the person hasn't made, and show the value beside the slider, since a position alone isn't a number.

- Registry name: `slider` (`@candor/slider`)
- Tier: Free (MIT). No licence key needed.
- Docs: https://candor.themethodic.com/docs/slider

## Install

```bash
npx candor-ui add slider
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/slider`.
It brings in: render-prop, tokens, utils.
npm packages: lucide-react@^1.67.0, radix-ui@^1.8.1.

## Example

```tsx
"use client"

import * as React from "react"
import { Slider } from "@/components/ui/slider"
import { Label } from "@/components/ui/label"

export default function Example() {
  const [budget, setBudget] = React.useState([20])
  const [range, setRange] = React.useState([10, 40])
  return (
    <div className="flex w-full max-w-sm flex-col gap-6">
      <div className="flex flex-col gap-2.5">
        <div className="flex items-center justify-between text-sm">
          <Label id="budget-label">Spending limit per run</Label>
          <span className="tabular-nums text-muted-foreground">${budget[0]}</span>
        </div>
        <Slider aria-labelledby="budget-label" min={0} max={100} step={5} value={budget} onValueChange={setBudget} />
      </div>
      <div className="flex flex-col gap-2.5">
        <div className="flex items-center justify-between text-sm">
          <span className="font-medium">Run time to keep</span>
          <span className="tabular-nums text-muted-foreground">
            {range[0]} to {range[1]} minutes
          </span>
        </div>
        <Slider thumbLabels={["Shortest run", "Longest run"]} min={0} max={60} value={range} onValueChange={setRange} />
      </div>
      <div className="flex flex-col gap-2.5">
        <span className="text-sm font-medium">Retention</span>
        <Slider aria-label="Retention in days" defaultValue={[30]} max={90} locked="Your plan keeps history for 30 days." />
      </div>
    </div>
  )
}
```

## <Slider>

Props:

- `locked?: string | undefined`: Why the slider can't be changed. With a reason it stays focusable but the pointer and arrow keys do nothing, it is marked `aria-disabled` and described by the reason, and the reason is printed under it. Without one the slider is normal. Use this rather than `disabled`, which takes the slider out of the tab order and says nothing.
- `thumbLabels?: string[] | undefined`: A name for each thumb, in order (a range has two: "Lowest price", "Highest price"). A thumb without one takes `aria-label`, then Radix's English "Minimum" and "Maximum" on a range, so give them in the app's language.

Also takes the props of `React.ComponentProps<typeof SliderPrimitive.Root>`, `RenderProp`.

## Motion

- **tint** (tint): The thumb's ring fades in when the pointer is over it and when it takes keyboard focus.

Set with `--cd-motion-slider-<moment>-*` in your brand file; the families are in the design reference.

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider` (fixed strings) and `TermsProvider` (nouns); entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
