Skip to content
Lenso UI

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类型默认值描述
valuenumber | number[]-当前值(受控)。
defaultValuenumber | number[]-默认值(非受控)。
onChange(value: number | number[]) => void-值变化时的事件处理函数。
onChangeEnd(value: number | number[]) => void-拖动结束时的事件处理函数。
minValuenumber0Slider 的最小值。
maxValuenumber100Slider 的最大值。
stepnumber1Slider 的步进值。
formatOptionsIntl.NumberFormatOptions-数值标签的显示格式。
orientation"horizontal" | "vertical""horizontal"Slider 的方向。
isDisabledboolean-Slider 是否禁用。
aria-labelstring-Slider 的无障碍标签。
aria-labelledbystring-标注 Slider 的元素 ID。
classNamestring-额外的 CSS 类。
childrenReactNode | RenderFunction-Slider 内容或渲染函数。
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderRenderProps>-使用自定义渲染函数覆盖默认 DOM 元素。

Slider.Output

Prop类型默认值描述
classNamestring-额外的 CSS 类。
childrenReactNode | RenderFunction-输出内容或渲染函数。
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderOutputRenderProps>-使用自定义渲染函数覆盖默认 DOM 元素。

Slider.Track

Prop类型默认值描述
classNamestring-额外的 CSS 类。
childrenReactNode | RenderFunction-轨道内容或渲染函数。
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderTrackRenderProps>-使用自定义渲染函数覆盖默认 DOM 元素。

Slider.Fill

Prop类型默认值描述
classNamestring-额外的 CSS 类。
styleCSSProperties-行内样式。

Slider.Thumb

Prop类型默认值描述
indexnumber0滑块在 Slider 内的索引。
isDisabledboolean-该滑块是否禁用。
namestring-输入元素名称,用于提交 HTML 表单。
classNamestring-额外的 CSS 类。
childrenReactNode | RenderFunction-滑块内容或渲染函数。
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, SliderThumbRenderProps>-使用自定义渲染函数覆盖默认 DOM 元素。

RenderProps

对 Slider.Output 或 Slider.Track 使用渲染函数时,会提供以下值:

Prop类型描述
stateSliderStateSlider 的状态。
valuesnumber[]按滑块索引管理的数值。
getThumbValueLabel(index: number) => string返回指定滑块数值的字符串标签。
orientation"horizontal" | "vertical"Slider 的方向。
isDisabledbooleanSlider 是否禁用。

示例

基本用法

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 文档。

相关组件