跳转到内容

Tree 树 ​

层级数据的展开与选择:分支可展开,节点可选。

用法 ​

collection 是层级元信息的唯一事实源,标记只负责外观;缩进由子层容器自行撑开

项目文件
src
main.ts
README.md

组件结构 ​

加粗的是必需部件。

data-scope="tree":root · label · tree · item · item-indicator · item-text · item-description · item-suffix · branch · branch-control · branch-trigger · branch-indicator · branch-text · branch-content · node-drag-trigger · empty · loading · live-region

示例 ​

多选 ​

multiple 关闭时是单选,开启后点击与确认键都变为切换,选中集合形状不变仍是数组

投放城市
华东
上海
杭州
南京
华北
北京
天津
选中:hz

受控 ​

传入 expandedValue / selection 后由宿主决定,组件只发事件不落内部值,宿主写回后才变化

文档目录
接口
鉴权
用户
展开:api · 选中:(无)

点击行展开与禁用节点 ​

缺省点行只选中、展开归箭头与左右方向键,expandOnClick 打开后点行同时切换展开态;禁用节点仍可聚焦,只是确认键不响应它

构建产物
build
vite.config.ts
pnpm-lock.yaml(禁用)
README.md

关键词过滤 ​

collection 换一份树即换一棵:标记跟随数据重新铺设,过滤后剩余的分支一并全部展开

投放城市
华东
上海
杭州
南京

异步加载子节点 ​

展开时才请求数据:先放置一行禁用的占位,取回后就地替换,收起再展开不重复请求

组织架构

前缀与行尾 ​

行中放置什么由标记决定:文字前放图标、文字后放操作,展开箭头也可以移到行尾

工作区
src
index.ts
app.vue
(还没动过)

只让叶子进入选中集合 ​

选中受控后由宿主决定:分支的值直接不写回,点击目录只剩展开收起这一个效果

要提交的文件
src
index.ts
app.vue
已选:(无)

级联勾选 ​

multiple 加 cascade 内建父子传导:点击分支整枝勾选、子全勾则父勾、部分勾选为半选;勾选与半选都画在行尾,半选是一道横杠,两态都由组件报告

投放城市
华东
上海
杭州
南京
华北
北京
天津

选中值(默认只收叶):hz

拖拽移动 ​

整个节点都是拖动源:按住拖到目标位置松手,也可以 Tab 进树后用 Alt + 上下键在同层移动、Alt + 左右键改变层级。三档落点(插在前 / 插在后 / 放进目录)连同指示线、自我后代守卫与读屏播报都归库;树仍不拥有数据,宿主只需按库报告的 value、parent、index 调整数组,外加一条 allowDrop 决定本次是否允许

邮箱目录
收件箱3
报价单.pdf
周报.md
会议纪要.md
归档1
去年总结.docx
回收站0
按住任意一行拖走,或 Tab 进树里按 Alt + 方向键搬

末端横排 ​

leaf-orientation 按结构判据横排子节点全为叶子的层;要指定哪一层横排就在节点上标注 childrenOrientation,它比树级值优先,标注 vertical 也可覆盖

菜单授权
系统管理
用户管理
新增
编辑
删除
导出
角色管理
新增
授权
删除
日志管理
查看
导出

范围选择 ​

按住 Shift 点击某一项,选中锚点到它的一段;按可见序取值,折叠的子节点不会被选入

点「上海」,再按住 Shift 点「北京」 —— 中间整段一起选上。 再按住 Shift 点「南京」,选区往回收,起点不变。

投放城市
华东
上海
杭州
南京
华北
北京
天津
选中:(无)

变体 ​

variant="ghost" 去掉外框与底色,树直接落在页面上;默认 outline 保持带框的外观

src
main.ts
App.vue
README.md
src
main.ts
App.vue
README.md

设计指引 ​

何时使用 ​

  • 文件目录、组织架构、权限节点等任意深度的层级数据。
  • 需要在树上多选并处理父子级联。

何时不用 ​

  • 树只用于选一个值时,使用树选择,它把树收进浮层。
  • 层级规整、层数固定且只为选值时,使用级联选择。
  • 数据是扁平的时,使用列表或表格。

