跳转到内容

Slider 滑块 ​

在连续或离散的区间内拖出一个值或一段范围。

用法 ​

值恒为数组,单滑块即长度 1;方向键移动一格 step,PageUp 与 PageDown 按 largeStep,Home 与 End 到达端点

组件结构 ​

加粗的是必需部件。

data-scope="slider":root · label · control · track · range · thumb · value-text · tick-group · tick · tick-label · hidden-input

示例 ​

区间选择 ​

两个拇指互为对方的边界、永不交叉,minStepsBetweenThumbs 再为它们之间留出格数;getValueText 把值转换为读屏可朗读的文本

竖向 ​

orientation 换为 vertical 后整条控件收为一块,键盘与拖动的方向随之翻转

禁用与只读 ​

禁用的拇指退出 Tab 序列、值也不再随表单提交;只读仍可聚焦与朗读,只是不可推动

颜色 ​

tone 决定已填轨道与滑块使用哪族颜色,不写时沿用品牌色

尺寸 ​

size 改变轨道厚度与滑块直径,不写即默认中档

文字方向 ​

dir 换为 rtl 后轨道从右向左填充,左右两键的语义随之对调;上下键与 Home、End 不受影响

滑块中的内容 ​

thumb 是一个普通容器,放置什么由作者决定;容纳空间依靠 --xh-slider-thumb-size 撑开直径

45%

轨道刻度 ​

刻度分圆点与文案两层:圆点固定在轨道上、文案排在下方且点击跳转到该值,落入已选区间的刻度分段上色;snapToMarks 使拖动/点击/键盘只落在刻度上

0°C26°C37°C沸腾
0°C26°C37°C沸腾

拖动时的值气泡 ​

value-text 挂在 thumb 中即随之移动;推动时由皮肤显示它,气泡中的文字取自作者的格式化函数

已选:¥1,800

离散档位 ​

可选值不必是等距数值:让滑块在档位下标上移动,宿主再把下标映射回自己的取值表,键盘与拖动都只落在档位上

可选:1 / 5 / 10 / 50 / 100 / 500

设计指引 ​

何时使用 ​

  • 用户关心的是相对位置而不是精确数字(音量、透明度、价格区间)。
  • 需要即时看到调整的效果。

何时不用 ​

特性 ​

  • 单值与区间共用一套结构,区间时 minStepsBetweenThumbs 防止两头交叉。
  • marks 绘制刻度,snapToMarks 让值吸附到刻度。
  • 两个回调:拖动途中连续发出,松手时发出一次;持久化使用后者。
  • getValueText 决定读屏读出的内容,不只读数字。

组合 ​

最佳实践 ​

  • 两端标出最小与最大值,用户才能知道当前位置。
  • 拖动时用值气泡显示当前值,松手后收起。

反模式 ​

  • 区间很大却不提供数字输入,拖到精确值几乎不可能。
  • 在移动端把滑块做得过细过短。

API 参考 ​

产物 ​

层值
自定义元素<xh-slider>
Vue 组件XhSliderControl XhSliderHiddenInput XhSliderLabel XhSliderRange XhSliderRoot XhSliderThumb XhSliderTickGroup XhSliderTrack XhSliderValueText
组合式函数useSlider
状态机sliderMachine
皮肤@xihan-ui/styles/slider.css

Props ​

属性类型必填说明
valuenumber[]
defaultValuenumber[]
minnumber
maxnumber
stepnumber
largeStepnumberPageUp / PageDown 的步长,默认 10 倍 step。
orientationOrientation
dirDirection
disabledboolean
readOnlyboolean
invalidboolean
toneTone语气:brand / neutral / success / warning / danger / info,决定使用哪族颜色
sizeSize尺寸:sm / md / lg,决定拇指直径与轨道厚度
namestring表单字段名;多滑块时逐个 append。
minStepsBetweenThumbsnumber相邻滑块至少相隔的格数,默认 0(可以贴在一起但不能交换顺序)。
marksSliderMark[]刻度表:轨道上的圆点与文案,点击文案即跳到该值。
snapToMarksboolean只接受刻度落点:拖动、点击与键盘都吸附到最近 / 下一档刻度。
getValueText(details: SliderValueTextDetails) => string把值转换为可读文字,产出写入拇指的 aria-valuetext。 未提供时不写该属性,读屏回退为朗读 aria-valuenow。
onValueChange(details: SliderValueChangeDetails) => void每次推动都发出;拖动过程中连续发出。
onValueChangeEnd(details: SliderValueChangeEndDetails) => void只在一次操作结束时发出一次,适合用于发起请求。

SliderMark ​

marks 的元素。

