跳转到内容

Transfer 穿梭框 ​

左右两栏,把条目从一侧移到另一侧。

用法 ​

collection 是条目全集的唯一事实源,value 只承载落在右侧的一批

待选权限
新建
编辑
删除
导出
审计
已选权限
查看

已选:read

组件结构 ​

加粗的是必需部件。

data-scope="transfer":root · hidden-input · source-panel · target-panel · panel-header · panel-title · panel-count · search · list · group · group-label · item · item-text · item-description · item-suffix · item-checkbox · empty · loading · to-target-trigger · to-source-trigger · select-all-trigger

示例 ​

搜索过滤 ​

searchable 为每侧配一个搜索框,筛选后剩余的才参与方向键、全选与移动

待选城市
北京
上海
广州
深圳
杭州
成都
武汉
西安
已选城市

条目禁用 ​

禁用写在 items 上:不可勾选也不可移动,但仍可聚焦、仍是方向键的起点

待选
查看
新建
删除
已选
所有者(内置)

单向移动 ​

oneWay 把向回移动的路径整个封闭,右侧不再接受勾选,向回的按钮也不必编写

可订阅指标
CPU 用量
内存用量
磁盘 IO
网络吞吐
请求量
已订阅

条目自定义内容 ​

条目的外观归作者:勾选格与文本各就各位,前后再各加一段自己的标记

候选成员
林可前端工程师
周宁服务端工程师
秦朗测试工程师
许知产品经理
项目组
何雨交互设计

列表分组 ​

本侧当前可见的条目由组件给出,据此分组渲染;group 是 role=group 的段落壳,段标题不进入方向键也不参与移动

可授予
读取
查看详情
导出数据
写入
新建
编辑
删除
管理
授权
审计
已授予
读取
查看列表
写入
管理

范围选择 ​

按住 Shift 点击某一项,选中锚点到它的一段;锚点跨到另一侧时退化为普通勾选

点左侧第一项,再按住 Shift 点更下面的一项 —— 中间整段一起勾上。 两侧是各自独立的列表,锚点跨到另一侧时退化成普通勾选。

待选权限
新建
编辑
删除
导出
审计
已选权限
查看

已选:read

一万条只渲染可视区 ​

面板插槽给出的是本侧当前可见的全集,作者按滚动位置切一段挂载,上下各留一个撑高块;全选、计数与移动不读 DOM,照常管理到窗口外

全部商品
商品 SKU-00001
商品 SKU-00002
商品 SKU-00004
商品 SKU-00005
商品 SKU-00006
商品 SKU-00007
商品 SKU-00008
商品 SKU-00009
商品 SKU-00010
商品 SKU-00011
商品 SKU-00012
商品 SKU-00013
商品 SKU-00014
商品 SKU-00015
本次上架
商品 SKU-00003

已上架 1 件

整块换档 ​

面板高度、表头、条目行、勾选格与移动按钮各是一个令牌,写在根上整块一起换档

紧凑

待选权限
新建
编辑
删除
导出
审计
已选权限
查看

宽松

待选权限
新建
编辑
删除
导出
审计
已选权限
查看

语气与尺寸 ​

tone 更换勾选标记的色族,size 更换条目行与勾选格的几何档;两轴写在根上,两侧面板一起变化

待选 · success
新建
编辑
已选
查看
待选 · danger
新建
编辑
已选
查看
待选 · sm
新建
编辑
已选
查看
待选 · lg
新建
编辑
已选
查看

设计指引 ​

何时使用 ​

  • 从一份候选中选出一个子集,且用户需要同时看到未选与已选。
  • 已选项的顺序或数量需要一目了然(分配权限、选人)。

何时不用 ​

特性 ​

  • 两栏都可搜索,filter 可自定义匹配规则。
  • 勾中的条目铺品牌淡底行面并由行首的方框标记,与表格选中行同一副外观;两侧定高列表挂自绘滚动条。
  • oneWay 单向移动:只能移向目标,不可退回。
  • 条目可逐条声明语气,搬到另一侧仍带着自己的那一份。
  • 条目可写副文本,第 2 行放一句解释,搬到另一侧一并带着。
  • 条目行尾留一格给作者(计数、徽标);行首那一格归勾选框。
  • 万级条目时只渲染可视区。
  • 每一侧的空(empty)与在途(loading)各有部件;loading 为真时两侧列表报 aria-busy,空态让位。
  • 设置 name 后,目标侧每个值以一个同名原生字段提交;源侧勾选 selection 不参与提交。三端自动装配隐藏出口,无需手写节点。
  • 值内逗号保留原样,使用 new FormData(form).getAll(name) 读取数组;目标为空时没有该字段,显式选中的空字符串则是一个有效字段值。
  • form 可指定同一文档或影子树内的原生表单 ID;指定无效 ID 时不关联其他表单。整体 disabled 不提交,只读和禁用条目已经存在的目标值仍提交。
  • 原生 form.reset() 恢复 defaultValue 与 defaultSelection,清理搜索与导航状态。受控值没有声明默认值时保持业务数据;声明默认值时只通知重置意图,由业务回写受控值。