特性 ​

  • 展开集合与选中集合两套值各自可受控。
  • variant 决定外框形态,默认 outline;subtle 换成淡底无描边,ghost 让树直接落在页面上。
  • 选中与树形选择器同一种读法:行不换面,单选、多选与级联都只在行尾画对号;分支行也摆 item-indicator,级联下的半选画横杠。
  • cascade 与 checkedStrategy 决定勾选父节点是否带子节点,以及回显给哪一层。
  • 支持只让叶子进选中集合、关键词过滤、子节点异步加载、拖放换父。
  • 展开与选中分开:点行只选中,展开归箭头与左右方向键;expandOnClick 打开后点整行才顺带展开。
  • 节点可逐条声明语气,不向下传导;叶子行与分支行同样表达。
  • 节点可写副文本,第 2 行放一句解释,不进连打检索串。
  • 节点行尾留一格给作者(计数、徽标),排在对号之前;行首那一格归展开箭头与拖拽把手。
  • 空(empty)与在途(loading)两个相位各有部件,都放在 root 内作为 tree 的兄弟;loading 为真时树报告 aria-busy,空态让位。
  • leafOrientation 按结构判据横排:子节点全是叶子的层跟随它,其余始终竖排。
  • 节点上标 childrenOrientation: 'horizontal' | 'vertical' 指定该层子节点的排列方向,优先于 leafOrientation;标 vertical 可以把树级的 horizontal 改回竖排。根层不受影响,始终竖排。

组合 ​

最佳实践 ​

  • 大树必须虚拟化或按需加载,一次展开全部会卡顿。
  • 级联勾选的策略与后端约定一致。
  • 只需要某一层横排时标 childrenOrientation,不开启树级 leafOrientation:后者按结构判断,其他恰好“子节点全是叶子”的层也会横排,并随数据增减变化。

反模式 ​

  • 展开状态不持久,用户每次进入都要重新展开。
  • 拖放换父没有落点提示。

API 参考 ​

产物 ​

层值
自定义元素<xh-tree>
Vue 组件XhTreeBranch XhTreeBranchContent XhTreeBranchControl XhTreeBranchIndicator XhTreeBranchText XhTreeBranchTrigger XhTreeEmpty XhTreeItem XhTreeItemDescription XhTreeItemIndicator XhTreeItemSuffix XhTreeItemText XhTreeLabel XhTreeLiveRegion XhTreeLoading XhTreeNodeDragTrigger XhTreeRoot XhTreeTree
组合式函数useTree
状态机treeMachine
皮肤@xihan-ui/styles/tree.css

Props ​

属性类型必填说明
collectionTreeNode[]树数据,层级元信息的唯一事实源。默认为空树。
variantControlVariant外框形态:outline 带描边与底色(默认),subtle 淡底无描边,ghost 去掉描边与底色只保留行。
leafOrientationOrientation末端层的排布方式,默认 vertical(每行一个)。horizontal 使它们并排铺开。 只作用于子节点全是叶子的层:菜单授权中即按钮层: 一个菜单下十几个按钮,横向排成一行,省去纵向翻找。中间层与整棵树恒为纵向, 它们承载的是层级本身,横向排布会失去层级信息。 这是结构判据,逐层自动识别。需要精确指定哪一层横向排布时,在节点上标注 childrenOrientation,它优先于本项。 只影响排布,不改变键盘:方向键在树上是层级操作(左右收展、上下移动可见行), 这是 treeview 的规范语义,不随排布方向改写。
expandedValuestring[]展开集合。提供即受控:cell 直读 prop,写入只发 onExpandedValueChange 不落内部值。
defaultExpandedValuestring[]
selectionstring[]选中集合。提供即受控,语义同上。
defaultSelectionstring[]
multipleboolean复选:点击与确认键都是切换,tree 带 aria-multiselectable=true。默认 false(单选)。
cascadebooleanmultiple 下父子级联勾选:点击分支整枝传导、子全勾父勾、部分勾选半选, 禁用子树整棵冻结。默认 false(朴素切换);single 下无效。
checkedStrategyCascadeStrategy级联下对外值的收敛策略,默认 child(只收叶);parent = 最高整枝,all = 全部勾选节点。
expandOnClickboolean点击分支行(与确认键)是否同时展开 / 收起,默认 false:展开与选中分开,只有 branch-trigger 与左右方向键能改变展开态。
disabledboolean整棵树禁用:所有节点为 aria-disabled,键盘与点击都不再改变展开 / 选中。
loadingboolean节点加载中:树报告 aria-busy,显示在途占位、隐藏空态占位。
loopboolean上下键到达首尾是否回绕,默认 false。
typeaheadboolean连打检索,默认开启。关闭后可打印字符一律放行给页面。
dirDirection文字方向,默认 ltr;只对调左右方向键的展开 / 收起语义。
translationsPartial<TreeTranslations>
nodeDraggableboolean节点可以拖动移动。整个节点都是拖动源,不另设把手。
allowDrop(move: TreeMove) => boolean本次移动是否允许。收到的是折算后的落点(移到哪个父节点下的第几位)。 未提供时全部允许:落进自身后代与落在禁用节点上两条由库自行拦截。
onNodeMove(move: TreeMove) => void
onExpandedValueChange(details: TreeExpandedValueChangeDetails) => void
onSelectionChange(details: TreeSelectionChangeDetails) => void

