TreeSelect
Sélection arborescente déroulante pour données hiérarchiques.
Importation
Section intitulée « Importation »import { TreeSelect } from 'asterui'import type { TreeDataNode } from 'asterui'Exemples
Section intitulée « Exemples »TreeSelect basique
Sélectionnez une seule valeur à partir d'une structure arborescente.
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const basicTreeData: TreeDataNode[] = [
{
key: 'parent',
title: 'Parent Node',
children: [
{
key: 'child1',
title: 'Child Node 1',
children: [
{ key: 'leaf1', title: 'Leaf 1' },
{ key: 'leaf2', title: 'Leaf 2' },
],
},
{ key: 'child2', title: 'Child Node 2' },
],
},
]
const [value, setValue] = useState<string | undefined>()
return (
<TreeSelect
treeData={basicTreeData}
value={value}
onChange={(val) => setValue(val as string)}
placeholder="Select an item"
/>
)
}
export default App Sélection multiple
Sélectionnez plusieurs valeurs de l'arbre.
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const categoriesData: TreeDataNode[] = [
{
key: 'electronics',
title: 'Electronics',
children: [
{
key: 'phones',
title: 'Phones',
children: [
{ key: 'iphone', title: 'iPhone' },
{ key: 'samsung', title: 'Samsung' },
{ key: 'pixel', title: 'Pixel' },
],
},
{
key: 'laptops',
title: 'Laptops',
children: [
{ key: 'macbook', title: 'MacBook' },
{ key: 'thinkpad', title: 'ThinkPad' },
],
},
],
},
{
key: 'clothing',
title: 'Clothing',
children: [
{ key: 'shirts', title: 'Shirts' },
{ key: 'pants', title: 'Pants' },
{ key: 'shoes', title: 'Shoes' },
],
},
]
const [value, setValue] = useState<string[]>([])
return (
<TreeSelect
treeData={categoriesData}
value={value}
onChange={(val) => setValue(val as string[])}
placeholder="Select items"
multiple
/>
)
}
export default App Cochable
Utilisez des cases à cocher pour la sélection avec association parent-enfant.
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const categoriesData: TreeDataNode[] = [
{
key: 'electronics',
title: 'Electronics',
children: [
{
key: 'phones',
title: 'Phones',
children: [
{ key: 'iphone', title: 'iPhone' },
{ key: 'samsung', title: 'Samsung' },
{ key: 'pixel', title: 'Pixel' },
],
},
{
key: 'laptops',
title: 'Laptops',
children: [
{ key: 'macbook', title: 'MacBook' },
{ key: 'thinkpad', title: 'ThinkPad' },
],
},
],
},
{
key: 'clothing',
title: 'Clothing',
children: [
{ key: 'shirts', title: 'Shirts' },
{ key: 'pants', title: 'Pants' },
{ key: 'shoes', title: 'Shoes' },
],
},
]
const [value, setValue] = useState<string[]>([])
return (
<TreeSelect
treeData={categoriesData}
value={value}
onChange={(val) => setValue(val as string[])}
placeholder="Check items"
treeCheckable
/>
)
}
export default App Recherchable
Filtrez les nœuds de l'arbre avec la recherche.
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const categoriesData: TreeDataNode[] = [
{
key: 'electronics',
title: 'Electronics',
children: [
{
key: 'phones',
title: 'Phones',
children: [
{ key: 'iphone', title: 'iPhone' },
{ key: 'samsung', title: 'Samsung' },
{ key: 'pixel', title: 'Pixel' },
],
},
{
key: 'laptops',
title: 'Laptops',
children: [
{ key: 'macbook', title: 'MacBook' },
{ key: 'thinkpad', title: 'ThinkPad' },
],
},
],
},
{
key: 'clothing',
title: 'Clothing',
children: [
{ key: 'shirts', title: 'Shirts' },
{ key: 'pants', title: 'Pants' },
{ key: 'shoes', title: 'Shoes' },
],
},
]
const [value, setValue] = useState<string | undefined>()
return (
<TreeSelect
treeData={categoriesData}
value={value}
onChange={(val) => setValue(val as string)}
placeholder="Search and select"
showSearch
/>
)
}
export default App Tailles
TreeSelect est disponible en différentes tailles.
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
function App() {
const simpleData: TreeDataNode[] = [
{ key: 'opt1', title: 'Option 1' },
{ key: 'opt2', title: 'Option 2' },
{ key: 'opt3', title: 'Option 3' },
]
return (
<div className="flex flex-col gap-2">
<TreeSelect treeData={simpleData} size="xs" placeholder="Extra small" />
<TreeSelect treeData={simpleData} size="sm" placeholder="Small" />
<TreeSelect treeData={simpleData} size="md" placeholder="Medium" />
<TreeSelect treeData={simpleData} size="lg" placeholder="Large" />
<TreeSelect treeData={simpleData} size="xl" placeholder="Extra large" />
</div>
)
}
export default App État de validation
Afficher les états d'erreur ou d'avertissement.
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
function App() {
const simpleData: TreeDataNode[] = [
{ key: 'opt1', title: 'Option 1' },
{ key: 'opt2', title: 'Option 2' },
{ key: 'opt3', title: 'Option 3' },
]
return (
<div className="flex flex-col gap-2">
<TreeSelect treeData={simpleData} status="error" placeholder="Error state" />
<TreeSelect treeData={simpleData} status="warning" placeholder="Warning state" />
</div>
)
}
export default App Chargement asynchrone
Charger les nœuds de l'arbre de manière asynchrone lors de l'expansion.
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const [treeData, setTreeData] = useState<TreeDataNode[]>([
{ key: 'region1', title: 'Region 1' },
{ key: 'region2', title: 'Region 2' },
])
const loadData = async (node: TreeDataNode) => {
await new Promise((resolve) => setTimeout(resolve, 1000))
setTreeData((prev) => {
const updateNode = (nodes: TreeDataNode[]): TreeDataNode[] =>
nodes.map((n) =>
n.key === node.key
? {
...n,
children: [
{ key: `${n.key}-1`, title: 'Child 1', isLeaf: true },
{ key: `${n.key}-2`, title: 'Child 2', isLeaf: true },
],
}
: { ...n, children: n.children ? updateNode(n.children) : undefined }
)
return updateNode(prev)
})
}
return (
<TreeSelect
treeData={treeData}
loadData={loadData}
placeholder="Expand to load"
/>
)
}
export default App Nombre maximum d'étiquettes
Limiter le nombre d'étiquettes visibles.
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const categoriesData: TreeDataNode[] = [
{
key: 'electronics',
title: 'Electronics',
children: [
{
key: 'phones',
title: 'Phones',
children: [
{ key: 'iphone', title: 'iPhone' },
{ key: 'samsung', title: 'Samsung' },
{ key: 'pixel', title: 'Pixel' },
],
},
{
key: 'laptops',
title: 'Laptops',
children: [
{ key: 'macbook', title: 'MacBook' },
{ key: 'thinkpad', title: 'ThinkPad' },
],
},
],
},
{
key: 'clothing',
title: 'Clothing',
children: [
{ key: 'shirts', title: 'Shirts' },
{ key: 'pants', title: 'Pants' },
{ key: 'shoes', title: 'Shoes' },
],
},
]
const [value, setValue] = useState<string[]>([])
return (
<TreeSelect
treeData={categoriesData}
value={value}
onChange={(val) => setValue(val as string[])}
placeholder="Select items"
treeCheckable
maxTagCount={2}
maxTagPlaceholder={(omitted) => `+${omitted.length} more...`}
/>
)
}
export default App Ligne d'arbre
Afficher les lignes de connexion entre les nœuds de l'arbre.
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
function App() {
const basicTreeData: TreeDataNode[] = [
{
key: 'parent',
title: 'Parent Node',
children: [
{
key: 'child1',
title: 'Child Node 1',
children: [
{ key: 'leaf1', title: 'Leaf 1' },
{ key: 'leaf2', title: 'Leaf 2' },
],
},
{ key: 'child2', title: 'Child Node 2' },
],
},
]
return (
<TreeSelect
treeData={basicTreeData}
placeholder="With tree lines"
treeLine
treeDefaultExpandAll
/>
)
}
export default App Éléments désactivés
Certains nœuds de l'arbre peuvent être désactivés.
import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'
function App() {
const [value, setValue] = useState<string | undefined>()
const treeDataWithDisabled: TreeDataNode[] = [
{
key: 'parent',
title: 'Available Parent',
children: [
{ key: 'child1', title: 'Available Child' },
{ key: 'child2', title: 'Disabled Child', disabled: true },
{ key: 'child3', title: 'Another Available' },
],
},
]
return (
<TreeSelect
treeData={treeDataWithDisabled}
value={value}
onChange={(val) => setValue(val as string)}
placeholder="Select an item"
/>
)
}
export default App TreeSelect
Section intitulée « TreeSelect »| Propriété | Description | Type | Défaut |
|---|---|---|---|
treeData | Structure de données d’arbre | TreeDataNode[] | [] |
value | Valeur(s) sélectionnée(s) | string | string[] | - |
defaultValue | Valeur(s) sélectionnée(s) par défaut | string | string[] | [] |
onChange | Callback lorsque la sélection change | (value: string | string[], labels: ReactNode[]) => void | - |
multiple | Permettre la sélection multiple | boolean | false |
treeCheckable | Afficher la case à cocher pour les nœuds de l’arbre | boolean | false |
treeCheckStrictly | Vérifier sans association parent-enfant | boolean | false |
showCheckedStrategy | Comment afficher les éléments cochés | 'SHOW_ALL' | 'SHOW_PARENT' | 'SHOW_CHILD' | 'SHOW_ALL' |
showSearch | Activer la fonctionnalité de recherche | boolean | false |
searchValue | Valeur contrôlée de l’entrée de recherche | string | - |
onSearch | Callback lorsque l’entrée de recherche change | (value: string) => void | - |
filterTreeNode | Fonction de filtrage personnalisée | (searchValue: string, node: TreeDataNode) => boolean | - |
placeholder | Texte de placeholder | string | 'Please select' |
allowClear | Afficher le bouton effacer | boolean | true |
disabled | Désactiver la sélection | boolean | false |
size | Taille de l’entrée | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' |
color | Thème de couleur | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | - |
status | État de validation | 'error' | 'warning' | - |
maxTagCount | Nombre maximum d’étiquettes à afficher | number | 'responsive' | - |
maxTagPlaceholder | Contenu pour les étiquettes masquées | ReactNode | ((omittedValues: string[]) => ReactNode) | - |
treeLine | Afficher les lignes de connexion | boolean | false |
treeDefaultExpandAll | Développer tous les nœuds de l’arbre par défaut | boolean | false |
treeDefaultExpandedKeys | Clés de nœuds d’arbre étendus par défaut | string[] | [] |
treeExpandedKeys | Clés de nœuds d’arbre étendus contrôlés | string[] | - |
onTreeExpand | Callback lorsque les nœuds de l’arbre se développent/réduisent | (expandedKeys: string[]) => void | - |
loadData | Charger les données de manière asynchrone | (node: TreeDataNode) => Promise<void> | - |
fieldNames | Personnaliser les noms de champs | { label?: string; value?: string; children?: string } | - |
open | Visibilité contrôlée du menu déroulant | boolean | - |
onDropdownVisibleChange | Callback lorsque la visibilité du menu déroulant change | (open: boolean) => void | - |
suffixIcon | Icône de suffixe personnalisée | ReactNode | - |
switcherIcon | Icône personnalisée de développer/réduire | ReactNode | ((props: { expanded: boolean }) => ReactNode) | - |
notFoundContent | Contenu lorsqu’il n’y a pas de résultats | ReactNode | 'No results found' |
dropdownRender | Rendu personnalisé du contenu déroulant | (menu: ReactNode) => ReactNode | - |
popupClassName | Classe pour le menu déroulant | string | - |
data-testid | ID de test pour le composant | string | 'treeselect' |
className | Classes CSS supplémentaires | string | - |
TreeDataNode
Section intitulée « TreeDataNode »| Propriété | Description | Type | Défaut |
|---|---|---|---|
key | Identifiant unique | string | - |
title | Texte affiché | ReactNode | - |
children | Nœuds enfants | TreeDataNode[] | - |
disabled | Si désactivé | boolean | - |
isLeaf | Si c’est un nœud feuille | boolean | - |
Accessibilité
Section intitulée « Accessibilité »Le composant TreeSelect suit les modèles WAI-ARIA combobox et tree avec des attributs ARIA appropriés et une navigation au clavier.
Navigation au clavier
Section intitulée « Navigation au clavier »| Touche | Action |
|---|---|
| Entrée / Espace | Ouvrir le menu déroulant ou sélectionner l’élément focalisé |
| Échap | Fermer le menu déroulant |
| ↓ | Ouvrir le menu déroulant ou déplacer le focus vers le bas |
| ↑ | Déplacer le focus vers le haut |
| → | Développer le nœud de l’arbre focalisé |
| ← | Réduire le nœud de l’arbre focalisé ou se déplacer vers le parent |
| Début | Déplacer le focus vers le premier élément |
| Fin | Déplacer le focus vers le dernier élément |
Le composant expose les attributs data-testid et data-state pour les tests :
| Élément | ID de test | Attributs de données |
|---|---|---|
| Racine | {baseTestId} | data-state="open|closed", data-disabled |
| Déclencheur | {baseTestId}-trigger | - |
| Menu déroulant | {baseTestId}-dropdown | - |
| Recherche | {baseTestId}-search | - |
| Effacer | {baseTestId}-clear | - |
| Option | {baseTestId}-option-{key} | data-state="selected|unselected", data-disabled |
| Étiquette | {baseTestId}-tag-{key} | - |
| Vide | {baseTestId}-empty | - |
Passez une prop personnalisée data-testid pour utiliser un ID de base différent.