组合 ​

最佳实践 ​

  • 两栏都显示计数,用户才知道剩余数量。
  • 候选很大时把搜索做成远端过滤,不把全量数据载入前端。

反模式 ​

  • 在窄屏上使用:两栏加中间的按钮列放不下。
  • 移动后不保留滚动位置,用户每移动一条都要重新定位。

API 参考 ​

产物 ​

层值
自定义元素<xh-transfer>
Vue 组件XhTransferEmpty XhTransferGroup XhTransferGroupLabel XhTransferItem XhTransferItemCheckbox XhTransferItemDescription XhTransferItemSuffix XhTransferItemText XhTransferList XhTransferLoading XhTransferPanelCount XhTransferPanelHeader XhTransferPanelTitle XhTransferRoot XhTransferSearch XhTransferSelectAllTrigger XhTransferSourcePanel XhTransferTargetPanel XhTransferToSourceTrigger XhTransferToTargetTrigger
组合式函数useTransfer
状态机transferMachine
皮肤@xihan-ui/styles/transfer.css

Props ​

属性类型必填说明
collectionTransferItem[]条目全集,元信息的唯一事实源。默认为空。
valuestring[]落在 target 侧的值。提供即受控:cell 直读 prop,写入只发 onValueChange 不落内部值。
defaultValuestring[]
namestring原生表单字段名;目标侧每个值提交一个同名字段。
formstring原生表单 ID;显式指定时覆盖祖先表单归属。
selectionstring[]两侧合计被勾选的值(用于移动)。提供即受控,语义同上。
defaultSelectionstring[]
searchableboolean每侧带一个搜索框;关闭时搜索框仍在 DOM 中但带 hidden,且搜索串一律按空处理。
filterTransferFilter自定义匹配规则;默认为标签大小写不敏感包含。
disabledboolean整个控件禁用:条目为 aria-disabled,三个按钮与搜索框使用原生 disabled。
readOnlyboolean只读:两侧照常浏览与搜索,但勾选不可修改、也不可移动。禁用还额外移除键盘入口。
invalidboolean校验失败:两侧列表报告 aria-invalid,各角色节点带 data-invalid。
loadingboolean条目加载中:两侧列表报告 aria-busy,显示在途占位、隐藏空态占位。
toneTone语气:brand / neutral / success / warning / danger / info,决定勾选标记使用哪族颜色。
sizeSize尺寸:sm / md / lg,决定条目与勾选格的几何档位。
oneWayboolean只能向右不能向回:向回移动的路径整体关闭,target 侧也不再接受勾选。
loopboolean列表内方向键到达末尾是否回绕,默认 true。
dirDirection文字方向,默认 ltr;决定列表内哪个横向方向键是移向对面。
translationsPartial<TransferTranslations>
onValueChange(details: TransferValueChangeDetails) => void
onSelectionChange(details: TransferSelectionChangeDetails) => void

TransferItem ​

collection 的元素。

字段类型必填说明
valuestring是
labelstring是展示名,也是搜索过滤的取字来源。
disabledboolean条目禁用:不可勾选、也不可移动,但它仍可聚焦、仍是方向键的起点。
toneTone该条自身的性质:已失效的写 danger、需要留意的写 warning。不写即与其余条目同档。 只换字色与悬停 / 按下的面,不表达勾选与校验;勾选的标记与禁用都压过它。 两侧面板读同一份数据,条目搬到哪一侧都带着自己的语气。
descriptionstring副文本,写入 item-description 部件;未提供时本条不铺该部件。 它是第 2 行的说明,跟着条目走 muted 档,不跟语气;放不下一行的解释才用它, 一句话能说清的写进 label。

事件 ​

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

事件载荷说明
value-changeTransferValueChangeDetails落在右侧的值变化;detail 为 { value: string[] }
selection-changeTransferSelectionChangeDetails勾选集合变化;detail 为 { value: string[] }

