使用场景
当需要选择的选项为树形结构时,可以使用树选择器,例如部门层级、学科体系、分类目录等。
代码演示
如何引入
import { TreeSelect } from '@fibrous/semi-ui-react';
基本用法
最简单的用法,默认为单选模式,每一级菜单项均可选择。
代码
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const treeData = [
{
label: '亚洲',
value: 'Asia',
key: '0',
children: [
{
label: '中国',
value: 'China',
key: '0-0',
children: [
{
label: '北京',
value: 'Beijing',
key: '0-0-0',
},
{
label: '上海',
value: 'Shanghai',
key: '0-0-1',
},
],
},
],
},
{
label: '北美洲',
value: 'North America',
key: '1',
},
];
return <TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} placeholder="请选择" />;
}多选
设置 multiple,可以进行多选。多选情况下所有子项都被选择时,自动勾选显示其父项。
通过 leafOnly 属性,可以设置只展示叶子节点,同时 onChange 的回调入参也会只有叶子节点的值。
代码
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const treeData = [
{
label: 'Asia',
value: 'Asia',
key: '0',
children: [
{
label: 'China',
value: 'China',
key: '0-0',
children: [
{
label: 'Beijing',
value: 'Beijing',
key: '0-0-0',
},
{
label: 'Shanghai',
value: 'Shanghai',
key: '0-0-1',
},
{
label: 'Chengdu',
value: 'Chengdu',
key: '0-0-2',
},
],
},
{
label: 'Japan',
value: 'Japan',
key: '0-1',
children: [
{
label: 'Osaka',
value: 'Osaka',
key: '0-1-0',
},
],
},
],
},
{
label: 'North America',
value: 'North America',
key: '1',
children: [
{
label: 'United States',
value: 'United States',
key: '1-0',
},
{
label: 'Canada',
value: 'Canada',
key: '1-1',
},
],
},
];
return (
<div>
<TreeSelect style={{ width: 300 }} multiple dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} placeholder="请选择" />
<br />
<br />
<TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} multiple leafOnly placeholder="只渲染叶子节点" />
<br />
<br />
</div>
);
}限制标签展示数量
在多选的场景中,利用 maxTagCount 可以限制展示的标签数量,超出部分将以 +N 的方式展示。
使用 showRestTagsPopover (>= v2.22.0) 可以设置在超出 maxTagCount 后,hover +N 是否显示 Popover,默认为 false。并且,还可以在 restTagsPopoverProps 属性中配置 Popover。
maxTagCount=2:
maxTagCount=2, showRestTagsPopover:
代码
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const treeData = [
{
label: 'Asia',
value: 'Asia',
key: '0',
children: [
{
label: 'China',
value: 'China',
key: '0-0',
children: [
{
label: 'Beijing',
value: 'Beijing',
key: '0-0-0',
},
{
label: 'Shanghai',
value: 'Shanghai',
key: '0-0-1',
},
{
label: 'Chengdu',
value: 'Chengdu',
key: '0-0-2',
},
],
},
{
label: 'Japan',
value: 'Japan',
key: '0-1',
children: [
{
label: 'Osaka',
value: 'Osaka',
key: '0-1-0',
},
],
},
],
},
{
label: 'North America',
value: 'North America',
key: '1',
children: [
{
label: 'United States',
value: 'United States',
key: '1-0',
},
{
label: 'Canada',
value: 'Canada',
key: '1-1',
},
],
},
];
const textStyle = { margin: '20px 0 10px' };
return (
<div>
<h4 style={textStyle}>maxTagCount=2:</h4>
<TreeSelect multiple maxTagCount={2} style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} placeholder="当选中标签超过两个将折叠" defaultValue={['Beijing', 'Chengdu', 'Canada']} />
<h4 style={textStyle}>maxTagCount=2, showRestTagsPopover:</h4>
<TreeSelect showRestTagsPopover restTagsPopoverProps={{ position: 'top' }} multiple maxTagCount={2} style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} placeholder="hover +N 查看" defaultValue={['Beijing', 'Chengdu', 'Canada']} />
</div>
);
}可搜索的
通过设置 filterTreeNode 属性可支持搜索功能。默认对 label 值进行搜索,可通过 treeNodeFilterProp 更改。
如果只希望展示过滤后的结果,可以设置 showFilteredOnly 。
如果想要获取搜索结果的具体信息,可使用 onSearch 回调函数,函数具体参数见 API 列表。
代码
import { useState } from 'react';
import { TreeSelect, Switch, type TreeNodeData } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const [showFilteredOnly, setShowFilteredOnly] = useState(false);
const treeData = [
{
label: 'Asia',
value: 'Asia',
key: '0',
children: [
{
label: 'China',
value: 'China',
key: '0-0',
children: [
{
label: 'Beijing',
value: 'Beijing',
key: '0-0-0',
},
{
label: 'Shanghai',
value: 'Shanghai',
key: '0-0-1',
},
],
},
{
label: 'Japan',
value: 'Japan',
key: '0-1',
children: [
{
label: 'Osaka',
value: 'Osaka',
key: '0-1-0',
},
],
},
],
},
{
label: 'North America',
value: 'North America',
key: '1',
children: [
{
label: 'United States',
value: 'United States',
key: '1-0',
},
{
label: 'Canada',
value: 'Canada',
key: '1-1',
},
],
},
];
function onSearch(inputValue: string, filteredExpandedKeys: string[], filteredNodes: TreeNodeData[]) {
console.log('onSearch', inputValue, filteredExpandedKeys, filteredNodes);
}
return (
<>
<span id="treeselect-searchable-filtered-only">showFilteredOnly</span>
<Switch aria-labelledby="treeselect-searchable-filtered-only" checked={showFilteredOnly} onChange={setShowFilteredOnly} size="small" />
<br />
<br />
<TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} filterTreeNode showFilteredOnly={showFilteredOnly} placeholder="单选可搜索的" onSearch={onSearch} />
<br />
<br />
<TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} multiple filterTreeNode maxTagCount={2} showFilteredOnly={showFilteredOnly} placeholder="多选可搜索的" searchPlaceholder="请输入关键字开始搜索" onSearch={onSearch} />
<br />
<br />
<TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} multiple filterTreeNode maxTagCount={2} showFilteredOnly={showFilteredOnly} placeholder="搜索框autofocus" searchPlaceholder="autofocus" searchAutoFocus onSearch={onSearch} />
</>
);
}远程搜索
通过设置 remote 属性可启用远程搜索。开启后,输入时不会执行本地过滤,而是仅触发 onSearch 回调,用户可自行处理远程数据获取并更新 treeData。
代码
import { useState, useCallback } from 'react';
import { TreeSelect, type TreeNodeData } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const [value, setValue] = useState<string>();
const [treeData, setTreeData] = useState<TreeNodeData[]>([]);
const handleSearch = useCallback((inputValue: string) => {
if (!inputValue) {
setTreeData([]);
return;
}
setTimeout(() => {
const mockData = [
{ label: `${inputValue} - 结果1`, value: `${inputValue}-1`, key: `${inputValue}-1` },
{ label: `${inputValue} - 结果2`, value: `${inputValue}-2`, key: `${inputValue}-2` },
{ label: `${inputValue} - 结果3`, value: `${inputValue}-3`, key: `${inputValue}-3` },
];
setTreeData(mockData);
}, 500);
}, []);
return <TreeSelect style={{ width: 300 }} placeholder="请输入关键字进行远程搜索" treeData={treeData} filterTreeNode remote value={value} onChange={setValue} onSearch={handleSearch} />;
}搜索框位置
可以使用 searchPosition 来设置搜索框的位置,可选: dropdown(默认)、trigger。
当输入框位于 trigger 时:
- 搜索框占位符由
placeholder控制; showClear=true时,点击输入框的清空按钮,将同时清空 inputValue 和 value。
代码
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const treeData = [
{
label: 'Asia',
value: 'Asia',
key: '0',
children: [
{
label: 'China',
value: 'China',
key: '0-0',
children: [
{
label: 'Beijing',
value: 'Beijing',
key: '0-0-0',
},
{
label: 'Shanghai',
value: 'Shanghai',
key: '0-0-1',
},
],
},
{
label: 'Japan',
value: 'Japan',
key: '0-1',
children: [
{
label: 'Osaka',
value: 'Osaka',
key: '0-1-0',
},
],
},
],
},
{
label: 'North America',
value: 'North America',
key: '1',
children: [
{
label: 'United States',
value: 'United States',
key: '1-0',
},
{
label: 'Canada',
value: 'Canada',
key: '1-1',
},
],
},
];
return (
<>
<TreeSelect searchPosition="trigger" style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} filterTreeNode placeholder="单选" />
<br />
<br />
<TreeSelect searchPosition="trigger" style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} multiple filterTreeNode maxTagCount={2} placeholder="多选" />
</>
);
}Trigger 内多行换行(triggerTagWrap)
当你在 多选 + 搜索框位于 trigger 的场景下,选择了较多项或输入较长文本时,默认 trigger 可能会更倾向于保持单行展示。
开启 triggerTagWrap 后,可以让 trigger 内的已选标签支持自动换行(多行展示)。
代码
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const treeData = [
{
label: 'Asia',
value: 'Asia',
key: '0',
children: [
{
label: 'China',
value: 'China',
key: '0-0',
children: [
{
label: 'Beijing',
value: 'Beijing',
key: '0-0-0',
},
{
label: 'Shanghai',
value: 'Shanghai',
key: '0-0-1',
},
{
label: 'Shenzhen',
value: 'Shenzhen',
key: '0-0-2',
},
{
label: 'Guangzhou',
value: 'Guangzhou',
key: '0-0-3',
},
],
},
{
label: 'Japan',
value: 'Japan',
key: '0-1',
children: [
{
label: 'Osaka',
value: 'Osaka',
key: '0-1-0',
},
],
},
],
},
{
label: 'North America',
value: 'North America',
key: '1',
children: [
{
label: 'United States',
value: 'United States',
key: '1-0',
},
{
label: 'Canada',
value: 'Canada',
key: '1-1',
},
],
},
];
return <TreeSelect searchPosition="trigger" triggerTagWrap style={{ width: 260 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} multiple filterTreeNode placeholder="请选择多个选项或输入长文本" defaultValue={['Beijing', 'Shanghai', 'Shenzhen', 'Guangzhou']} />;
}尺寸大小
可以通过 size 设置尺寸大小,可选: 'small'、'default'、'large'
代码
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const treeData = [
{
label: '亚洲',
value: 'Asia',
key: '0',
children: [
{
label: '中国',
value: 'China',
key: '0-0',
children: [
{
label: '北京',
value: 'Beijing',
key: '0-0-0',
},
{
label: '上海',
value: 'Shanghai',
key: '0-0-1',
},
],
},
],
},
{
label: '北美洲',
value: 'North America',
key: '1',
},
];
return (
<div>
<TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} multiple size="small" placeholder="small" />
<br />
<br />
<TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} multiple size="default" placeholder="default" />
<br />
<br />
<TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} multiple size="large" placeholder="large" />
</div>
);
}默认展开
defaultExpandAll 和 expandAll 均可以设置 TreeSelect 的默认展开/收起状态。二者的区别是,defaultExpandAll 只在初始化时生效,而 expandAll 不仅会在初始化时生效,当数据(treeData)发生动态更新时,expandAll 也仍然生效。
在下面的 demo 中,TreeData 更新后,defaultExpandAll 失效,expandAll 仍然生效。
代码
import { useEffect, useState } from 'react';
import { TreeSelect, type TreeNodeData } from '@fibrous/semi-ui-react';
const treeData: TreeNodeData[] = [
{
label: '亚洲',
value: 'Asia',
key: '0',
children: [
{
label: '中国',
value: 'China',
key: '0-0',
children: [
{
label: '北京',
value: 'Beijing',
key: '0-0-0',
},
{
label: '上海',
value: 'Shanghai',
key: '0-0-1',
},
],
},
],
},
{
label: '北美洲',
value: 'North America',
key: '1',
},
];
export default function TreeSelectDemo() {
const [data, setData] = useState<TreeNodeData[]>([]);
useEffect(() => {
const timer = setTimeout(() => setData(treeData), 500);
return () => clearTimeout(timer);
}, []);
return (
<>
<TreeSelect style={{ width: 300, marginBottom: 20 }} expandAll treeData={data} placeholder="expandAll" />
<TreeSelect style={{ width: 300 }} defaultExpandAll treeData={data} placeholder="defaultExpandAll" />
</>
);
}禁用
代码
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const treeData = [
{
label: '亚洲',
value: 'Asia',
key: '0',
children: [
{
label: '中国',
value: 'China',
key: '0-0',
children: [
{
label: '北京',
value: 'Beijing',
key: '0-0-0',
},
{
label: '上海',
value: 'Shanghai',
key: '0-0-1',
},
],
},
],
},
{
label: '北美洲',
value: 'North America',
key: '1',
},
];
return (
<div>
<TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} disabled placeholder="禁用下拉菜单" />
<br />
<br />
<TreeSelect style={{ width: 300 }} defaultValue="Shanghai" dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} disabled />
<br />
<br />
<TreeSelect style={{ width: 300 }} defaultValue={['Shanghai', 'North America']} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} multiple disabled />
</div>
);
}严格禁用
可以使用 disableStrictly 来开启严格禁用。开启严格禁用后,当节点是 disabled 的时候,则不能通过子级或者父级的关系改变选中状态。
以下面的 demo 为例,节点"中国"开启了严格禁用,因此,当我们改变其父节点"亚洲"的选中状态时,也不会影响到节点"中国"的选中状态。
代码
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const treeData = [
{
label: '亚洲',
value: 'Asia',
key: '0',
children: [
{
label: '中国',
value: 'China',
key: '0-0',
disabled: true,
children: [
{
label: '北京',
value: 'Beijing',
key: '0-0-0',
},
{
label: '上海',
value: 'Shanghai',
key: '0-0-1',
},
],
},
{
label: '日本',
value: 'Japan',
key: '0-1',
},
],
},
{
label: '北美洲',
value: 'North America',
key: '1',
},
];
return (
<div>
<TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} disableStrictly multiple defaultValue={['Shanghai']} />
</div>
);
}受控
传入 value 时即为受控组件,可以配合 onChange 使用。
代码
import { useState } from 'react';
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const [value, setValue] = useState<string | undefined>('Shanghai');
const treeData = [
{
label: '亚洲',
value: 'Asia',
key: '0',
children: [
{
label: '中国',
value: 'China',
key: '0-0',
children: [
{
label: '北京',
value: 'Beijing',
key: '0-0-0',
},
{
label: '上海',
value: 'Shanghai',
key: '0-0-1',
},
],
},
],
},
{
label: '北美洲',
value: 'North America',
key: '1',
},
];
return <TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} value={value} placeholder="请选择" onChange={setValue} />;
}节点选中关系
版本:>= 2.5.0
多选时,可以使用 checkRelation 来设置节点之间选中关系的类型,可选:'related'(默认)、'unRelated'。当选中关系为 'unRelated' 时,意味着节点之间的选中互不影响。
代码
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const treeData = [
{
label: '亚洲',
value: 'Asia',
key: '0',
children: [
{
label: '中国',
value: 'China',
key: '0-0',
children: [
{
label: '北京',
value: 'Beijing',
key: '0-0-0',
},
{
label: '上海',
value: 'Shanghai',
key: '0-0-1',
},
],
},
],
},
{
label: '北美洲',
value: 'North America',
key: '1',
},
];
return <TreeSelect multiple defaultValue={['Asia']} checkRelation="unRelated" style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} />;
}开启搜索的展开受控
传入 expandedKeys 时即为展开受控组件,可以配合 onExpand 使用。当展开受控时,如果开启 filterTreeNode 并进行搜索是不会再自动展开节点的,此时,节点的展开完全由 expandedKeys 来控制。你可以利用 onSearch 的入参 filteredExpandedKeys(version: >= 2.6.0) 来实现展开受控时的搜索展开效果。
代码
import { useState } from 'react';
import { TreeSelect } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
const treeData = [
{
label: '亚洲',
value: 'Asia',
key: '0',
children: [
{
label: '中国',
value: 'China',
key: '0-0',
children: [
{
label: '北京',
value: 'Beijing',
key: '0-0-0',
},
{
label: '上海',
value: 'Shanghai',
key: '0-0-1',
},
],
},
{
label: '日本',
value: 'Japan',
key: '0-1',
},
],
},
{
label: '北美洲',
value: 'North America',
key: '1',
},
];
return (
<TreeSelect
style={{ width: 300 }}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
treeData={treeData}
filterTreeNode
expandedKeys={expandedKeys}
onExpand={(expandedKeys) => {
setExpandedKeys(expandedKeys);
}}
onSearch={(_inputValue, filteredExpandedKeys) => {
setExpandedKeys([...filteredExpandedKeys, ...expandedKeys]);
}}
/>
);
}虚拟化
列表虚拟化,用于大量树节点的情况。开启后,动画效果将被关闭。
virtualize 是一个包含下列值的对象:
- height: 高度值,如果为 string 必须有计算高度才能被渲染出来,即其父节点有 offsetHeight。建议传入数值。
- width: 宽度值,默认 100%
- itemSize: 每行的treeNode的高度,必传
如果带搜索框,建议开启 showFilteredOnly 减少多余节点的渲染。
代码
import { useState } from 'react';
import { TreeSelect, Button, type TreeNodeData } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const [gData, setGData] = useState<TreeNodeData[]>([]);
const [total, setTotal] = useState(0);
function generateData(x = 5, y = 4, z = 3, data: TreeNodeData[] = []) {
// x: nodes per level. y: nodes with children per level. z: depth (0 is one level)
function fill(level: number, preKey: string, nodes: TreeNodeData[]) {
const parents: string[] = [];
for (let i = 0; i < x; i++) {
const key = `${preKey}-${i}`;
nodes.push({ label: `${key}-标签`, key: `${key}-key`, value: `${key}-value` });
if (i < y) {
parents.push(key);
}
}
if (level < 0) {
return;
}
parents.forEach((key, index) => {
const children: TreeNodeData[] = [];
nodes[index].children = children;
fill(level - 1, key, children);
});
}
fill(z, '0', data);
let total = 0;
for (let n = z + 1; n >= 0; n--) {
total += x * y ** n;
}
return { gData: data, total };
}
function onGen() {
const { gData, total } = generateData();
setGData(gData);
setTotal(total);
}
return (
<div style={{ padding: '0 20px' }}>
<Button onClick={onGen}>生成数据: </Button>
<span>共 {total} 个节点</span>
<br />
<br />
{Boolean(gData.length) && (
<TreeSelect
style={{ width: 300 }}
treeData={gData}
filterTreeNode
showFilteredOnly
placeholder="Please select"
dropdownStyle={{
overflow: 'hidden',
}}
virtualize={{
itemSize: 28,
// Dropdown height 300 minus the search box and 8 * 2 padding; a set height fills the rest
height: 236,
}}
/>
)}
</div>
);
}动态更新数据
代码
import { useState } from 'react';
import { TreeSelect, Button, type TreeNodeData } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const [treeData, setTreeData] = useState<TreeNodeData[]>([]);
function add() {
const itemLength = Math.floor(Math.random() * 5) + 1;
const nextTreeData = Array.from({ length: itemLength }, (_v, i) => {
const length = Math.floor(Math.random() * 3);
const children = Array.from({ length }, (_cv, ci) => {
const child = {
key: `${i}-${ci}`,
label: `Leaf-${i}-${ci}`,
value: `${i}-${ci}`,
};
return child;
});
const item = {
key: `${i}`,
label: `Item-${i}`,
value: `${i}`,
children,
};
return item;
});
setTreeData(nextTreeData);
}
return (
<>
<TreeSelect style={{ width: 300 }} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData} placeholder="请选择" />
<br />
<br />
<Button onClick={add}>动态改变数据</Button>
</>
);
}异步加载数据
通过设置 loadData 可以动态加载数据,此时需要在数据中传入 isLeaf 标明叶子节点。
代码
import { useState } from 'react';
import { TreeSelect, type TreeNodeData } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const initialData: TreeNodeData[] = [
{
label: 'Expand to load',
value: '0',
key: '0',
},
{
label: 'Expand to load',
value: '1',
key: '1',
},
{
label: 'Leaf Node',
value: '2',
key: '2',
isLeaf: true,
},
];
const [treeData, setTreeData] = useState(initialData);
function updateTreeData(list: TreeNodeData[], key: string | undefined, children: TreeNodeData[]): TreeNodeData[] {
return list.map((node) => {
if (node.key === key) {
return { ...node, children };
}
if (node.children) {
return { ...node, children: updateTreeData(node.children, key, children) };
}
return node;
});
}
function onLoadData({ key, children }: TreeNodeData) {
return new Promise<void>((resolve) => {
if (children) {
resolve();
return;
}
setTimeout(() => {
setTreeData((origin) =>
updateTreeData(origin, key, [
{
label: 'Child Node',
key: `${key}-0`,
},
{
label: 'Child Node',
key: `${key}-1`,
},
])
);
resolve();
}, 1000);
});
}
return <TreeSelect loadData={onLoadData} treeData={treeData} style={{ width: 300 }} placeholder="请选择" />;
}自定义 Trigger
如果默认的触发器样式满足不了你的需求,可以用 triggerRender 自定义选择框的展示。
triggerRender 入参如下:
interface TriggerRenderProps {
componentProps: TreeSelectProps;// 所有用户传给 TreeSelect 的 props
disabled: boolean; // 是否禁用 TreeSelect
value: TreeNodeData[]; // 已选中的 node 的数据
inputValue: string; // 当前 input 框的输入值
onClear: e => void; // 用于清空值的函数
placeholder: string; // placeholder
/* 删除单个 item 时调用的函数,以 item 的 key 作为入参,
* 从 v2.32.0 版本开始支持
*/
onRemove: key => void;
/**
* 用于在 Input 框值更新时候启动搜索,当你在 triggerRender 自定义的
* Input 组件值更新时,你应该调用该函数,用于向 TreeSelect 内部
* 同步状态, 使用同时需要设置 filterTreeNode 参数非 false,
* searchPosition 为 'trigger'
* 从 v2.32.0 版本开始支持
*/
onSearch: inputValue => void;
}
代码
import { useCallback, useMemo } from 'react';
import { TreeSelect, Tag, TagInput, type TagProps, type TreeSelectTriggerRenderProps } from '@fibrous/semi-ui-react';
export default function TreeSelectDemo() {
const treeData = useMemo(
() => [
{
label: '亚洲',
value: '亚洲',
key: '0',
children: [
{
label: '中国',
value: '中国',
key: '0-0',
children: [
{
label: '北京',
value: '北京',
key: '0-0-0',
},
{
label: '上海',
value: '上海',
key: '0-0-1',
},
],
},
],
},
{
label: '北美洲',
value: '北美洲',
key: '1',
},
],
[]
);
const onValueChange = useCallback((value: unknown) => {
console.log('onChange', value);
}, []);
const renderTrigger = useCallback(({ value, onSearch, onRemove, inputValue }: TreeSelectTriggerRenderProps) => {
const tagInputValue = value.flatMap<string>((item) => item.key ?? []);
const renderTagInMultiple = (key: string) => {
const label = value.find((item) => item.key === key)?.label;
const onCloseTag: TagProps['onClose'] = () => {
onRemove(key);
};
return (
<Tag style={{ marginLeft: 2 }} tagKey={key} key={key} onClose={onCloseTag} closable>
{label}
</Tag>
);
};
return <TagInput inputValue={inputValue} value={tagInputValue} onInputChange={onSearch} renderTagItem={renderTagInMultiple} />;
}, []);
return <TreeSelect triggerRender={renderTrigger} filterTreeNode searchPosition="trigger" multiple treeData={treeData} placeholder="Custom Trigger" onChange={onValueChange} style={{ width: 300 }} />;
}自定义渲染已选项
你可以通过 renderSelectedItem 自定义选择框中已选项标签的渲染结构。
- 单选时
renderSelectedItem(treeNode: TreeNodeData) => content:ReactNode - 多选时
renderSelectedItem(treeNode: TreeNodeData, { index:number, onClose:function }) => { isRenderInTag:bool, content:ReactNode }- isRenderInTag 为 true 时,会自动将 content 包裹在 Tag 中渲染(带有背景色以及关闭按钮)
- isRenderInTag 为 false 时,将直接渲染返回的 content
单选
多选+ isRenderInTag=true
多选 + isRenderInTag=false
代码
import { TreeSelect, Tag, type TreeNodeData } from '@fibrous/semi-ui-react';
const treeData = [
{
label: '亚洲',
value: 'Asia',
key: '0',
children: [
{
label: '中国',
value: 'China',
key: '0-0',
children: [
{
label: '北京',
value: 'Beijing',
key: '0-0-0',
},
{
label: '上海',
value: 'Shanghai',
key: '0-0-1',
},
],
},
],
},
{
label: '北美洲',
value: 'North America',
key: '1',
},
{
label: '南美洲',
value: 'South America',
key: '2',
},
{
label: '南极洲',
value: 'Antarctica',
key: '3',
},
];
export default function TreeSelectDemo() {
return (
<>
<h4>单选</h4>
<TreeSelect style={{ width: 300 }} treeData={treeData} renderSelectedItem={(item: TreeNodeData) => item.label} />
<h4>多选+ isRenderInTag=true</h4>
<TreeSelect style={{ width: 300 }} treeData={treeData} multiple renderSelectedItem={(item) => ({ content: item.label, isRenderInTag: true })} />
<h4>多选 + isRenderInTag=false</h4>
<TreeSelect
style={{ width: 300 }}
treeData={treeData}
multiple
maxTagCount={2}
renderSelectedItem={(item, { index, onClose }) => {
return {
content: (
<Tag key={index} color="white" closable onClose={onClose}>
{item.value}
</Tag>
),
isRenderInTag: false,
};
}}
/>
</>
);
}API参考
TreeSelect
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| aria-label | combobox 的可访问名称:搜索框在选择框内时是搜索框,否则是触发器。 | string | - |
| arrowIcon | 自定义右侧下拉箭头图标,传 null 不显示箭头。showClear 开启且有已选值时,hover 优先显示清除图标。 | React.ReactNode | Type<IconChevronDown /> |
| autoAdjustOverflow | 弹出层被遮挡时是否自动调整方向。 | boolean | true |
| autoExpandParent | 是否自动展开父节点。 | boolean | false |
| autoMergeValue | 是否合并值:开启后选中父节点时,值中不包含其后代节点。仅在 leafOnly 为 false 时生效。 | boolean | true |
| borderless | 是否使用无边框样式。 | boolean | false |
| checkRelation | 多选时节点选中状态的关系,可选 related、unRelated。unRelated 时节点之间的选中互不影响。 | CheckRelation | "related" |
| className | 选择框的类名,落在触发器元素上。 | string | - |
| clearIcon | 自定义清除按钮的图标,showClear 为 true 时有效。 | React.ReactNode | - |
| clickToHide | 选中后是否自动关闭下拉面板,仅在单选时生效。 | boolean | true |
| clickTriggerToHide | 面板打开时,点击触发器后是否关闭面板。 | boolean | true |
| defaultExpandAll | 初始化时是否展开全部节点。数据(treeData)变化后此属性不再生效,需要时使用 expandAll。 | boolean | - |
| defaultExpandedKeys | 默认展开的节点 key,展开后显示直接子节点。 | string[] | - |
| defaultOpen | 是否默认打开下拉面板。 | boolean | false |
| defaultValue | 默认选中的值,只在挂载时读取;多选时为数组。 | TypeModeValue<T, Multiple> | - |
| disabled | 是否禁用。 | boolean | - |
| disableStrictly | 严格禁用:节点禁用时,它的选中状态不会因为父或子节点的变化而改变。 | boolean | false |
| dropdownClassName | 下拉面板的类名。 | string | - |
| dropdownMatchSelectWidth | 下拉面板的最小宽度是否与选择框相同。 | boolean | true |
| dropdownStyle | 下拉面板的样式。 | React.CSSProperties | - |
| emptyContent | 无数据或搜索无结果时的空状态内容,未设置时显示语言包中的文案;传 null 时不显示。 | ReactNode | - |
| expandAction | 节点的展开方式,可选 false(只有点击展开图标才展开)、click、doubleClick。 | ExpandAction | false |
| expandAll | 是否默认展开全部节点。数据(treeData)变化后仍受此属性影响。 | boolean | false |
| expandedKeys | (受控)展开的节点 key,展开后显示直接子节点。 | string[] | - |
| expandIcon | 自定义展开图标,可传节点或函数。函数入参为 className、onClick 与 expanded,由函数渲染展开按钮并把它们挂到元素上。 | TypeReact.ReactNode | ((props: { onClick: (e: React.MouseEvent) => void; className: string; expanded: boolean }) => React.ReactNode) | - |
| filterTreeNode | 是否可搜索,也可以传入函数自定义搜索逻辑,函数的第三个参数为节点数据 data。 | Typeboolean | ((inputValue: string, treeNodeString: string, data?: TreeNodeData) => boolean) | false |
| insetLabel | 选择框内的标签,同时作为下拉树的名称。 | React.ReactNode | - |
| insetLabelId | insetLabel 外层元素的 id,供 aria-labelledby 引用。 | string | - |
| keyMaps | 自定义节点中 key、label、value、disabled、children、isLeaf 与 icon 字段的名称。如果自定义了 label 的字段名并开启搜索,需要把 treeNodeFilterProp 设为 treeData 中的某个字段,或通过 filterTreeNode 传入自定义搜索函数。 | KeyMapProps | - |
| labelEllipsis | 标签溢出时是否省略。未设置时,虚拟化模式下为 true,否则为 false。 | boolean | - |
| leafOnly | 多选时是否只展示叶子节点的标签,onChange 的入参也只包含叶子节点的值。 | boolean | - |
| loadData | 异步加载子节点,返回 Promise。需要在 treeData 中用 isLeaf 标明叶子节点。 | Type(data: BasicTreeNodeData) => Promise<void> | - |
| loadedKeys | (受控)已加载完成的节点 key,与 loadData 配合使用。 | string[] | - |
| maxTagCount | 最多显示的标签数量,超出部分以 +N 的形式展示。 | number | - |
| motion | 下拉面板打开和关闭时是否带动画。 | boolean | true |
| motionExpand | 节点展开和收起时是否带动画。 | boolean | true |
| multiple | 是否多选。 | Multiple | false |
| onBlur | 失去焦点时的回调,每次 onFocus 后只触发一次。焦点离开触发器与下拉面板时入参为原生 FocusEvent,点击外部时为原生 MouseEvent,选中节点并关闭下拉面板时为该次点击或按键的事件。 | Type(e: React.MouseEvent | React.KeyboardEvent | globalThis.MouseEvent | globalThis.FocusEvent) => void | - |
| onChange | 选中值变化时的回调,入参为节点的 value(多选时为数组)、节点数据与事件。关闭标签时事件为 null,键盘选中时为 KeyboardEvent,清空单选时值为 undefined。onChangeWithObject 为 true 时,入参变为节点数据与事件。 | Type(...args: OnChangeArgs<T, Multiple, WithObject>) => void | - |
| onChangeWithObject | onChange 的入参是否为节点的全部属性。为 true 时,onChange 的入参变为 (node, e)。 | WithObject | false |
| onClear | 点击清除按钮时的回调。 | Type(e: React.MouseEvent) => void | - |
| onExpand | 展开或收起节点时的回调,入参为展开的 key 数组与 { expanded, node }。 | Type(expandedKeys: string[], expandedOtherProps: ExpandedOtherProps) => void | - |
| onFocus | 焦点从外部进入触发器(含搜索框、清除按钮)或下拉面板时的回调,入参为原生 FocusEvent;在它们之间移动焦点不会再次触发。选中后关闭下拉面板,又通过点击或按键重新打开时也会触发,入参为该次点击或按键的事件;searchAutoFocus 挂载时聚焦的入参为 null。 | Type(e: React.MouseEvent | React.KeyboardEvent | globalThis.FocusEvent | null) => void | - |
| onLoad | 节点加载完毕时的回调,入参为已加载的 key 集合与节点数据。 | Type(keys: Set<string>, data: BasicTreeNodeData) => void | - |
| onSearch | 搜索值变化时的回调。入参为搜索值、filteredExpandedKeys(因搜索或 value 而展开的节点 key,展开受控时可用于实现搜索展开)与 filteredNodes(命中搜索的节点)。 | Type(searchValue: string, filteredExpandedKeys: string[], filteredNodes: BasicTreeNodeData[]) => void | - |
| onSelect | 节点被选中或取消选中时的回调,入参为节点的 key、是否选中与节点数据。 | Type(selectedKey: string, selected: boolean, selectedNode: TreeNodeData) => void | - |
| onVisibleChange | 下拉面板显示或隐藏时的回调,入参为是否可见。 | Type(isVisible: boolean) => void | - |
| optionListStyle | 选项列表的样式。 | React.CSSProperties | - |
| outerBottomSlot | 渲染在下拉面板底部的自定义内容,与选项列表同级。 | React.ReactNode | - |
| outerTopSlot | 渲染在下拉面板顶部的自定义内容,与选项列表同级。开启 filterTreeNode 时它会替代搜索框,需要自定义搜索时可以通过 ref 的 search 方法实现。 | React.ReactNode | - |
| placeholder | 输入框的占位文本。 | string | - |
| position | 下拉面板的位置,可选值参考 Tooltip 的 position,默认 bottomLeft(RTL 下为 bottomRight)。 | PopoverProps['position'] | - |
| prefix | 选择框前面的内容。 | React.ReactNode | - |
| preventScroll | 组件内部调用 focus 时是否阻止浏览器滚动文档以显示新聚焦的元素,不作用于用户传入的元素。 | boolean | - |
| ref | 组件句柄,带有 search 与 close 方法,类型为 TreeSelectHandle,不是 DOM 元素。 | TypeReact.Ref<TreeSelectHandle> | - |
| remote | 是否开启远程搜索。开启后输入时跳过本地过滤,仅触发 onSearch 回调,用户可自行处理远程数据获取并更新 treeData。 | boolean | false |
| renderFullLabel | 自定义整行的渲染。返回值外层会包一层带 role="treeitem" 与状态属性的行元素,用法与 Tree 的 renderFullLabel 相同。 | Type(renderFullLabelProps: RenderFullLabelProps) => ReactNode | - |
| renderLabel | 自定义节点文本的渲染,入参为原文本、节点数据与搜索词。 | Type(label?: ReactNode, treeNode?: TreeNodeData, searchWord?: string) => ReactNode | - |
| renderSelectedItem | 自定义选择框中已选项的渲染。单选时返回内容;多选时返回 { content, isRenderInTag },isRenderInTag 为 true 时内容自动包进带背景色与关闭按钮的 Tag 中。 | TypeByMultiple<Multiple, RenderSelectedItemInSingle, RenderSelectedItemInMultiple> | - |
| restTagsPopoverProps | 超出 maxTagCount 后折叠标签的 Popover 配置,见 Popover。 | PopoverProps | {} |
| searchAutoFocus | 搜索框挂载后是否自动聚焦。 | boolean | false |
| searchPlaceholder | 下拉面板中搜索框的占位文本。 | string | - |
| searchPosition | 搜索框的位置,可选 dropdown、trigger。 | 'dropdown' | 'trigger' | "dropdown" |
| searchRender | 自定义搜索框;传 false 时不渲染搜索框。入参为输入框的属性,包括 ref 与 ARIA 属性,需要全部写到输入框上。 | Typeboolean | ((inputProps: InputProps & { ref: (el: SearchInputElement | null) => void }) => React.ReactNode) | - |
| showClear | 值不为空时,触发器是否显示清除按钮。 | boolean | false |
| showFilteredOnly | 搜索时是否只展示过滤后的结果。 | boolean | - |
| showLine | 选项面板中的节点是否显示连接线。 | boolean | - |
| showRestTagsPopover | 标签数量超过 maxTagCount 后,hover 到 +N 时是否用 Popover 展示其余标签。 | boolean | false |
| showSearchClear | 下拉面板中的搜索框是否支持清空。 | boolean | true |
| size | 输入框的尺寸,可选 large、small、default。 | Size | "default" |
| stopPropagation | 是否阻止下拉面板上的点击事件冒泡。 | boolean | string | true |
| style | 选择框(触发器)的内联样式。 | React.CSSProperties | - |
| suffix | 选择框后面的内容。 | React.ReactNode | - |
| treeData | 节点数据,key 在整棵树内唯一。只有传入新数组才会更新,原地修改数组或节点不会生效。 | TreeNodeData[] | - |
| treeNodeFilterProp | 搜索时匹配的 TreeNodeData 属性。 | string | "label" |
| treeNodeLabelProp | 显示文本所用的 TreeNodeData 属性。 | string | "label" |
| triggerRender | 自定义触发器,入参为 TriggerRenderProps,返回值替换整个触发器。 | Type(props: TriggerRenderProps) => React.ReactNode | - |
| triggerTagWrap | 已选标签在触发器内是否允许换行。仅在 multiple、开启搜索且 searchPosition 为 trigger 时生效。 | boolean | false |
| validateStatus | 校验状态,可选 warning、error、default,只影响组件的背景色。 | ValidateStatus | - |
| value | (受控)当前选中的值,传入后即为受控组件,可配合 onChange 使用;多选时为数组。 | TypeModeValue<T, Multiple> | - |
| virtualize | 虚拟列表配置,对象包含 itemSize(必传,每行的高度)、height(下拉高度,建议传数值)与 width。虚拟化时动画关闭。 | Virtualize | - |
Methods
| 方法 | 说明 | 类型 |
|---|---|---|
| close | 关闭下拉面板。 | Type() => void |
| search | 按输入了该值来搜索,先打开下拉面板,需要同时设置 filterTreeNode。在外部自定义搜索框时,可在其值变化时调用。 | Type(value: string) => void |
aria-label、aria-labelledby、aria-describedby、aria-errormessage、aria-invalid 与 aria-required 落在当前的 combobox 上:不可搜索时是触发器,搜索框在触发器内时是搜索框的输入框。其他原生属性(如 id、data-*、onClick)落在触发器元素上。
TreeNodeData
不同
TreeNodeData的 key 值要求必填且唯一。label允许重复。value 值非必填。此时 onChange, value, defaultValue 及 onChangeWithObject 中所取的 value 属性值将改为 key 值。为了保证行为的符合预期,treeData 中的 value 值或者全部不填写,或者全部填写且唯一,不建议混写。
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| value | 属性值 | string|number | - |
| label | 展示的文本 | string|ReactNode | - |
| icon | 自定义图标 | ReactNode | - |
| disabled | 是否禁用,多选状态下支持 | boolean | false |
| key | required且要求唯一 | string | - |
| isLeaf | 是否为叶子节点 | boolean | - |
Methods
绑定在组件实例上的方法,可以通过 ref 调用实现某些特殊交互,方法的说明见 TreeSelect 的 API 参考。
Accessibility
ARIA
- 按 ARIA 1.2 的 combobox 写法,任一时刻只有一个元素是 combobox。它的名称按优先级取:
aria-labelledby、aria-label、实际渲染出的 insetLabel(Vue 为#insetLabel,未传insetLabelId时组件生成 id;有 prefix 时 insetLabel 不渲染,也不作名称来源),都没有时取语言包中的名称:- 不可搜索或
searchPosition="dropdown"时,触发器是 select-only combobox;下拉内的搜索框保持文本框角色,带aria-controls、aria-autocomplete、aria-activedescendant searchPosition="trigger"时,搜索框是 combobox 和唯一的 Tab 停靠点,带aria-autocomplete="list",触发器不再有角色。单选时搜索框在输入前为空,已选文本以aria-describedby关联为它的描述。点击触发器任意位置会把焦点交给搜索框;
- 不可搜索或
- TreeSelect 允许用户设置
aria-describedby、aria-errormessage、aria-invalid、aria-labelledby、aria-required,另外,Form 会为 Form.TreeSelect 自动设置这些属性; - 下拉中
role="tree"的列表与 combobox 使用同一个名称来源:同一组aria-labelledby、同一个aria-label或同一个 insetLabel;都没有时与 combobox 一样取语言包中的名称;
- 下拉中的节点与 Tree 相同:
role="treeitem",带aria-level、aria-setsize、aria-posinset、aria-disabled,可展开的节点带aria-expanded;单选时用aria-selected,多选时用aria-checked(半选为mixed);
- 节点前的展开箭头和多选复选框只是状态的图示,对读屏软件隐藏,也不接收焦点。
键盘交互
TreeSelect 按 WAI-ARIA Combobox 处理键盘,弹出层是一棵树:焦点始终留在触发器或搜索框上,aria-activedescendant 指向当前节点,当前节点显示焦点环。下拉刚打开时没有当前节点。
- 下拉关闭时:
ArrowDown、ArrowUp、Enter、Space打开下拉;Home、End打开下拉并移到第一个、最后一个可见节点 ArrowDown、ArrowUp:移到下一个、上一个可见节点,第一次按ArrowDown移到第一个节点;Home、End:移到第一个、最后一个可见节点ArrowRight:展开收起的节点;节点已展开时移到它的第一个子节点(RTL 下与ArrowLeft互换)ArrowLeft:收起展开的节点;否则移到父节点Enter、Space:选中当前节点,多选时勾选或取消勾选;禁用节点不响应- 输入字符:下拉打开时,从当前节点往后,移到第一个以输入内容开头的可见节点;快速连续输入的字符合成一个搜索词。下拉关闭时不响应
Esc:关闭下拉
焦点在搜索框里时,只有 ArrowDown、ArrowUp、Enter 用于移动和选择,其余按键(含字符、Space、Home、End、ArrowLeft、ArrowRight)用于编辑文字。
自定义 searchRender 的参数里带有这组 ARIA 属性(aria-activedescendant、aria-controls、aria-autocomplete、名称;在触发器内时为整组 combobox 属性,含 role、aria-expanded),请把它们写在输入框上,否则读屏软件不会读出当前节点。参数里的 ref 也要写到输入框(Semi Input、原生 input 或 textarea)上,点击触发器内的已选文本时才能把焦点交给它。
showClear 开启、有已选值或搜索文本且未禁用时,触发器内渲染清除按钮。它是原生 button,名称为语言包中的「清空已选值」,在 hover、下拉打开或焦点位于 TreeSelect 内时显示。从触发器或搜索框按 Tab 移到清除按钮,Enter 或 Space 清空,效果与鼠标点击相同,清空后焦点回到触发器或搜索框。多选时也可在搜索框中用 Backspace 删除标签。
示例:
<TreeSelect
/* 其他属性 */
aria-label='example treeSelect'
/>
设计变量
| Sass 变量 | 值 | 用法 |
|---|---|---|
| $color-treeSelect_default-bg-default | var(--semi-color-fill-0) | 树选择器选择框背景颜色 - 默认 |
| $color-treeSelect_default-bg-hover | var(--semi-color-fill-1) | 树选择器选择框背景颜色 - 悬停 |
| $color-treeSelect_default-bg-active | var(--semi-color-fill-2) | 树选择器选择框背景颜色 - 按下 |
| $color-treeSelect_default-bg-focus | var(--semi-color-fill-0) | 树选择器选择框背景颜色 - 选中 |
| $color-treeSelect_default-border-default | transparent | 树选择器选择框描边颜色 - 默认 |
| $color-treeSelect_selection-text-default | var(--semi-color-text-0) | 树选择器选择框回填内容文本颜色 - 默认 |
| $color-treeSelect_default-icon-default | var(--semi-color-text-2) | 树选择器选择框图标颜色 - 默认 |
| $color-treeSelect_default-icon-hover | var(--semi-color-primary-hover) | 树选择器选择框清空按钮颜色 - 悬停 |
| $color-treeSelect_default-icon-active | var(--semi-color-primary-active) | 树选择器选择框清空按钮颜色 - 按下 |
| $color-treeSelect_default-border-hover | transparent | 树选择器选择框描边颜色 - 悬浮 |
| $color-treeSelect_default-border-focus | var(--semi-color-focus-border) | 树选择器选择框描边颜色 - 选中 |
| $color-treeSelect_search-border-default | var(--semi-color-fill-0) | 树选择器菜单搜索框描边颜色 - 默认 |
| $color-treeSelect_tag_disabled-bg-default | transparent | 禁用树选择器菜单标签背景颜色 |
| $color-treeSelect_input_disabled-bg-default | var(--semi-color-disabled-fill) | 禁用树选择器选择框背景颜色 |
| $color-treeSelect_input_disabled-text-default | var(--semi-color-disabled-text) | 禁用树选择器选择框文本颜色 |
| $color-treeSelect_input_disabled-bg-hover | var(--semi-color-disabled-fill) | 禁用树选择器选择框背景颜色 - 悬浮 |
| $color-treeSelect_input_placeholder-text-default | var(--semi-color-text-2) | 树选择器选择框占位文本颜色 |
| $color-treeSelect_warning-bg-default | var(--semi-color-warning-light-default) | 警告树选择器选择框背景颜色 - 默认 |
| $color-treeSelect_warning-border-default | var(--semi-color-warning-light-default) | 警告树选择器选择框描边颜色 - 默认 |
| $color-treeSelect_warning-bg-hover | var(--semi-color-warning-light-hover) | 警告树选择器选择框背景颜色 - 悬浮 |
| $color-treeSelect_warning-border-hover | var(--semi-color-warning-light-hover) | 警告树选择器选择框描边颜色 - 悬浮 |
| $color-treeSelect_warning-bg-focus | var(--semi-color-warning-light-default) | 警告树选择器选择框背景颜色 - 选中 |
| $color-treeSelect_warning-border-focus | var(--semi-color-warning) | 警告树选择器选择框描边颜色 - 选中 |
| $color-treeSelect_warning-bg-active | var(--semi-color-warning-light-active) | 警告树选择器选择框背景颜色 - 激活 |
| $color-treeSelect_warning-border-active | var(--semi-color-warning-light-active) | 警告树选择器选择框描边颜色 - 激活 |
| $color-treeSelect_danger-bg-default | var(--semi-color-danger-light-default) | 错误树选择器选择框背景颜色 - 默认 |
| $color-treeSelect_danger-border-default | var(--semi-color-danger-light-default) | 错误树选择器选择框描边颜色 - 默认 |
| $color-treeSelect_danger-bg-hover | var(--semi-color-danger-light-hover) | 错误树选择器选择框背景颜色 - 悬浮 |
| $color-treeSelect_danger-border-hover | var(--semi-color-danger-light-hover) | 错误树选择器选择框描边颜色 - 悬浮 |
| $color-treeSelect_danger-bg-focus | var(--semi-color-danger-light-default) | 错误树选择器选择框背景颜色 - 选中 |
| $color-treeSelect_danger-border-focus | var(--semi-color-danger) | 错误树选择器选择框描边颜色 - 选中 |
| $color-treeSelect_danger-bg-active | var(--semi-color-danger-light-active) | 错误树选择器选择框背景颜色 - 激活 |
| $color-treeSelect_danger-border-active | var(--semi-color-danger-light-active) | 错误树选择器选择框描边颜色 - 激活 |
| $radius-treeSelect | var(--semi-border-radius-small) | 树选择器圆角 |
| $width-treeSelect-border | 1px | 树选择器描边宽度 |
| $width-treeSelect_search_wrapper-border | 1px | 树选择器搜索框描边宽度 |
| $width-treeSelect_hover-border | $border-thickness-control-focus | 树选择器选择框描边宽度 - 悬浮 |
| $width-treeSelect_focus-border | $width-treeSelect_hover-border | 树选择器选择框描边宽度 - 选中 |
| $width-treeSelect_default | 80px | 树选择器最小宽度 |
| $height-treeSelect_default | $height-control-default | 树选择器选择器高度 - 默认 |
| $font-treeSelect_default-lineHeight | $height-treeSelect_default | 树选择器选择器文本行高 |
| $font-treeSelect_default-fontWeight | $font-weight-regular | 树选择器选择器文本字重 |
| $height-treeSelect_small | $height-control-small | 小尺寸树选择器选择器高度 |
| $font-treeSelect_small-lineHeight | $height-treeSelect_small | 小尺寸树选择器选择器文本行高 |
| $height-treeSelect_large | $height-control-large | 大尺寸树选择器选择器文本行高 |
| $font-treeSelect_large-lineHeight | $height-treeSelect_large | 大尺寸树选择器选择器文本行高 |
| $font-treeSelect_prefix_suffix_fontWeight | $font-weight-bold | 树选择器前缀后缀文本字重 |
| $spacing-treeSelect_selection_tagInput_wrapper-paddingX | $spacing-extra-tight | 树选择器多选标签容器水平内边距 |
| $spacing-treeSelect_selection_tagInput_empty-marginLeft | $spacing-extra-tight | 树选择器多选标签容器为空时左侧外边距 |
| $spacing-treeSelect_selection_tagInput_notEmpty-marginLeft | -$spacing-extra-tight | 树选择器多选标签容器不为空时左侧外边距 |
| $spacing-treeSelect_selection-paddingLeft | $spacing-base-tight | 树选择器单选左侧内边距 |
| $spacing-treeSelect_tag-marginX | $spacing-super-tight | 树选择器多选标签水平外边距 |
| $spacing-treeSelect_tag-marginY | 1px | 树选择器多选标签垂直外边距 |
| $spacing-treeSelect_selection_multiple-paddingLeft | 4px | 树选择器多选标签左侧内边距 |
| $spacing-treeSelect_placeholder_multiple-paddingLeft | 8px | 树选择器多选占位文本左侧外边距 |
| $spacing-treeSelect_prefix_text-marginY | 0px | 树选择器前缀文本垂直外边距 |
| $spacing-treeSelect_prefix_text-marginX | $spacing-base-tight | 树选择器前缀文本水平外边距 |
| $spacing-treeSelect_prefix_icon-marginY | 0px | 树选择器前缀图标垂直外边距 |
| $spacing-treeSelect_prefix_icon-marginX | $spacing-tight | 树选择器前缀图标水平外边距 |
| $spacing-treeSelect_selection_withSuffix-paddingRight | 0px | 树选择器有后缀时内容右侧内边距 |
| $color-treeSelect_selection_TriggerSearchItem_disabled-text-default | var(--semi-color-disabled-text) | 带搜索的树选择器触发器占位文本默认颜色 |
| $color-treeSelect_inputTrigger-border-default | none | 带搜索的树选择器触发器描边颜色 |
| $color-treeSelect_inputTrigger-bg-default | transparent | 带搜索的树选择器触发器背景颜色 |
| $color-treeSelect_prefix_suffix_text-default | var(--semi-color-text-2) | 带搜索的树选择器前后缀文本颜色 |
| $width-treeSelect_arrow | 32px | 树选择器展开箭头宽度 |
| $width-treeSelect_option | 230px | 树选择器菜单项宽度 |
| $height-treeSelect_popover | 300px | 树选择器菜单高度 |
| $height-treeSelect_selection_tagInput_wrapper_small | 22px | 树选择器多选搜索,搜索框在选择框时选择框最小高度 - 小尺寸 |
| $height-treeSelect_selection_tagInput_wrapper_default | 30px | 树选择器多选搜索,搜索框在选择框时选择框最小高度 - 默认尺寸 |
| $height-treeSelect_selection_tagInput_wrapper_large | 38px | 树选择器多选搜索,搜索框在选择框时选择框最小高度 - 大尺寸 |