TreeNode ​

collection 的元素。

字段类型必填说明
valuestring是
labelstring展示名,也是连打检索与分支可及名的取字来源;默认回退为 value。
disabledboolean节点禁用:方向键与连打检索跳过它,但它仍可聚焦、仍是导航起点。不向下传导给子节点。
toneTone该节点自身的性质:已失效的写 danger、需要留意的写 warning。不写即与其余节点同档, 也不向下传导给子节点——每一层各自声明。只换字色与悬停 / 按下的面,不改字重与缩进, 也不表达选中或校验;选中的标记与禁用都压过它。彩字不是唯一通道,要紧的差别仍要配图标。
descriptionstring副文本,写入 item-description 部件;未提供时本条不铺该部件。 它是第 2 行的说明,跟着条目走 muted 档,不跟语气;放不下一行的解释才用它, 一句话能说清的写进 label。
childrenTreeNode[]子节点。提供数组即判定为分支,空数组也计入:暂时没有子项的目录仍要报告 aria-expanded。
childrenOrientationOrientation该层子节点的排布方式,由作者在数据上标注。提供后以它为准,vertical 也优先于树级的 leafOrientation;未提供时才回退为 leafOrientation 加子节点全是叶子的结构判据。 标注在哪一层,横向排布就只落在哪一层:菜单授权中标注在按钮的父菜单上,其他目录不受影响, 也不随子节点增减漂移。只影响排布,不改变键盘。

事件 ​

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

事件载荷说明
expanded-value-changeTreeExpandedValueChangeDetails展开集合变化;detail 为 { value: string[] }
selection-changeTreeSelectionChangeDetails选中集合变化;detail 为 { value: string[] }
node-moveTreeNodeMoveDetails节点已移动;detail 为 { value, parent, index },parent 为 null 即根层,index 是在该层的落位(已经过先移除后插入的修正)

插槽 ​

仅列出带载荷的插槽。

Vue 组件插槽载荷说明
XhTreeRootdefaultTreeRootSlotProps

React 适配器 props ​

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

React 组件属性类型必填说明
XhTreeBranchvaluestring是
XhTreeItemvaluestring是
XhTreeRootchildrenSlotChildren<TreeRootSlotProps>

状态 ​

公开状态写入 data-state。

部件取值
branch'open' | 'closed'
branch-control'open' | 'closed'
branch-trigger'open' | 'closed'
branch-indicator'open' | 'closed'
branch-text'open' | 'closed'
branch-content'open' | 'closed'

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

状态:idle

事件:EXPANDED.SET · BRANCH.EXPAND · BRANCH.COLLAPSE · BRANCH.TOGGLE · SELECTION.SET · NODE.SELECT · NODE.FOCUS · TREE.BLUR · NODE_DRAG.START · NODE_DRAG.MOVE · NODE_DRAG.END · NODE_DRAG.CANCEL · NODE.MOVE_BY · PRESS.START · PRESS.END