插槽 ​

仅列出带载荷的插槽。

Vue 组件插槽载荷说明
XhTransferRootdefaultTransferRootSlotProps

React 适配器 props ​

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

React 组件属性类型必填说明
XhTransferGroupvaluestring是
XhTransferItemvaluestring是
XhTransferRootchildrenSlotChildren<TransferRootSlotProps>

状态 ​

公开状态写入 data-state。

部件取值
item'checked' | 'unchecked'
item-text'checked' | 'unchecked'
item-description'checked' | 'unchecked'
item-suffix'checked' | 'unchecked'
item-checkbox'checked' | 'unchecked'
select-all-triggercheckStates[panel.side]

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

状态:idle

事件:FORM.RESET · VALUE.SET · SELECTION.SET · ITEM.TOGGLE · SIDE.TOGGLE_ALL · ITEMS.MOVE · SEARCH.SET · ITEM.FOCUS · LIST.BLUR · PRESS.START · PRESS.END

判据:canPress

connect API ​

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

成员类型说明
collectionreadonly TransferItem[]条目全集(作者提供的数据,原样透出)。
valuestring[]落在 target 侧的值。
selectionstring[]两侧合计被勾选的值。
disabledboolean
readOnlyboolean
invalidboolean
oneWayboolean
searchableboolean
visibleItems(side: TransferSide) => readonly TransferItem[]某一侧当前可见的条目(分侧 + 搜索之后),顺序恒为 collection 原序。
checkedValues(side: TransferSide) => string[]某一侧当前实际勾选的值(只计可见且未禁用的条目,与三态、移动同一口径)。
checkState(side: TransferSide) => TransferCheckState
query(side: TransferSide) => string
canMove(to: TransferSide) => boolean向 to 侧移动当前是否可行:对面有勾选的可操作条目,且该路径未被 oneWay 关闭。
isChecked(value: string) => boolean
sideOf(value: string) => TransferSide
setValue(next: string[]) => void
setSelection(next: string[]) => void
setQuery(side: TransferSide, query: string) => void
toggle(value: string, options?: { extend?: boolean }) => void切换某一项的勾选。extend 为真时选中锚点到该项的范围(同侧才成立)。
toggleAll(side: TransferSide) => void
move(to: TransferSide) => void程序化移动;焦点安排不在这里处理,那需要知道触发的节点。
getRootProps() => T['element']
getHiddenInputProps(props: { value: string }) => T['input']单个目标值的原生出口;适配器按 value 数组逐项渲染,空集合不提交字段。
getPanelProps(props: TransferPanelProps) => T['element']
getPanelHeaderProps(props: TransferPanelProps) => T['element']
getPanelTitleProps(props: TransferPanelProps) => T['element']
getPanelCountProps(props: TransferPanelProps) => T['element']
getSearchProps(props: TransferPanelProps) => T['input']
getListProps(props: TransferPanelProps) => T['element']
getSelectAllTriggerProps(props: TransferPanelProps) => T['button']
getEmptyProps(props: TransferPanelProps) => T['element']空态占位:放在面板中、list 的兄弟;本侧没有任何可见条目时显示,其余时候带 hidden。
getLoadingProps(props: TransferPanelProps) => T['element']在途占位:与空态占位同一位置,两者不同时显示:加载期间显示它,空态让位。
getGroupProps(props: TransferGroupProps) => T['element']分组容器:role=group,条目挂在其中;分组标题经 aria-labelledby 关联。
getGroupLabelProps(props: TransferGroupProps) => T['element']分组标题:不是选项、不进入导航,只作为本组的可及名。
getItemProps(props: TransferItemProps) => T['element']
getItemTextProps(props: TransferItemProps) => T['element']
getItemDescriptionProps(props: TransferItemProps) => T['element']
getItemSuffixProps(props: TransferItemProps) => T['element']
getItemCheckboxProps(props: TransferItemProps) => T['element']
getToTargetTriggerProps() => T['button']
getToSourceTriggerProps() => T['button']

无障碍 ​

键盘 ​

规格出处:W3C APG

