Slider 滑块
Slider 允许用户在范围内选择一个或多个值。
用法
import { Slider } from '@lenso/ui';此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";/** Adapted from HeroUI v3.2.6. SPDX-License-Identifier: Apache-2.0 */import { Slider } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({ slider: { width: "100%", maxWidth: 320 } });export function Default() { return ( <Slider xstyle={styles.slider} defaultValue={30}> <Slider.Label>Volume</Slider.Label> <Slider.Output /> <Slider.Control> <Slider.Track> <Slider.Fill /> </Slider.Track> <Slider.Thumb aria-label="Volume" /> </Slider.Control> </Slider> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
组件结构
import { Slider, Label } from '@lenso/ui';
export default () => ( <Slider> <Label /> <Slider.Output /> <Slider.Track> <Slider.Fill /> <Slider.Thumb /> </Slider.Track> </Slider>)示例
禁用
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";/** Adapted from HeroUI v3.2.6. SPDX-License-Identifier: Apache-2.0 */import { Slider } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ root: { width: "100%", maxWidth: "20rem" } });export function Disabled() { return ( <Slider disabled xstyle={styles.root} defaultValue={30}> <Slider.Label>Volume</Slider.Label> <Slider.Output /> <Slider.Control> <Slider.Track> <Slider.Fill /> </Slider.Track> <Slider.Thumb /> </Slider.Control> </Slider> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
范围滑块结构
import { Slider, Label } from '@lenso/ui';
export default () => ( <Slider defaultValue={[25, 75]}> <Label /> <Slider.Output /> <Slider.Track> {({state}) => ( <> <Slider.Fill /> {state.values.map((_, i) => ( <Slider.Thumb key={i} index={i} /> ))} </> )} </Slider.Track> </Slider>)垂直方向
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";/** Adapted from HeroUI v3.2.6. SPDX-License-Identifier: Apache-2.0 */import { Slider } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ wrapper: { display: "flex", height: "16rem", alignItems: "center", justifyContent: "center" }, root: { height: "100%" },});export function Vertical() { return ( <div {...stylex.props(styles.wrapper)}> <Slider xstyle={styles.root} defaultValue={30} orientation="vertical"> <Slider.Label>Volume</Slider.Label> <Slider.Output /> <Slider.Control> <Slider.Track> <Slider.Fill /> </Slider.Track> <Slider.Thumb /> </Slider.Control> </Slider> </div> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
范围选择
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";/** * Adapted from HeroUI v3.2.6. SPDX-License-Identifier: Apache-2.0 * Native Base UI control geometry and value formatting. */import { Slider } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({ root: { width: "100%", maxWidth: "20rem" } });
export function Range() { return ( <Slider xstyle={styles.root} defaultValue={[100, 500]} format={{ currency: "USD", style: "currency" }} max={1000} min={0} step={50} > <Slider.Label>Price Range</Slider.Label> <Slider.Output>{(formattedValues) => formattedValues.join(" – ")}</Slider.Output> <Slider.Control> <Slider.Track> <Slider.Fill /> </Slider.Track> <Slider.Thumb index={0} aria-label="Minimum price" /> <Slider.Thumb index={1} aria-label="Maximum price" /> </Slider.Control> </Slider> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
渲染函数
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";/** Adapted from HeroUI v3.2.6. SPDX-License-Identifier: Apache-2.0 */import { Slider } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ root: { width: "100%", maxWidth: "20rem" } });export function RenderFunction() { return ( <Slider xstyle={styles.root} defaultValue={30} render={(props) => <div {...props} data-custom="foo" />} > <Slider.Label>Volume</Slider.Label> <Slider.Output /> <Slider.Control> <Slider.Track> <Slider.Fill /> </Slider.Track> <Slider.Thumb /> </Slider.Control> </Slider> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
自定义样式
Tailwind CSS
此预览复用英文版适配,不代表中文源示例已完成本地实现。
"use client";/** Adapted from HeroUI v3.2.6. SPDX-License-Identifier: Apache-2.0 */import { Slider } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ root: { width: "100%", maxWidth: "20rem" }, label: { fontWeight: 500, color: "var(--foreground)" }, output: { fontSize: ".75rem", color: "var(--muted)", fontVariantNumeric: "tabular-nums" }, track: { backgroundColor: "var(--default)" }, fill: { backgroundColor: "var(--accent)" }, thumb: { backgroundColor: "var(--accent)", "::after": { backgroundColor: "var(--accent-foreground)" }, },});export function CustomStyles() { return ( <Slider xstyle={styles.root} defaultValue={40}> <Slider.Label xstyle={styles.label}>Brightness</Slider.Label> <Slider.Output xstyle={styles.output} /> <Slider.Control> <Slider.Track xstyle={styles.track}> <Slider.Fill xstyle={styles.fill} /> </Slider.Track> <Slider.Thumb xstyle={styles.thumb} /> </Slider.Control> </Slider> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
全局 CSS
若要自定义组件类,可使用 @layer components 指令。了解更多。
@layer components { .slider { @apply flex flex-col gap-2; }
.slider__output { @apply text-muted-fg text-sm; }
.slider-track { @apply relative h-2 w-full rounded-full bg-surface-secondary; }
.slider-fill { @apply absolute h-full rounded-full bg-accent; }
.slider-thumb { @apply size-4 rounded-full bg-accent border-2 border-background; }}样式参考
HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。
CSS 类
Slider 组件使用以下 CSS 类(查看源码样式):
基础类 [!toc]
.slider- Slider 根容器.slider__output- 显示当前值的输出元素.slider-track- 包含填充与滑块的轨道元素.slider-fill- 显示已选范围的填充元素.slider-thumb- 单个滑块控制点
状态类 [!toc]
.slider[data-disabled="true"]- 禁用状态.slider[data-orientation="vertical"]- 纵向方向.slider-thumb[data-dragging="true"]- 滑块正在拖动.slider-thumb[data-focus-visible="true"]- 滑块键盘聚焦.slider-thumb[data-disabled="true"]- 滑块禁用状态.slider-track[data-fill-start="true"]- 填充从起点开始.slider-track[data-fill-end="true"]- 填充在终点结束
交互状态
该组件同时支持 CSS 伪类与 data 属性,以提供更灵活的状态控制:
- 悬停:滑块上的
:hover或[data-hovered="true"] - 聚焦:滑块上的
:focus-visible或[data-focus-visible="true"] - 拖动:滑块上的
[data-dragging="true"] - 禁用:Slider 或滑块上的
:disabled或[data-disabled="true"]
API 参考
Slider
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
value | number | number[] | - | 当前值(受控)。 |
defaultValue | number | number[] | - | 默认值(非受控)。 |
onChange | (value: number | number[]) => void | - | 值变化时的事件处理函数。 |
onChangeEnd | (value: number | number[]) => void | - | 拖动结束时的事件处理函数。 |
minValue | number | 0 | Slider 的最小值。 |
maxValue | number | 100 | Slider 的最大值。 |
step | number | 1 | Slider 的步进值。 |
formatOptions | Intl.NumberFormatOptions | - | 数值标签的显示格式。 |
orientation | "horizontal" | "vertical" | "horizontal" | Slider 的方向。 |
isDisabled | boolean | - | Slider 是否禁用。 |
aria-label | string | - | Slider 的无障碍标签。 |
aria-labelledby | string | - | 标注 Slider 的元素 ID。 |
className | string | - | 额外的 CSS 类。 |
children | ReactNode | RenderFunction | - | Slider 内容或渲染函数。 |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderRenderProps> | - | 使用自定义渲染函数覆盖默认 DOM 元素。 |
Slider.Output
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 额外的 CSS 类。 |
children | ReactNode | RenderFunction | - | 输出内容或渲染函数。 |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderOutputRenderProps> | - | 使用自定义渲染函数覆盖默认 DOM 元素。 |
Slider.Track
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 额外的 CSS 类。 |
children | ReactNode | RenderFunction | - | 轨道内容或渲染函数。 |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderTrackRenderProps> | - | 使用自定义渲染函数覆盖默认 DOM 元素。 |
Slider.Fill
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 额外的 CSS 类。 |
style | CSSProperties | - | 行内样式。 |
Slider.Thumb
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
index | number | 0 | 滑块在 Slider 内的索引。 |
isDisabled | boolean | - | 该滑块是否禁用。 |
name | string | - | 输入元素名称,用于提交 HTML 表单。 |
className | string | - | 额外的 CSS 类。 |
children | ReactNode | RenderFunction | - | 滑块内容或渲染函数。 |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderThumbRenderProps> | - | 使用自定义渲染函数覆盖默认 DOM 元素。 |
RenderProps
对 Slider.Output 或 Slider.Track 使用渲染函数时,会提供以下值:
| Prop | 类型 | 描述 |
|---|---|---|
state | SliderState | Slider 的状态。 |
values | number[] | 按滑块索引管理的数值。 |
getThumbValueLabel | (index: number) => string | 返回指定滑块数值的字符串标签。 |
orientation | "horizontal" | "vertical" | Slider 的方向。 |
isDisabled | boolean | Slider 是否禁用。 |
示例
基本用法
import { Slider, Label } from '@lenso/ui';
<Slider defaultValue={30}> <Label>Volume</Label> <Slider.Output /> <Slider.Track> <Slider.Fill /> <Slider.Thumb /> </Slider.Track></Slider>范围滑块
import { Slider, Label } from '@lenso/ui';
<Slider defaultValue={[100, 500]} formatOptions={{style: "currency", currency: "USD"}} maxValue={1000} minValue={0} step={50}> <Label>Price Range</Label> <Slider.Output /> <Slider.Track> {({state}) => ( <> <Slider.Fill /> {state.values.map((_, i) => ( <Slider.Thumb key={i} index={i} /> ))} </> )} </Slider.Track></Slider>受控数值
import { Slider, Label } from '@lenso/ui';import { useState } from 'react';
function ControlledSlider() { const [value, setValue] = useState(25);
return ( <> <Slider value={value} onChange={setValue}> <Label>Volume</Label> <Slider.Output /> <Slider.Track> <Slider.Fill /> <Slider.Thumb /> </Slider.Track> </Slider> <p>Current value: {value}</p> </> );}自定义数值格式
import { Slider, Label } from '@lenso/ui';
<Slider defaultValue={60} formatOptions={{style: "currency", currency: "USD"}}> <Label>Price</Label> <Slider.Output /> <Slider.Track> <Slider.Fill /> <Slider.Thumb /> </Slider.Track></Slider>垂直方向
import { Slider, Label } from '@lenso/ui';
<Slider defaultValue={30} orientation="vertical" aria-label="Volume"> <Label>Volume</Label> <Slider.Output /> <Slider.Track> <Slider.Fill /> <Slider.Thumb /> </Slider.Track></Slider>自定义输出展示
import { Slider, Label } from '@lenso/ui';
<Slider defaultValue={[25, 75]}> <Label>Range</Label> <Slider.Output> {({state}) => state.values.map((_, i) => state.getThumbValueLabel(i)).join(' – ') } </Slider.Output> <Slider.Track> {({state}) => ( <> <Slider.Fill /> {state.values.map((_, i) => ( <Slider.Thumb key={i} index={i} /> ))} </> )} </Slider.Track></Slider>无障碍
Slider 组件实现 ARIA slider 模式,并提供:
- 完整的键盘导航支持(方向键、Home、End、Page Up/Down)
- 数值变化时的屏幕阅读器播报
- 合理的焦点管理
- 禁用状态支持
- 通过隐藏 input 元素与 HTML 表单集成
- 结合区域设置进行数值格式化的国际化支持
- 从右到左(RTL)语言支持
更多信息见 React Aria Slider 文档。