判据:canPress

connect API ​

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

成员类型说明
collectionreadonly TreeNode[]作者提供的原始树数据。
visibleNodesreadonly TreeVisibleNode[]当前可见行序列(收起分支的子树不在其中)。 方向键、Home/End 与连打检索都在它上面移动,不在原始树上移动。
dropTargetDropTarget | null当前的落点;松手即落在此处。不合法或未落在任何节点上时为 null。
announcementstring读屏播报文本。渲染进 live-region,不进入视觉版面。
expandedValuestring[]
selectionstring[]
focusedValuestring | null焦点锚点;焦点不在树内、或它已被收起而不可见时为 null。
multipleboolean生效的是否为复选。
disabledboolean
isExpanded(value: string) => boolean
isSelected(value: string) => boolean
isIndeterminate(value: string) => boolean级联模式下该分支是否半选(有效叶后代部分勾选);非级联恒为 false。
setExpandedValue(next: string[]) => void
setSelection(next: string[]) => void
expand(value: string) => void
collapse(value: string) => void
select(value: string, options?: { extend?: boolean }) => void选中某个节点。extend 为真时选中锚点到该节点的范围(仅复选、且非级联)。
getRootProps() => T['element']
getLabelProps() => T['element']
getTreeProps() => T['element']
getEmptyProps() => T['element']空态占位:放在 root 中、tree 的兄弟(role=tree 只允许拥有 treeitem 与 group)。 提供 collection 时由连接层按条数收放;节点手写时不写 hidden,是否显示由作者决定。
getLoadingProps() => T['element']在途占位:与空态占位同一位置,两者不同时显示:加载期间显示它,空态让位。 提供 collection 时由连接层按条数收放;节点手写时只按 loading 收放。
getNodeDragTriggerProps(props: TreeNodeProps) => T['element']节点拖动把手。触屏路径唯一的入口,不占 Tab 位。 常驻即可:nodeDraggable 关闭或该节点禁用时它声明 data-disabled、也不再让出滚动, 渲染不会出错。按是否可拖动决定是否渲染,会使 DOM 结构随状态变化。
getLiveRegionProps() => T['element']
getItemProps(props: TreeNodeProps) => T['element']
getItemTextProps(props: TreeNodeProps) => T['element']
getItemDescriptionProps(props: TreeNodeProps) => T['element']
getItemSuffixProps(props: TreeNodeProps) => T['element']
getItemIndicatorProps(props: TreeNodeProps) => T['element']
getBranchProps(props: TreeNodeProps) => T['element']
getBranchControlProps(props: TreeNodeProps) => T['element']
getBranchTriggerProps(props: TreeNodeProps) => T['element']
getBranchIndicatorProps(props: TreeNodeProps) => T['element']
getBranchTextProps(props: TreeNodeProps) => T['element']
getBranchContentProps(props: TreeNodeProps) => T['element']

无障碍 ​

键盘 ​

规格出处:W3C APG