按键生效条件行为
Enter / Spaceheld on 条目 / 全选格 / 搬运按钮, 未禁用、未只读、未加载且部件自身可用按住期间条目、全选格或搬运按钮投影 data-pressed,与指针 :active 同一副按压面;抬起或失焦撤下,搬完后按钮失去可搬的条目时由机器撤下。勾选与搬运语义照旧由这一次按键承担
Tab / Shift+Tabfocus outside a list每一侧列表只占一个 Tab 位:焦点进入该侧锚点条目,无锚点时先落列表容器再由它转投;两个搬运按钮与两个全选格各自另占一位,禁用时自动退出 Tab 序列
ArrowDownfocus in a list焦点移到本侧下一个可停留条目(禁用项跳过、尽头按 loop 回绕);不会走到对面那一侧去
ArrowUpfocus in a list焦点移到本侧上一个可停留条目
Homefocus in a list焦点移到本侧首个可停留条目
Endfocus in a list焦点移到本侧末个可停留条目
Space / Enter / Ctrl+Spacefocus on item, 本侧可勾选切换焦点条目的勾选态,其余勾选不动;条目禁用、或已被搜索藏起来则不认
Shift+ArrowDown / Shift+ArrowUpfocus in a list, 本侧可勾选焦点移到相邻条目并切换它的勾选态;反向移动即取消刚扩展进来的条目
Ctrl+A / Cmd+Afocus in a list, 本侧可勾选勾中本侧全部可操作条目(可见且未禁用);已经全勾则一并取消
ArrowRight / ArrowLeftfocus in a list, 该方向指向对面且可以移动把本侧勾选的条目移动到对面(dir=rtl 时左右语义对调);移动完成后焦点落到目标侧的列表上。方向指向本侧、或当前无法移动时该键放行给页面
Enter / Spacefocus on to-target-trigger / to-source-trigger把对面勾中的条目搬过来(原生按钮的激活行为);搬完按钮多半随即变禁用,焦点改落到目的地那一侧的列表上
Enter / Spacefocus on select-all-trigger全选/取消全选该侧可操作条目(原生按钮的激活行为);三态经 aria-checked 上报,半选时是 mixed

ARIA ​

以下属性由 connect 生成。

部件属性值
searcharia-controlslistId[panel.side]
searcharia-labelledbytitleId[panel.side]
listaria-busy'true' | undefined
listaria-disabled'true' | 'false'
listaria-invalid'true' | 'false'
listaria-labelledbytitleId[panel.side]
listaria-multiselectable'true' | 'false'
listaria-readonly'true' | 'false'
listrole'listbox'
grouparia-labelledbygroup-label 部件的 id
grouprole'group'
itemaria-disabled'true' | 'false'
itemaria-selected'true' | 'false'
itemrole'option'
item-checkboxaria-hidden'true'
to-target-triggeraria-controlslistId.target
to-target-triggeraria-labellabel.toTarget
to-source-triggeraria-controlslistId.source
to-source-triggeraria-labellabel.toSource
select-all-triggeraria-checked'true' | 'mixed' | 'false'
select-all-triggeraria-controlslistId[panel.side]
select-all-triggerrole'checkbox'

样式参考 ​

皮肤 ​

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

数据属性 ​

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

