'use client'
import { useState } from 'react'
import { Slider } from '@hina-ui/react'
export default function Demo() {
const [volume, setVolume] = useState<number | undefined>(60)
return <Slider value={volume} onValueChange={setVolume} aria-label="音量" className="w-64" />
}
用法
import { Slider } from '@hina-ui/react'
滑块在 min 与 max 之间取一个数,value / onValueChange 绑定当前值。拖动过程中值持续更新,松手时另外调用一次 onCommit。未声明的属性都会传给拇指元素,应当用 aria-label 或者 aria-labelledby 命名。宽度归布局,滑块本身撑满容器。
当前值:40
'use client'
import { useState } from 'react'
import { Slider, Stack, Text } from '@hina-ui/react'
export default function Demo() {
const [brightness, setBrightness] = useState<number | undefined>(40)
return (
<Stack gap="sm" className="w-64">
<Slider value={brightness} onValueChange={setBrightness} aria-label="亮度" />
<Text size="sm" tone="muted">
当前值:{brightness}
</Text>
</Stack>
)
}
示例
范围与步长
min、max 与 step 决定取值范围与粒度,键盘方向键也按 step 移动。
'use client'
import { useState } from 'react'
import { Slider } from '@hina-ui/react'
export default function Demo() {
const [rating, setRating] = useState<number | undefined>(3.5)
return (
<Slider
value={rating}
onValueChange={setRating}
min={1}
max={5}
step={0.5}
aria-label="评分"
className="w-64"
/>
)
}
方向
dir 支持 ltr 和 rtl,优先于 ConfigProvider 的全局方向配置;未配置时继承外层元素的 dir。切换方向会同步更新轨道、拇指、刻度点与刻度文字。
RTL 下最小值在右、最大值在左;右方向键减小数值,左方向键增大数值,Home / End 仍分别跳到最小值与最大值。
LTR
RTL
'use client'
import { useState } from 'react'
import { Slider, Stack, Text } from '@hina-ui/react'
const marks = [0, 25, 50, 75, 100].map(value => ({ value, label: String(value) }))
export default function Demo() {
const [value, setValue] = useState<number | undefined>(25)
return (
<Stack gap="lg" className="w-72 max-w-full">
{(['ltr', 'rtl'] as const).map(dir => (
<Stack key={dir} gap="xs">
<Text size="sm" tone="muted">
{dir.toUpperCase()}
</Text>
<Slider
value={value}
onValueChange={setValue}
dir={dir}
marks={marks}
step={5}
aria-label={'数值 (' + dir.toUpperCase() + ')'}
/>
</Stack>
))}
</Stack>
)
}
刻度
marks 在轨道上放刻度点,带 label 的刻度在下方显示文字。
'use client'
import { useState } from 'react'
import { Slider } from '@hina-ui/react'
const marks = [
{ value: 0, label: '慢' },
{ value: 25 },
{ value: 50, label: '中' },
{ value: 75 },
{ value: 100, label: '快' },
]
export default function Demo() {
const [speed, setSpeed] = useState<number | undefined>(50)
return (
<Slider
value={speed}
onValueChange={setSpeed}
step={25}
marks={marks}
aria-label="翻页速度"
className="w-64"
/>
)
}
取值标签
取值标签是一个 Tooltip,以拇指为触发器,随拇指移动,接近视口边缘时会翻转到另一侧。默认在悬停、聚焦与拖动时显示当前值;label 为 always 时始终显示,为 none 时不显示。format 定制显示的文字,默认按当前语言格式化数字。与 IconButton 的提示相同,它依赖应用中的 TooltipProvider,缺少时不显示。
'use client'
import { useState } from 'react'
import { Slider, Stack } from '@hina-ui/react'
export default function Demo() {
const [quality, setQuality] = useState<number | undefined>(80)
const [opacity, setOpacity] = useState<number | undefined>(30)
return (
<Stack gap="lg" className="w-64 pt-6">
<Slider
value={quality}
onValueChange={setQuality}
label="always"
format={(v: number) => `${v}%`}
aria-label="图片质量"
/>
<Slider value={opacity} onValueChange={setOpacity} label="none" aria-label="遮罩透明度" />
</Stack>
)
}
尺寸
size 有 sm、md、lg 三档,轨道高 20、24、28 像素,拇指 12、16、20 像素,与 Switch 相同。
import { Slider, Stack } from '@hina-ui/react'
export default function Demo() {
return (
<Stack gap="sm" className="w-64">
<Slider size="sm" value={30} aria-label="小号" />
<Slider size="md" value={50} aria-label="中号" />
<Slider size="lg" value={70} aria-label="大号" />
</Stack>
)
}
状态
disabled 禁用整个滑块。
import { Slider } from '@hina-ui/react'
export default function Demo() {
return <Slider disabled value={45} aria-label="已禁用" className="w-64" />
}
松手时提交
onCommit 只在一次拖动或者一次按键结束时调用,适合发起请求之类代价较高的操作。
拖动中:20,松手后:20
'use client'
import { useState } from 'react'
import { Slider, Stack, Text } from '@hina-ui/react'
export default function Demo() {
const [value, setValue] = useState<number | undefined>(20)
const [committed, setCommitted] = useState(20)
return (
<Stack gap="sm" className="w-64">
<Slider value={value} onValueChange={setValue} aria-label="阈值" onCommit={setCommitted} />
<Text size="sm" tone="muted">
拖动中:{value},松手后:{committed}
</Text>
</Stack>
)
}
在表单中
放进 FormField 后,标签通过 aria-labelledby 关联到拇指,说明与错误信息由字段渲染;校验规则与提交交给 Form。
'use client'
import { useState } from 'react'
import * as v from 'valibot'
import { Button, Form, FormField, Slider, Text } from '@hina-ui/react'
const schema = v.object({
quality: v.pipe(v.number(), v.minValue(60, '画质不能低于 60')),
})
export default function Demo() {
const [values, setValues] = useState({ quality: 40 })
const [saved, setSaved] = useState('')
async function save(data: unknown) {
await new Promise(resolve => setTimeout(resolve, 600))
setSaved(JSON.stringify(data))
}
return (
<Form values={values} rules={schema} className="w-80" onSubmit={save}>
{({ submitting }) => (
<>
<FormField name="quality" label="导出画质" description="60 以下的画质会明显失真">
<Slider
value={values.quality}
onValueChange={quality => setValues({ ...values, quality: quality ?? 0 })}
min={0}
max={100}
step={5}
/>
</FormField>
<Button type="submit" loading={submitting} className="self-start">
导出
</Button>
{saved && (
<Text tone="muted" size="sm">
已导出:{saved}
</Text>
)}
</>
)}
</Form>
)
}
行为
- 点击轨道任意位置,拇指跳到该处并开始拖动;拖动时拇指与填充跟手,不带过渡;点击与键盘引起的跳动带过渡。
- 键盘 Tab 落在拇指上,左右方向键按
step移动,PageUp / PageDown 大步移动,Home / End 跳到两端。 - 悬停整条滑块时拇指落墨、取值标签淡入;按住拖动时加深。
无障碍
- 拇指是
role="slider",带aria-valuenow、aria-valuemin、aria-valuemax与aria-orientation。 - 通过
aria-label或者aria-labelledby给拇指命名;刻度对屏幕阅读器隐藏,屏幕阅读器读取的是aria-valuenow;取值标签显示时作为拇指的aria-describedby。
API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
value | number | — | 当前值,未绑定时落在 min |
min | number | 0 | 最小值 |
max | number | 100 | 最大值 |
step | number | 1 | 步长 |
dir | 'ltr' | 'rtl' | — | 方向,未指定时继承 |
marks | Array<{ value: number; label?: string }> | — | 刻度 |
label | 'auto' | 'always' | 'none' | 'auto' | 取值标签的显示方式 |
format | (value: number) => string | — | 取值标签的文字,默认按语言格式化 |
size | 'sm' | 'md' | 'lg' | 'md' | 尺寸 |
disabled | boolean | false | 是否禁用 |
className | string | — | 追加至根元素的类名 |
回调
| 回调 | 参数 | 说明 |
|---|---|---|
onValueChange | value: number | 值变化时,拖动中持续触发 |
onCommit | value: number | 一次拖动或者按键结束时 |