按键生效条件行为
Tab / Shift+Tabfocus outside the tree整棵树只占一个 Tab 位:焦点进入锚点节点,无锚点时先落容器再由它转投
ArrowDownfocus in tree焦点移到下一个可见行(禁用行跳过;loop 默认关,末行不回绕)
ArrowUpfocus in tree焦点移到上一个可见行(禁用行跳过;loop 默认关,首行不回绕)
Homefocus in tree焦点移到首个可见行
Endfocus in tree焦点移到末个可见行(展开着的子树也算行)
ArrowRightfocus on branch(dir=rtl 时改由 ArrowLeft 承担)收起的分支就地展开;已展开则把焦点移到首个子节点;叶子上什么都不做且不吞键
ArrowLeftfocus in tree(dir=rtl 时改由 ArrowRight 承担)展开的分支就地收起;收起的分支与叶子则把焦点移到父节点;根层的行什么都不做
Enter / Spacefocus on node, 节点未禁用选中焦点节点(单选替换、复选切换);焦点在分支上且 expandOnClick 打开时顺带切换展开态
Enter / Spaceheld on node, 树未禁用、未加载且节点未禁用按住期间叶子行或分支行(branch-control)投影 data-pressed,与指针 :active 同一副按压面;抬起或失焦撤下。选中与展开语义照旧由这一次按键承担
*focus in tree展开与焦点行同一父级的全部分支(已展开与禁用的不动);同级没有可展开的分支时不吞这个键
单个可打印字符focus in tree, typeahead 未关连打检索在可见行上按 label 首字母搬焦点,不改选中值,也不展开任何分支
Alt+ArrowUp / Alt+ArrowDownfocus in tree, draggable 开启把焦点节点在同一层的兄弟里往前 / 往后挪一位,按一下就是一次完整提交,不进拖动态;纵轴与文字方向无关,rtl 下两键不对调;已是同层首位 / 末位就不动,也不回绕;落点节点禁用或 allowDrop 不许就不搬。裸方向键仍是走可见行、确认键仍是选中
Alt+ArrowLeft / Alt+ArrowRightfocus in tree, draggable 开启改焦点节点的缩进层级:往里去是认上一个兄弟当父、落进它子层末位,往外去是变成父节点的下一个兄弟;rtl 下两键对调,「往里去」的那个方向恒是缩进。没有上一个兄弟就缩不进去,已在根层就退不出去,两种情形都不动;落点节点禁用或 allowDrop 不许就不搬

ARIA ​

以下属性由 connect 生成。

部件属性值
treearia-busy'true' | undefined
treearia-disabled'true' | 'false'
treearia-labelledbylabel 部件的 id
treearia-multiselectable'true' | 'false'
treearia-orientation'vertical'
treerole'tree'
itemaria-checked'true' | 'mixed' | 'false' | undefined
itemaria-disabled'true' | 'false'
itemaria-levelmeta?.level
itemaria-posinsetmeta?.posInSet
itemaria-selected'true' | 'false'
itemaria-setsizemeta?.setSize
itemrole'treeitem'
item-indicatoraria-hidden'true'
brancharia-checked'true' | 'mixed' | 'false' | undefined
brancharia-disabled'true' | 'false'
brancharia-expanded'true' | 'false'
brancharia-labelmetaOf(node.value)?.label
brancharia-levelmeta?.level
brancharia-posinsetmeta?.posInSet
brancharia-selected'true' | 'false'
brancharia-setsizemeta?.setSize
branchrole'treeitem'
branch-triggeraria-hidden'true'
branch-indicatoraria-hidden'true'
branch-contentrole'group'
node-drag-triggeraria-hidden'true'
live-regionaria-atomic'true'
live-regionaria-live'polite'
live-regionrole'status'

样式参考 ​

皮肤 ​

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

数据属性 ​

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