部件属性值
rootdata-disabled''(条件成立时才出现)
rootdata-invalid''(条件成立时才出现)
rootdata-loading''(条件成立时才出现)
rootdata-one-way''(条件成立时才出现)
rootdata-readonly''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-toneprops.tone
panel-headerdata-disabled''(条件成立时才出现)
panel-headerdata-sidepanel.side
panel-titledata-sidepanel.side
panel-countdata-checked-countString(checked[panel.side].length)
panel-countdata-countString(visible[panel.side].length)
panel-countdata-sidepanel.side
searchdata-sidepanel.side
listdata-disabled''(条件成立时才出现)
listdata-invalid''(条件成立时才出现)
listdata-readonly''(条件成立时才出现)
listdata-sidepanel.side
groupdata-disabled''(条件成立时才出现)
groupdata-sidegroup.side
group-labeldata-disabled''(条件成立时才出现)
group-labeldata-sidegroup.side
itemdata-disabled''(条件成立时才出现)
itemdata-highlighted''(条件成立时才出现)
itemdata-pressed''(条件成立时才出现)
itemdata-sideitem.side
itemdata-state'checked' | 'unchecked'
itemdata-toneindex.get(v)?.tone
itemdata-xh-collection-context'page'
itemdata-xh-collection-item''
itemdata-xh-collection-sizeprops.size
item-textdata-disabled''(条件成立时才出现)
item-textdata-highlighted''(条件成立时才出现)
item-textdata-sideitem.side
item-textdata-state'checked' | 'unchecked'
item-textdata-xh-collection-slot'text'
item-descriptiondata-disabled''(条件成立时才出现)
item-descriptiondata-highlighted''(条件成立时才出现)
item-descriptiondata-sideitem.side
item-descriptiondata-state'checked' | 'unchecked'
item-descriptiondata-xh-collection-slot'description'
item-suffixdata-disabled''(条件成立时才出现)
item-suffixdata-highlighted''(条件成立时才出现)
item-suffixdata-sideitem.side
item-suffixdata-state'checked' | 'unchecked'
item-suffixdata-xh-collection-slot'suffix'
item-checkboxdata-disabled''(条件成立时才出现)
item-checkboxdata-highlighted''(条件成立时才出现)
item-checkboxdata-sideitem.side
item-checkboxdata-state'checked' | 'unchecked'
item-checkboxdata-xh-collection-slot'prefix'
emptydata-disabled''(条件成立时才出现)
emptydata-sidepanel.side
loadingdata-disabled''(条件成立时才出现)
loadingdata-sidepanel.side
to-target-triggerdata-disabled''(条件成立时才出现)
to-target-triggerdata-pressed''(条件成立时才出现)
to-target-triggerdata-xh-action-control''
to-target-triggerdata-xh-action-display'always'
to-target-triggerdata-xh-action-profile'icon'
to-target-triggerdata-xh-action-size'sm'
to-target-triggerdata-xh-action-variant'outline'
to-source-triggerdata-disabled''(条件成立时才出现)
to-source-triggerdata-pressed''(条件成立时才出现)
to-source-triggerdata-xh-action-control''
to-source-triggerdata-xh-action-display'always'
to-source-triggerdata-xh-action-profile'icon'
to-source-triggerdata-xh-action-size'sm'
to-source-triggerdata-xh-action-variant'outline'
select-all-triggerdata-disabled''(条件成立时才出现)
select-all-triggerdata-pressed''(条件成立时才出现)
select-all-triggerdata-sidepanel.side
select-all-triggerdata-statecheckStates[panel.side]
select-all-triggerdata-xh-action-control''
select-all-triggerdata-xh-action-display'always'
select-all-triggerdata-xh-action-profile'text'
select-all-triggerdata-xh-action-size'xs'
select-all-triggerdata-xh-action-variant'ghost'
paneldata-disabled''(条件成立时才出现)
paneldata-sidepanel.side

CSS 变量 ​

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