字段类型必填说明
valuenumber是
labelstring

事件 ​

自定义元素将载荷放在 detail;Vue 使用同名 emit。

事件载荷说明
value-changeSliderValueTextDetails值变化(拖动途中连续发出);detail 为 { value: number[] }
value-change-endSliderValueChangeEndDetails一次操作收尾时发出一次;detail 为 { value: number[], index: number }

插槽 ​

仅列出带载荷的插槽。

Vue 组件插槽载荷说明
XhSliderRootdefaultSliderRootSlotProps
XhSliderTickGrouptickSliderTickGroupTickSlotProps

React 适配器 props ​

只列各组件自己声明的那些:继承自 ComponentPropsWithRef 的 DOM 属性不在其中,根组件上与上面 Props 表同名的也不重复列。Vue 的对应物是上面的插槽表。

React 组件属性类型必填说明
XhSliderRootchildrenSlotChildren<SliderRootSlotProps>
XhSliderThumbindexnumber | string第几个滑块,多滑块时必须逐个写明;兼收字符串。
XhSliderTickGrouptickSlotChildren<SliderTickSlotProps>逐档刻度的文案接管口;未提供时填入刻度自带的 label。

状态 ​

以下名称仅用于内部状态机。

状态:idle · dragging

事件:VALUE.SET · THUMB.STEP · THUMB.TO_MIN · THUMB.TO_MAX · THUMB.SET · THUMB.FOCUS · DRAG.START · DRAG.MOVE · DRAG.END · FORM.RESET

判据:canDrag

connect API ​

getXxxProps() 返回对应部件的宿主属性。

成员类型说明
valuenumber[]
range{ start: number, end: number }已选区间在轨道上的起止,0-1。
thumbsSliderThumbState[]
marksSliderMarkMeta[]刻度呈现数据:夹进区间、升序去重,带位置与分段上色标记。
draggingboolean
disabledboolean
readOnlyboolean
valueText(index: number) => string某个拇指的值文本:提供 getValueText 时是其产出,否则是值本身。
setValue(next: number[]) => void
setThumbValue(index: number, next: number) => void
getRootProps() => T['element']
getLabelProps() => T['label']
getControlProps() => T['element']
getTrackProps() => T['element']
getRangeProps() => T['element']
getThumbProps(index: number) => T['element']
getValueTextProps(index: number) => T['element']值气泡:挂在拇指中显示该拇指的当前值;aria-hidden,读屏使用拇指自身的 aria-valuetext。
getTickGroupProps() => T['element']刻度容器。
getTickProps(props: SliderTickProps) => T['element']刻度点:轨道上的圆点,纯装饰。
getTickLabelProps(props: SliderTickProps) => T['element']刻度文案:点击把最近的滑块跳到该档。
getHiddenInputProps(index: number) => T['input']

无障碍 ​

键盘 ​

规格出处:W3C APG

按键生效条件行为
ArrowRight / ArrowUpfocus in thumb, not disabled/readOnly按 step 增大;RTL 与竖直排布下按屏幕方向对调,语义恒是"朝 max 走一格"
ArrowLeft / ArrowDownfocus in thumb, not disabled/readOnly按 step 减小,同上对调规则
PageUpfocus in thumb, not disabled/readOnly按 largeStep 增大(默认 10 倍 step)
PageDownfocus in thumb, not disabled/readOnly按 largeStep 减小
Homefocus in thumb, not disabled/readOnly取 min;多滑块时取自己被邻居允许的下界
Endfocus in thumb, not disabled/readOnly取 max;多滑块时取自己被邻居允许的上界

ARIA ​

以下属性由 connect 生成。

