# 滑块

用户在给定范围内选择一个值的输入组件。

## Features

- 可以是可控或不可控的。

- 支持多个滑块。

- 支持滑块之间的最小值。

- 支持在轨道上触摸或点击以更新值。

- 支持从右到左的方向。

- 完整的键盘导航。

## [架构](#架构)

导入所有部分并将其组合在一起。

```jsx
import { Slider } from "radix-ui";

export default () => (
  <Slider.Root>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>

    <Slider.Thumb />
  </Slider.Root>
);
```

## [API 参考](#api-参考)

### [根节点](#根节点)

包含滑块的所有部分。当在 `form` 中使用时，它将为每个滑块渲染一个 `input`，以确保事件正确传播。

| Prop                    | Type       | Default          |
| ----------------------- | ---------- | ---------------- |
| `asChild`               | `boolean`  | `false`          |
| `defaultValue`          | `number[]` | No default value |
| `value`                 | `number[]` | No default value |
| `onValueChange`         | `function` | No default value |
| `onValueCommit`         | `function` | No default value |
| `name`                  | `string`   | No default value |
| `disabled`              | `boolean`  | `false`          |
| `orientation`           | `enum`     | `"horizontal"`   |
| `dir`                   | `enum`     | No default value |
| `inverted`              | `boolean`  | `false`          |
| `min`                   | `number`   | `0`              |
| `max`                   | `number`   | `100`            |
| `step`                  | `number`   | `1`              |
| `minStepsBetweenThumbs` | `number`   | `0`              |
| `form`                  | `string`   | No default value |

| Data attribute       | Values                       |
| -------------------- | ---------------------------- |
| `[data-disabled]`    | 禁用时存在                   |
| `[data-orientation]` | `"vertical" \| "horizontal"` |

### [轨道](#轨道)

包含 `Slider.Range` 的轨道。

| Prop      | Type      | Default |
| --------- | --------- | ------- |
| `asChild` | `boolean` | `false` |

| Data attribute       | Values                       |
| -------------------- | ---------------------------- |
| `[data-disabled]`    | 禁用时存在                   |
| `[data-orientation]` | `"vertical" \| "horizontal"` |

### [范围](#范围)

范围部分。必须位于 `Slider.Track` 内部。

| Prop      | Type      | Default |
| --------- | --------- | ------- |
| `asChild` | `boolean` | `false` |

| Data attribute       | Values                       |
| -------------------- | ---------------------------- |
| `[data-disabled]`    | 禁用时存在                   |
| `[data-orientation]` | `"vertical" \| "horizontal"` |

### [滑块](#滑块-1)

可拖动的滑块。您可以渲染多个滑块。

| Prop      | Type      | Default |
| --------- | --------- | ------- |
| `asChild` | `boolean` | `false` |

| Data attribute       | Values                       |
| -------------------- | ---------------------------- |
| `[data-disabled]`    | 禁用时存在                   |
| `[data-orientation]` | `"vertical" \| "horizontal"` |

## [示例](#示例)

### [垂直方向](#垂直方向)

使用 `orientation` 属性创建一个垂直滑块。

```jsx
// index.jsx

import { Slider } from "radix-ui";

import "./styles.css";

export default () => (
  <Slider.Root className="SliderRoot" defaultValue={[50]} orientation="vertical">
    <Slider.Track className="SliderTrack">
      <Slider.Range className="SliderRange" />
    </Slider.Track>

    <Slider.Thumb className="SliderThumb" />
  </Slider.Root>
);
```

```css
/* styles.css */

.SliderRoot {
  position: relative;

  display: flex;

  align-items: center;
}

.SliderRoot[data-orientation="vertical"] {
  flex-direction: column;

  width: 20px;

  height: 100px;
}

.SliderTrack {
  position: relative;

  flex-grow: 1;

  background-color: grey;
}

.SliderTrack[data-orientation="vertical"] {
  width: 3px;
}

.SliderRange {
  position: absolute;

  background-color: black;
}

.SliderRange[data-orientation="vertical"] {
  width: 100%;
}

.SliderThumb {
  display: block;

  width: 20px;

  height: 20px;

  background-color: black;
}
```