部件属性值
rootdata-disabled''(条件成立时才出现)
rootdata-loading''(条件成立时才出现)
rootdata-orientation'vertical'
rootdata-variantprops.variant
labeldata-disabled''(条件成立时才出现)
treedata-disabled''(条件成立时才出现)
treedata-orientation'vertical'
itemdata-disabled''(条件成立时才出现)
itemdata-draggable''(条件成立时才出现)
itemdata-dragging''(条件成立时才出现)
itemdata-drop'before' | 'after' | 'inside'
itemdata-highlighted''(条件成立时才出现)
itemdata-indeterminate''(条件成立时才出现)
itemdata-pressed''(条件成立时才出现)
itemdata-selected''(条件成立时才出现)
itemdata-tonemetaOf(value)?.tone
itemdata-xh-collection-context'overlay'
itemdata-xh-collection-item''
itemdata-xh-collection-size'md'
item-indicatordata-disabled''(条件成立时才出现)
item-indicatordata-highlighted''(条件成立时才出现)
item-indicatordata-indeterminate''(条件成立时才出现)
item-indicatordata-selected''(条件成立时才出现)
item-indicatordata-xh-collection-slot'indicator'
item-textdata-disabled''(条件成立时才出现)
item-textdata-highlighted''(条件成立时才出现)
item-textdata-indeterminate''(条件成立时才出现)
item-textdata-selected''(条件成立时才出现)
item-textdata-xh-collection-slot'text'
item-descriptiondata-disabled''(条件成立时才出现)
item-descriptiondata-highlighted''(条件成立时才出现)
item-descriptiondata-indeterminate''(条件成立时才出现)
item-descriptiondata-selected''(条件成立时才出现)
item-descriptiondata-xh-collection-slot'description'
item-suffixdata-disabled''(条件成立时才出现)
item-suffixdata-highlighted''(条件成立时才出现)
item-suffixdata-indeterminate''(条件成立时才出现)
item-suffixdata-selected''(条件成立时才出现)
item-suffixdata-xh-collection-slot'suffix'
branchdata-disabled''(条件成立时才出现)
branchdata-highlighted''(条件成立时才出现)
branchdata-indeterminate''(条件成立时才出现)
branchdata-selected''(条件成立时才出现)
branchdata-state'open' | 'closed'
branch-controldata-disabled''(条件成立时才出现)
branch-controldata-draggable''(条件成立时才出现)
branch-controldata-dragging''(条件成立时才出现)
branch-controldata-drop'before' | 'after' | 'inside'
branch-controldata-highlighted''(条件成立时才出现)
branch-controldata-indeterminate''(条件成立时才出现)
branch-controldata-pressed''(条件成立时才出现)
branch-controldata-selected''(条件成立时才出现)
branch-controldata-state'open' | 'closed'
branch-controldata-tonemetaOf(value)?.tone
branch-controldata-xh-collection-context'overlay'
branch-controldata-xh-collection-item''
branch-controldata-xh-collection-size'md'
branch-triggerdata-disabled''(条件成立时才出现)
branch-triggerdata-highlighted''(条件成立时才出现)
branch-triggerdata-indeterminate''(条件成立时才出现)
branch-triggerdata-selected''(条件成立时才出现)
branch-triggerdata-state'open' | 'closed'
branch-triggerdata-xh-collection-slot'prefix'
branch-indicatordata-disabled''(条件成立时才出现)
branch-indicatordata-highlighted''(条件成立时才出现)
branch-indicatordata-indeterminate''(条件成立时才出现)
branch-indicatordata-selected''(条件成立时才出现)
branch-indicatordata-state'open' | 'closed'
branch-indicatordata-xh-collection-slot'prefix'
branch-textdata-disabled''(条件成立时才出现)
branch-textdata-highlighted''(条件成立时才出现)
branch-textdata-indeterminate''(条件成立时才出现)
branch-textdata-selected''(条件成立时才出现)
branch-textdata-state'open' | 'closed'
branch-textdata-xh-collection-slot'text'
branch-contentdata-disabled''(条件成立时才出现)
branch-contentdata-highlighted''(条件成立时才出现)
branch-contentdata-indeterminate''(条件成立时才出现)
branch-contentdata-orientation'horizontal' | 'vertical'
branch-contentdata-selected''(条件成立时才出现)
branch-contentdata-state'open' | 'closed'
node-drag-triggerdata-disabled''(条件成立时才出现)
node-drag-triggerdata-dragging''(条件成立时才出现)
node-drag-triggerdata-xh-collection-slot'prefix'
emptydata-disabled''(条件成立时才出现)
loadingdata-disabled''(条件成立时才出现)

CSS 变量 ​

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