部件属性值
thumbaria-disabled'true' | 'false'
thumbaria-labelledbylabel 部件的 id
thumbaria-orientationprops.orientation
thumbaria-valuemaxString(thumb.max)
thumbaria-valueminString(thumb.min)
thumbaria-valuenowString(thumb.value)
thumbaria-valuetextprop('getValueText')?.({ value: thumb.value, index: t…
thumbrole'slider'
value-textaria-hidden'true'
tickaria-hidden'true'

样式参考 ​

皮肤 ​

@xihan-ui/styles/slider.css 使用 [data-scope="slider"][data-part="root"] 部件选择器,位于 xihan.components 层。覆盖样式使用 xihan.overrides。

数据属性 ​

由 connect 生成;条件不成立时不输出无值属性。

部件属性值
rootdata-disabled''(条件成立时才出现)
rootdata-dragging''(条件成立时才出现)
rootdata-invalid''(条件成立时才出现)
rootdata-orientationprops.orientation
rootdata-readonly''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-toneprops.tone
labeldata-disabled''(条件成立时才出现)
labeldata-dragging''(条件成立时才出现)
labeldata-invalid''(条件成立时才出现)
labeldata-orientationprops.orientation
labeldata-readonly''(条件成立时才出现)
controldata-disabled''(条件成立时才出现)
controldata-dragging''(条件成立时才出现)
controldata-invalid''(条件成立时才出现)
controldata-orientationprops.orientation
controldata-readonly''(条件成立时才出现)
trackdata-disabled''(条件成立时才出现)
trackdata-dragging''(条件成立时才出现)
trackdata-invalid''(条件成立时才出现)
trackdata-orientationprops.orientation
trackdata-readonly''(条件成立时才出现)
rangedata-disabled''(条件成立时才出现)
rangedata-dragging''(条件成立时才出现)
rangedata-invalid''(条件成立时才出现)
rangedata-orientationprops.orientation
rangedata-readonly''(条件成立时才出现)
thumbdata-disabled''(条件成立时才出现)
thumbdata-dragging''(条件成立时才出现)
thumbdata-indexString(thumb.index)
thumbdata-invalid''(条件成立时才出现)
thumbdata-orientationprops.orientation
thumbdata-readonly''(条件成立时才出现)
value-textdata-disabled''(条件成立时才出现)
value-textdata-dragging''(条件成立时才出现)
value-textdata-indexString(thumb.index)
value-textdata-invalid''(条件成立时才出现)
value-textdata-orientationprops.orientation
value-textdata-readonly''(条件成立时才出现)
tick-groupdata-disabled''(条件成立时才出现)
tick-groupdata-dragging''(条件成立时才出现)
tick-groupdata-invalid''(条件成立时才出现)
tick-groupdata-orientationprops.orientation
tick-groupdata-readonly''(条件成立时才出现)
tickdata-passed''(条件成立时才出现)
tick-labeldata-passed''(条件成立时才出现)
hidden-inputdata-indexString(thumb.index)

CSS 变量 ​

本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。

变量部件CSS 属性状态默认来源说明
--xh-slider-control-guttercontrol
root
margin-inlinehas([data-part='tick-label'])
orientation=horizontal
--xh-space-6slider 的 control、root 部件 margin-inline 覆盖槽。
--xh-slider-gaprootgapdefault--xh-space-1slider 的 root 部件 gap 覆盖槽。
--xh-slider-label-fglabelcolordefault--xh-fg-defaultslider 的 label 部件 color 覆盖槽。
--xh-slider-label-fg-disabledlabelcolordisabled--xh-fg-subtleslider 的 label 部件 color 覆盖槽。
--xh-slider-label-font-sizelabelfont-sizedefault--xh-text-label-sizeslider 的 label 部件 font-size 覆盖槽。
--xh-slider-label-font-weightlabelfont-weightdefault--xh-text-label-weightslider 的 label 部件 font-weight 覆盖槽。
--xh-slider-range-bgrangebackgrounddefault--xh-_toneslider 的 range 部件 background 覆盖槽。
--xh-slider-range-bg-disabledrangebackgrounddisabled--xh-fg-disabledslider 的 range 部件 background 覆盖槽。
--xh-slider-range-bg-invalidrangebackgroundinvalid--xh-border-invalidslider 的 range 部件 background 覆盖槽。
--xh-slider-range-radiusrangeborder-radiusdefault--xh-shape-pillslider 的 range 部件 border-radius 覆盖槽。
--xh-slider-thumb-bgthumbbackgrounddefault--xh-_toneslider 的 thumb 部件 background 覆盖槽。
--xh-slider-thumb-bg-disabledthumbbackgrounddisabled--xh-bg-surfaceslider 的 thumb 部件 background 覆盖槽。
--xh-slider-thumb-bg-invalidthumbbackgroundinvalid--xh-border-invalidslider 的 thumb 部件 background 覆盖槽。
--xh-slider-thumb-borderthumbborderdefault--xh-border-default-opaqueslider 的 thumb 部件 border 覆盖槽。
--xh-slider-thumb-radiusthumbborder-radiusdefault--xh-shape-circleslider 的 thumb 部件 border-radius 覆盖槽。
--xh-slider-thumb-scale-draggingthumbscaledragging--xh-motion-scale-dragslider 的 thumb 部件 scale 覆盖槽。
--xh-slider-thumb-shadowthumbbox-shadowdefault--xh-elevation-raisedslider 的 thumb 部件 box-shadow 覆盖槽。
--xh-slider-thumb-shadow-disabledthumbbox-shadowdisablednoneslider 的 thumb 部件 box-shadow 覆盖槽。
--xh-slider-thumb-shadow-draggingthumbbox-shadowdragging--xh-elevation-liftedslider 的 thumb 部件 box-shadow 覆盖槽。
--xh-slider-thumb-sizecontrol
root
thumb
block-size
inline-size
margin-block-end
margin-block-start
margin-inline-start
default
orientation=horizontal
orientation=vertical
size=lg
size=sm
--xh-space-3
--xh-space-6
--xh-track-thumb-size
slider 的 control、root、thumb 部件 block-size、inline-size、margin-block-end、margin-block-start、margin-inline-start 覆盖槽。
--xh-slider-tick-bgtickbackgrounddefault--xh-border-strongslider 的 tick 部件 background 覆盖槽。
--xh-slider-tick-bg-activetickbackgroundpassed--xh-_toneslider 的 tick 部件 background 覆盖槽。
--xh-slider-tick-bg-active-disabledtick
tick-group
backgrounddisabled
passed
--xh-fg-disabledslider 的 tick、tick-group 部件 background 覆盖槽。
--xh-slider-tick-bg-disabledtick
tick-group
backgrounddisabled--xh-border-defaultslider 的 tick、tick-group 部件 background 覆盖槽。
--xh-slider-tick-label-fgtick-labelcolordefault--xh-fg-subtleslider 的 tick-label 部件 color 覆盖槽。
--xh-slider-tick-label-fg-activetick-labelcolorpassed--xh-fg-defaultslider 的 tick-label 部件 color 覆盖槽。
--xh-slider-tick-label-fg-disabledtick-group
tick-label
colordisabled--xh-fg-disabledslider 的 tick-group、tick-label 部件 color 覆盖槽。
--xh-slider-tick-label-font-sizetick-labelfont-sizedefault--xh-text-caption-sizeslider 的 tick-label 部件 font-size 覆盖槽。
--xh-slider-tick-label-gaproot
tick-label
margin-block-start
margin-inline-start
default
orientation=vertical
--xh-space-1slider 的 root、tick-label 部件 margin-block-start、margin-inline-start 覆盖槽。
--xh-slider-tick-radiustickborder-radiusdefault--xh-shape-circleslider 的 tick 部件 border-radius 覆盖槽。
--xh-slider-tick-sizetickblock-size
inline-size
default--xh-space-1slider 的 tick 部件 block-size、inline-size 覆盖槽。
--xh-slider-track-bgtrackbackgrounddefault--xh-bg-subtle-activeslider 的 track 部件 background 覆盖槽。
--xh-slider-track-bg-disabledtrackbackgrounddisabled--xh-bg-subtleslider 的 track 部件 background 覆盖槽。
--xh-slider-track-radiustrackborder-radiusdefault--xh-shape-pillslider 的 track 部件 border-radius 覆盖槽。
--xh-slider-track-thicknessroot
track
block-size
inline-size
orientation=horizontal
orientation=vertical
size=lg
size=sm
--xh-space-1
--xh-space-2
--xh-track-thickness
slider 的 root、track 部件 block-size、inline-size 覆盖槽。
--xh-slider-value-text-bgvalue-textbackgrounddefault--xh-_toneslider 的 value-text 部件 background 覆盖槽。
--xh-slider-value-text-fgvalue-textcolordefault--xh-_tone-onslider 的 value-text 部件 color 覆盖槽。
--xh-slider-value-text-font-sizevalue-textfont-sizedefault--xh-text-caption-sizeslider 的 value-text 部件 font-size 覆盖槽。
--xh-slider-value-text-offsetvalue-textmargin-block-end
margin-inline
default
orientation=vertical
--xh-space-2slider 的 value-text 部件 margin-block-end、margin-inline 覆盖槽。
--xh-slider-value-text-pxvalue-textpadding-inlinedefault--xh-space-2slider 的 value-text 部件 padding-inline 覆盖槽。
--xh-slider-value-text-pyvalue-textpadding-blockdefault--xh-space-0_5slider 的 value-text 部件 padding-block 覆盖槽。
--xh-slider-value-text-radiusvalue-textborder-radiusdefault--xh-shape-controlslider 的 value-text 部件 border-radius 覆盖槽。
--xh-slider-vertical-lengthcontrolblock-sizeorientation=vertical10remslider 的 control 部件 block-size 覆盖槽。

动效 ​

动效角色:状态 · 切换(见动效规范)。

可覆盖的动效槽:--xh-slider-thumb-scale-dragging。

box-shadow · opacity · scale 走 transition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

系统开启减弱动效时由令牌层统一收敛,皮肤不另作判断。

RTL ​

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像。

Released under The MIT License