### [创建范围](#创建范围)

添加多个滑块和值以创建一个范围滑块。

```jsx
import { Slider } from "radix-ui";

export default () => (
  <Slider.Root defaultValue={[25, 75]}>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>

    <Slider.Thumb />

    <Slider.Thumb />
  </Slider.Root>
);
```

### [定义步长](#定义步长)

使用 `step` 属性增加步进间隔。

```jsx
import { Slider } from "radix-ui";

export default () => (
  <Slider.Root defaultValue={[50]} step={10}>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>

    <Slider.Thumb />
  </Slider.Root>
);
```

### [防止滑块重叠](#防止滑块重叠)

使用 `minStepsBetweenThumbs` 避免滑块值相等。

```jsx
import { Slider } from "radix-ui";

export default () => (
  <Slider.Root defaultValue={[25, 75]} step={10} minStepsBetweenThumbs={1}>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>

    <Slider.Thumb />

    <Slider.Thumb />
  </Slider.Root>
);
```

## [无障碍](#无障碍)

遵循 [滑块 WAI-ARIA 设计模式](https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb)。

### [键盘交互](#键盘交互)

| Key                 | Description                                  |
| ------------------- | -------------------------------------------- |
| `ArrowRight`        | 根据 `orientation` 的值递增/递减 `step` 值。 |
| `ArrowLeft`         | 根据 `orientation` 的值递增/递减 `step` 值。 |
| `ArrowUp`           | 值增加 `step` 数量。                         |
| `ArrowDown`         | 值减少 `step` 数量。                         |
| `PageUp`            | 值增加一个较大的 `step`。                    |
| `PageDown`          | 值减少一个较大的 `step`。                    |
| `Shift + ArrowUp`   | 值增加一个较大的 `step`。                    |
| `Shift + ArrowDown` | 值减少一个较大的 `step`。                    |
| `Home`              | 将值设置为最小值。                           |
| `End`               | 将值设置为最大值。                           |

## [自定义 API](#自定义-api)

通过将基本部分抽象为自己的组件来创建自定义 API。

### [抽象所有部分](#抽象所有部分)

此示例抽象了所有 `Slider` 部分，以便可以将其用作自闭合元素。

#### 用法

```jsx
import { Slider } from "./your-slider";

export default () => <Slider defaultValue={[25]} />;
```

#### 实现

```jsx
// your-slider.jsx

import { Slider as SliderPrimitive } from "radix-ui";

export const Slider = React.forwardRef((props, forwardedRef) => {
  const value = props.value || props.defaultValue;

  return (
    <SliderPrimitive.Slider {...props} ref={forwardedRef}>
      <SliderPrimitive.Track>
        <SliderPrimitive.Range />
      </SliderPrimitive.Track>

      {value.map((_, i) => (
        <SliderPrimitive.Thumb key={i} />
      ))}
    </SliderPrimitive.Slider>
  );
});
```

## [注意事项](#注意事项)

### [鼠标事件未触发](#鼠标事件未触发)

由于在实现过程中遇到的 [限制](https://github.com/radix-ui/primitives/blob/83a8c13bf66f3d9f17d77caeb187a69eb146930b/packages/react/slider/src/Slider.tsx#L383-L384)，以下示例将无法按预期正常工作，`onMouseDown` 和 `onMouseUp` 事件处理程序将不会触发：

```jsx
<Slider.Root
  onMouseDown={() => console.log("onMouseDown")}
  onMouseUp={() => console.log("onMouseUp")}
>
  …
</Slider.Root>
```

我们建议使用指针事件（例如 `onPointerDown`，`onPointerUp`）。尽管存在上述限制，但这些事件更适合跨平台/设备处理，因为它们适用于所有指针输入类型（鼠标、触摸、笔等）。

<!--$-->

<!--/$-->