变量部件CSS 属性状态默认来源说明
--xh-transfer-checkbox-bgitem-checkbox
select-all-trigger
backgrounddefaulttransparenttransfer 的 item-checkbox、select-all-trigger 部件 background 覆盖槽。
--xh-transfer-checkbox-bg-checkeditem-checkbox
select-all-trigger
backgroundis([data-state='checked'], [data-state='indeterminate'])
state=checked
state=indeterminate
--xh-_transfer-accenttransfer 的 item-checkbox、select-all-trigger 部件 background 覆盖槽。
--xh-transfer-checkbox-bg-disableditem-checkboxbackgrounddisabled--xh-bg-mutedtransfer 的 item-checkbox 部件 background 覆盖槽。
--xh-transfer-checkbox-borderitem-checkbox
select-all-trigger
borderdefault--xh-border-controltransfer 的 item-checkbox、select-all-trigger 部件 border 覆盖槽。
--xh-transfer-checkbox-border-checkeditem-checkbox
select-all-trigger
border-coloris([data-state='checked'], [data-state='indeterminate'])
state=checked
state=indeterminate
--xh-_transfer-accenttransfer 的 item-checkbox、select-all-trigger 部件 border-color 覆盖槽。
--xh-transfer-checkbox-border-disableditem-checkboxborder-colordisabled--xh-border-defaulttransfer 的 item-checkbox 部件 border-color 覆盖槽。
--xh-transfer-checkbox-fgitem-checkbox
select-all-trigger
background-color
color
default
state=checked
state=indeterminate
--xh-_transfer-on-accenttransfer 的 item-checkbox、select-all-trigger 部件 background-color、color 覆盖槽。
--xh-transfer-checkbox-font-sizeitem-checkbox
select-all-trigger
font-sizedefault
state=checked
state=indeterminate
--xh-_transfer-boxtransfer 的 item-checkbox、select-all-trigger 部件 font-size 覆盖槽。
--xh-transfer-checkbox-radiusitem-checkbox
select-all-trigger
border-radiusdefault--xh-shape-insettransfer 的 item-checkbox、select-all-trigger 部件 border-radius 覆盖槽。
--xh-transfer-checkbox-sizeitem-checkbox
select-all-trigger
--xh-icon-size
block-size
inline-size
margin-inline-start
default
state=checked
state=indeterminate
--xh-_transfer-boxtransfer 的 item-checkbox、select-all-trigger 部件 --xh-icon-size、block-size、inline-size、margin-inline-start 覆盖槽。
--xh-transfer-empty-fgemptycolordefault--xh-fg-subtletransfer 的 empty 部件 color 覆盖槽。
--xh-transfer-empty-font-sizeemptyfont-sizedefault--xh-_transfer-font-sizetransfer 的 empty 部件 font-size 覆盖槽。
--xh-transfer-empty-pxemptypadding-inlinedefault--xh-_transfer-pxtransfer 的 empty 部件 padding-inline 覆盖槽。
--xh-transfer-empty-pyemptypadding-blockdefault--xh-space-3transfer 的 empty 部件 padding-block 覆盖槽。
--xh-transfer-fgrootcolordefault--xh-fg-defaulttransfer 的 root 部件 color 覆盖槽。
--xh-transfer-gaprootgapdefault--xh-space-3transfer 的 root 部件 gap 覆盖槽。
--xh-transfer-group-gapgroupgapdefault--xh-list-option-gaptransfer 的 group 部件 gap 覆盖槽。
--xh-transfer-group-label-fggroup-labelcolordefault--xh-fg-subtletransfer 的 group-label 部件 color 覆盖槽。
--xh-transfer-group-label-font-sizegroup-labelfont-sizedefault--xh-text-caption-sizetransfer 的 group-label 部件 font-size 覆盖槽。
--xh-transfer-group-label-font-weightgroup-labelfont-weightdefault--xh-font-weight-mediumtransfer 的 group-label 部件 font-weight 覆盖槽。
--xh-transfer-group-label-pxgroup-labelpadding-inlinedefault--xh-_transfer-pxtransfer 的 group-label 部件 padding-inline 覆盖槽。
--xh-transfer-group-label-pygroup-labelpadding-blockdefault--xh-space-1transfer 的 group-label 部件 padding-block 覆盖槽。
--xh-transfer-group-spacinggroupmargin-block-startdefault--xh-space-1_5transfer 的 group 部件 margin-block-start 覆盖槽。
--xh-transfer-icon-sizeitem
root
to-source-trigger
to-target-trigger
--xh-icon-sizedefault
size=lg
size=sm
--xh-_action-profile-glyph-size
--xh-_collection-glyph-size
--xh-glyph-size-lg
--xh-glyph-size-md
--xh-glyph-size-sm
transfer 的 item、root、to-source-trigger、to-target-trigger 部件 --xh-icon-size 覆盖槽。
--xh-transfer-item-bg-hoveritembackground-colordisabled
error
highlighted
hover
is(:focus-visible, [data-highlighted])
not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error])
--xh-bg-subtletransfer 的 item 部件 background-color 覆盖槽。
--xh-transfer-item-bg-presseditembackground-colordisabled
error
is(:active, [data-pressed])
not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error])
pressed
--xh-bg-subtle-hovertransfer 的 item 部件 background-color 覆盖槽。
--xh-transfer-item-bg-selecteditembackground-colordisabled
error
is([aria-selected='true'], [data-selected])
not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error])
selected
xh-collection-context=page
--xh-bg-brand-subtletransfer 的 item 部件 background-color 覆盖槽。
--xh-transfer-item-fgitemcolordefault
disabled
error
highlighted
hover
is(:active, [data-pressed])
is(:focus-visible, [data-highlighted])
not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error])
pressed
--xh-fg-defaulttransfer 的 item 部件 color 覆盖槽。
--xh-transfer-item-fg-selecteditemcolordisabled
error
highlighted
hover
is(:active, [data-pressed])
is(:focus-visible, [data-highlighted])
is([aria-selected='true'], [data-selected])
not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error])
pressed
selected
xh-collection-context=page
--xh-fg-on-brand-subtletransfer 的 item 部件 color 覆盖槽。
--xh-transfer-item-font-sizeitemfont-sizedefault--xh-_transfer-font-sizetransfer 的 item 部件 font-size 覆盖槽。
--xh-transfer-item-gapitemgapdefault--xh-_transfer-gaptransfer 的 item 部件 gap 覆盖槽。
--xh-transfer-item-leadingitemline-heightdefault--xh-leading-normaltransfer 的 item 部件 line-height 覆盖槽。
--xh-transfer-item-pxitempadding-inlinedefault--xh-_transfer-pxtransfer 的 item 部件 padding-inline 覆盖槽。
--xh-transfer-item-pyitempadding-blockdefault--xh-_transfer-item-pytransfer 的 item 部件 padding-block 覆盖槽。
--xh-transfer-item-radiusitemborder-radiusdefault--xh-shape-controltransfer 的 item 部件 border-radius 覆盖槽。
--xh-transfer-list-gaplistgapdefault--xh-list-option-gaptransfer 的 list 部件 gap 覆盖槽。
--xh-transfer-list-hlistblock-sizedefault--xh-viewport-h-mdtransfer 的 list 部件 block-size 覆盖槽。
--xh-transfer-list-pxlistpadding-inlinedefault--xh-space-1transfer 的 list 部件 padding-inline 覆盖槽。
--xh-transfer-list-pylistpadding-blockdefault--xh-space-1transfer 的 list 部件 padding-block 覆盖槽。
--xh-transfer-loading-fgloadingcolordefault--xh-fg-subtletransfer 的 loading 部件 color 覆盖槽。
--xh-transfer-loading-font-sizeloadingfont-sizedefault--xh-_transfer-font-sizetransfer 的 loading 部件 font-size 覆盖槽。
--xh-transfer-loading-pxloadingpadding-inlinedefault--xh-_transfer-pxtransfer 的 loading 部件 padding-inline 覆盖槽。
--xh-transfer-loading-pyloadingpadding-blockdefault--xh-space-3transfer 的 loading 部件 padding-block 覆盖槽。
--xh-transfer-panel-bgsource-panel
target-panel
backgrounddefault--xh-bg-surfacetransfer 的 source-panel、target-panel 部件 background 覆盖槽。
--xh-transfer-panel-bg-disabledsource-panel
target-panel
backgrounddisabled--xh-bg-mutedtransfer 的 source-panel、target-panel 部件 background 覆盖槽。
--xh-transfer-panel-borderpanel-header
source-panel
target-panel
border
border-block-end
default--xh-border-defaulttransfer 的 panel-header、source-panel、target-panel 部件 border、border-block-end 覆盖槽。
--xh-transfer-panel-border-invalidroot
source-panel
target-panel
border-colorinvalid
is([data-scope='transfer'][data-part='source-panel'], [data-scope='transfer'][data-part='target-panel'])
--xh-border-invalidtransfer 的 root、source-panel、target-panel 部件 border-color 覆盖槽。
--xh-transfer-panel-count-fgpanel-countcolordefault--xh-fg-subtletransfer 的 panel-count 部件 color 覆盖槽。
--xh-transfer-panel-count-font-sizepanel-countfont-sizedefault--xh-text-caption-sizetransfer 的 panel-count 部件 font-size 覆盖槽。
--xh-transfer-panel-header-gappanel-headergapdefault--xh-_transfer-gaptransfer 的 panel-header 部件 gap 覆盖槽。
--xh-transfer-panel-header-pxpanel-headerpadding-inlinedefault--xh-_transfer-pxtransfer 的 panel-header 部件 padding-inline 覆盖槽。
--xh-transfer-panel-header-pypanel-headerpadding-blockdefault--xh-space-2transfer 的 panel-header 部件 padding-block 覆盖槽。
--xh-transfer-panel-radiussource-panel
target-panel
border-radiusdefault--xh-shape-surfacetransfer 的 source-panel、target-panel 部件 border-radius 覆盖槽。
--xh-transfer-panel-title-fgpanel-titlecolordefault--xh-fg-defaulttransfer 的 panel-title 部件 color 覆盖槽。
--xh-transfer-panel-title-font-sizepanel-titlefont-sizedefault--xh-text-label-sizetransfer 的 panel-title 部件 font-size 覆盖槽。
--xh-transfer-panel-title-font-weightpanel-titlefont-weightdefault--xh-font-weight-semiboldtransfer 的 panel-title 部件 font-weight 覆盖槽。
--xh-transfer-search-bgsearchbackgrounddefaulttransparenttransfer 的 search 部件 background 覆盖槽。
--xh-transfer-search-bordersearchborder-block-enddefault--xh-border-controltransfer 的 search 部件 border-block-end 覆盖槽。
--xh-transfer-search-fgsearchcolordefault--xh-fg-defaulttransfer 的 search 部件 color 覆盖槽。
--xh-transfer-search-font-sizesearchfont-sizedefault--xh-_transfer-font-sizetransfer 的 search 部件 font-size 覆盖槽。
--xh-transfer-search-hsearchblock-sizedefault--xh-control-h-smtransfer 的 search 部件 block-size 覆盖槽。
--xh-transfer-search-pxsearchpadding-inlinedefault--xh-_transfer-pxtransfer 的 search 部件 padding-inline 覆盖槽。
--xh-transfer-select-all-bg-hoverselect-all-triggerbackground-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hovertransfer 的 select-all-trigger 部件 background-color 覆盖槽。
--xh-transfer-select-all-bg-pressedselect-all-triggerbackground-colordisabled
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-bg-pressedtransfer 的 select-all-trigger 部件 background-color 覆盖槽。
--xh-transfer-select-all-fgselect-all-triggercolordefault
disabled
focus-visible
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-fg-mutedtransfer 的 select-all-trigger 部件 color 覆盖槽。
--xh-transfer-select-all-font-sizeselect-all-triggerfont-sizedefault--xh-text-caption-sizetransfer 的 select-all-trigger 部件 font-size 覆盖槽。
--xh-transfer-select-all-gapselect-all-triggergapdefault--xh-control-gap-smtransfer 的 select-all-trigger 部件 gap 覆盖槽。
--xh-transfer-select-all-radiusselect-all-triggerborder-radiusdefault--xh-shape-insettransfer 的 select-all-trigger 部件 border-radius 覆盖槽。
--xh-transfer-trigger-bgto-source-trigger
to-target-trigger
--xh-ink-surface
background-color
default
xh-ink-surface
--xh-_action-variant-bg-resttransfer 的 to-source-trigger、to-target-trigger 部件 --xh-ink-surface、background-color 覆盖槽。
--xh-transfer-trigger-bg-activeto-source-trigger
to-target-trigger
background-colordisabled
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-bg-pressedtransfer 的 to-source-trigger、to-target-trigger 部件 background-color 覆盖槽。
--xh-transfer-trigger-bg-hoverto-source-trigger
to-target-trigger
background-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hovertransfer 的 to-source-trigger、to-target-trigger 部件 background-color 覆盖槽。
--xh-transfer-trigger-borderto-source-trigger
to-target-trigger
border
border-color
default
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-border-hover
--xh-_action-variant-border-pressed
--xh-_action-variant-border-rest
transfer 的 to-source-trigger、to-target-trigger 部件 border、border-color 覆盖槽。
--xh-transfer-trigger-fgto-source-trigger
to-target-trigger
colordefault
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-fg-hover
--xh-_action-variant-fg-pressed
--xh-_action-variant-fg-rest
transfer 的 to-source-trigger、to-target-trigger 部件 color 覆盖槽。
--xh-transfer-trigger-font-sizeto-source-trigger
to-target-trigger
font-sizedefault--xh-text-label-sizetransfer 的 to-source-trigger、to-target-trigger 部件 font-size 覆盖槽。
--xh-transfer-trigger-pxto-source-trigger
to-target-trigger
padding-inlinedefault--xh-_action-profile-padding-inlinetransfer 的 to-source-trigger、to-target-trigger 部件 padding-inline 覆盖槽。
--xh-transfer-trigger-radiusto-source-trigger
to-target-trigger
border-radiusdefault--xh-shape-controltransfer 的 to-source-trigger、to-target-trigger 部件 border-radius 覆盖槽。
--xh-transfer-trigger-shadow-activeto-source-trigger
to-target-trigger
box-shadowdisabled
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
nonetransfer 的 to-source-trigger、to-target-trigger 部件 box-shadow 覆盖槽。
--xh-transfer-trigger-shadow-hoverto-source-trigger
to-target-trigger
box-shadowdisabled
hover
loading
not([data-disabled])
not([data-loading])
nonetransfer 的 to-source-trigger、to-target-trigger 部件 box-shadow 覆盖槽。
--xh-transfer-trigger-sizeto-source-trigger
to-target-trigger
block-size
inline-size
min-inline-size
default
xh-action-profile=icon
--xh-_action-profile-visual-sizetransfer 的 to-source-trigger、to-target-trigger 部件 block-size、inline-size、min-inline-size 覆盖槽。

动效 ​

动效角色:按压 · 状态(见动效规范)。

background-color · border-color 走 transition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

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

响应式 ​

皮肤按视口分档:min-width: 640px。

皮肤另按输入能力分档:pointer: coarse:同一份皮肤在触屏与带指针的设备上不一样,与视口宽度无关。

RTL ​

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

Released under The MIT License