变量部件CSS 属性状态默认来源说明
--xh-tree-bgroot
tree
backgrounddefault
variant=subtle
--xh-bg-subtle
--xh-bg-surface
tree 的 root、tree 部件 background 覆盖槽。
--xh-tree-bordertreeborderdefault--xh-border-defaulttree 的 tree 部件 border 覆盖槽。
--xh-tree-branch-content-gapbranch-contentgap
row-gap
default
orientation=horizontal
--xh-list-option-gaptree 的 branch-content 部件 gap、row-gap 覆盖槽。
--xh-tree-branch-gapbranchgapdefault--xh-list-option-gaptree 的 branch 部件 gap 覆盖槽。
--xh-tree-branch-indicator-fgbranch-indicator
branch-trigger
colordefault--xh-fg-subtletree 的 branch-indicator、branch-trigger 部件 color 覆盖槽。
--xh-tree-drag-fgnode-drag-triggercolordefault--xh-fg-subtletree 的 node-drag-trigger 部件 color 覆盖槽。
--xh-tree-drag-fg-activenode-drag-triggercolordisabled
dragging
hover
not([data-disabled])
--xh-fg-defaulttree 的 node-drag-trigger 部件 color 覆盖槽。
--xh-tree-drag-fg-disablednode-drag-triggercolordisabled--xh-fg-disabledtree 的 node-drag-trigger 部件 color 覆盖槽。
--xh-tree-drag-grip-longnode-drag-triggerinline-sizeempty--xh-space-2tree 的 node-drag-trigger 部件 inline-size 覆盖槽。
--xh-tree-drag-grip-shortnode-drag-triggerblock-sizeempty--xh-space-1tree 的 node-drag-trigger 部件 block-size 覆盖槽。
--xh-tree-drag-radiusnode-drag-triggerborder-radiusdefault--xh-shape-controltree 的 node-drag-trigger 部件 border-radius 覆盖槽。
--xh-tree-drag-sizenode-drag-triggerblock-size
inline-size
default--xh-control-indicator-sizetree 的 node-drag-trigger 部件 block-size、inline-size 覆盖槽。
--xh-tree-dragging-opacitybranch-control
item
opacitydragging--xh-state-dragging-opacitytree 的 branch-control、item 部件 opacity 覆盖槽。
--xh-tree-drop-fgbranch-control
item
background
box-shadow
disabled
drop=after
drop=before
drop=inside
is([data-drop='before'], [data-drop='after'])
not([data-disabled])
--xh-border-control-focustree 的 branch-control、item 部件 background、box-shadow 覆盖槽。
--xh-tree-drop-inside-bgbranch-control
item
backgrounddisabled
drop=inside
not([data-disabled])
--xh-bg-subtle-hovertree 的 branch-control、item 部件 background 覆盖槽。
--xh-tree-drop-linebranch-control
item
block-size
box-shadow
disabled
drop=after
drop=before
drop=inside
is([data-drop='before'], [data-drop='after'])
not([data-disabled])
--xh-stroke-thicktree 的 branch-control、item 部件 block-size、box-shadow 覆盖槽。
--xh-tree-empty-fgemptycolordefault--xh-fg-subtletree 的 empty 部件 color 覆盖槽。
--xh-tree-empty-font-sizeemptyfont-sizedefault--xh-text-body-sizetree 的 empty 部件 font-size 覆盖槽。
--xh-tree-empty-pxemptypadding-inlinedefault--xh-space-3tree 的 empty 部件 padding-inline 覆盖槽。
--xh-tree-empty-pyemptypadding-blockdefault--xh-space-3tree 的 empty 部件 padding-block 覆盖槽。
--xh-tree-fgtreecolordefault--xh-fg-defaulttree 的 tree 部件 color 覆盖槽。
--xh-tree-gaprootgapdefault--xh-space-2tree 的 root 部件 gap 覆盖槽。
--xh-tree-icon-sizebranch-control
item
root
--xh-icon-sizedefault--xh-_collection-glyph-size
--xh-glyph-size-md
tree 的 branch-control、item、root 部件 --xh-icon-size 覆盖槽。
--xh-tree-indentbranch-contentpadding-inline-startdefault--xh-space-4tree 的 branch-content 部件 padding-inline-start 覆盖槽。
--xh-tree-indicator-sizebranch-control
branch-indicator
branch-trigger
item
item-indicator
--xh-icon-size
inline-size
padding-inline-start
default
orientation=vertical
--xh-control-indicator-sizetree 的 branch-control、branch-indicator、branch-trigger、item、item-indicator 部件 --xh-icon-size、inline-size、padding-inline-start 覆盖槽。
--xh-tree-item-check-fgbranch-control
item
colordisabled
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
state=checked
xh-collection-context=overlay
xh-collection-slot=indicator
--xh-tree-item-indicator-fgtree 的 branch-control、item 部件 color 覆盖槽。
--xh-tree-item-indicator-fgbranch-control
item
colordisabled
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
state=checked
xh-collection-context=overlay
xh-collection-slot=indicator
--xh-fg-brandtree 的 branch-control、item 部件 color 覆盖槽。
--xh-tree-label-fglabelcolordefault--xh-fg-mutedtree 的 label 部件 color 覆盖槽。
--xh-tree-label-font-sizelabelfont-sizedefault--xh-text-label-sizetree 的 label 部件 font-size 覆盖槽。
--xh-tree-label-font-weightlabelfont-weightdefault--xh-text-label-weighttree 的 label 部件 font-weight 覆盖槽。
--xh-tree-leaf-row-gapbranch-contentcolumn-gaporientation=horizontal--xh-space-3tree 的 branch-content 部件 column-gap 覆盖槽。
--xh-tree-loading-fgloadingcolordefault--xh-fg-subtletree 的 loading 部件 color 覆盖槽。
--xh-tree-loading-font-sizeloadingfont-sizedefault--xh-text-body-sizetree 的 loading 部件 font-size 覆盖槽。
--xh-tree-loading-pxloadingpadding-inlinedefault--xh-space-3tree 的 loading 部件 padding-inline 覆盖槽。
--xh-tree-loading-pyloadingpadding-blockdefault--xh-space-3tree 的 loading 部件 padding-block 覆盖槽。
--xh-tree-max-htreemax-block-sizedefault--xh-viewport-h-lgtree 的 tree 部件 max-block-size 覆盖槽。
--xh-tree-pxtreepadding-inlinedefault--xh-space-1tree 的 tree 部件 padding-inline 覆盖槽。
--xh-tree-pytreepadding-blockdefault--xh-space-1tree 的 tree 部件 padding-block 覆盖槽。
--xh-tree-radiustreeborder-radiusdefault--xh-shape-surfacetree 的 tree 部件 border-radius 覆盖槽。
--xh-tree-row-bg-hoverbranch-control
item
background-colordisabled
error
highlighted
hover
is(:focus-visible, [data-highlighted])
is([aria-selected='true'], [data-selected])
not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error])
selected
xh-collection-context=overlay
--xh-bg-subtletree 的 branch-control、item 部件 background-color 覆盖槽。
--xh-tree-row-bg-pressedbranch-control
item
background-colordisabled
error
is(:active, [data-pressed])
is([aria-selected='true'], [data-selected])
not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error])
pressed
selected
xh-collection-context=overlay
--xh-bg-subtle-hovertree 的 branch-control、item 部件 background-color 覆盖槽。
--xh-tree-row-fgbranch-control
item
colordefault
disabled
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=overlay
--xh-fg-defaulttree 的 branch-control、item 部件 color 覆盖槽。
--xh-tree-row-fg-selectedbranch-control
item
colordisabled
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=overlay
--xh-tree-row-fgtree 的 branch-control、item 部件 color 覆盖槽。
--xh-tree-row-font-sizebranch-control
item
font-sizedefault--xh-text-body-sizetree 的 branch-control、item 部件 font-size 覆盖槽。
--xh-tree-row-gapbranch-control
item
gap
padding-inline-start
default
orientation=vertical
--xh-control-gap-mdtree 的 branch-control、item 部件 gap、padding-inline-start 覆盖槽。
--xh-tree-row-leadingbranch-control
item
line-heightdefault--xh-leading-normaltree 的 branch-control、item 部件 line-height 覆盖槽。
--xh-tree-row-pxbranch-control
item
padding-inline
padding-inline-start
default
orientation=vertical
--xh-control-px-mdtree 的 branch-control、item 部件 padding-inline、padding-inline-start 覆盖槽。
--xh-tree-row-pybranch-control
item
padding-blockdefault--xh-list-option-py-mdtree 的 branch-control、item 部件 padding-block 覆盖槽。
--xh-tree-row-radiusbranch-control
item
border-radiusdefault--xh-shape-controltree 的 branch-control、item 部件 border-radius 覆盖槽。
--xh-tree-row-selected-font-weightbranch-control
item
font-weightdisabled
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=overlay
--xh-font-weight-regulartree 的 branch-control、item 部件 font-weight 覆盖槽。
--xh-tree-tree-gaptreegapdefault--xh-list-option-gaptree 的 tree 部件 gap 覆盖槽。

动效 ​

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

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

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

RTL ​

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像;另有按 dir 分支的规则。

Released under The MIT License