Aller au contenu

TreeSelect

Sélection arborescente déroulante pour données hiérarchiques.

import { TreeSelect } from 'asterui'
import type { TreeDataNode } from 'asterui'

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
PropriétéDescriptionTypeDéfaut
treeDataStructure de données d’arbreTreeDataNode[][]
valueValeur(s) sélectionnée(s)string | string[]-
defaultValueValeur(s) sélectionnée(s) par défautstring | string[][]
onChangeCallback lorsque la sélection change(value: string | string[], labels: ReactNode[]) => void-
multiplePermettre la sélection multiplebooleanfalse
treeCheckableAfficher la case à cocher pour les nœuds de l’arbrebooleanfalse
treeCheckStrictlyVérifier sans association parent-enfantbooleanfalse
showCheckedStrategyComment afficher les éléments cochés'SHOW_ALL' | 'SHOW_PARENT' | 'SHOW_CHILD''SHOW_ALL'
showSearchActiver la fonctionnalité de recherchebooleanfalse
searchValueValeur contrôlée de l’entrée de recherchestring-
onSearchCallback lorsque l’entrée de recherche change(value: string) => void-
filterTreeNodeFonction de filtrage personnalisée(searchValue: string, node: TreeDataNode) => boolean-
placeholderTexte de placeholderstring'Please select'
allowClearAfficher le bouton effacerbooleantrue
disabledDésactiver la sélectionbooleanfalse
sizeTaille de l’entrée'xs' | 'sm' | 'md' | 'lg' | 'xl''md'
colorThème de couleur'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error'-
statusÉtat de validation'error' | 'warning'-
maxTagCountNombre maximum d’étiquettes à affichernumber | 'responsive'-
maxTagPlaceholderContenu pour les étiquettes masquéesReactNode | ((omittedValues: string[]) => ReactNode)-
treeLineAfficher les lignes de connexionbooleanfalse
treeDefaultExpandAllDévelopper tous les nœuds de l’arbre par défautbooleanfalse
treeDefaultExpandedKeysClés de nœuds d’arbre étendus par défautstring[][]
treeExpandedKeysClés de nœuds d’arbre étendus contrôlésstring[]-
onTreeExpandCallback lorsque les nœuds de l’arbre se développent/réduisent(expandedKeys: string[]) => void-
loadDataCharger les données de manière asynchrone(node: TreeDataNode) => Promise<void>-
fieldNamesPersonnaliser les noms de champs{ label?: string; value?: string; children?: string }-
openVisibilité contrôlée du menu déroulantboolean-
onDropdownVisibleChangeCallback lorsque la visibilité du menu déroulant change(open: boolean) => void-
suffixIconIcône de suffixe personnaliséeReactNode-
switcherIconIcône personnalisée de développer/réduireReactNode | ((props: { expanded: boolean }) => ReactNode)-
notFoundContentContenu lorsqu’il n’y a pas de résultatsReactNode'No results found'
dropdownRenderRendu personnalisé du contenu déroulant(menu: ReactNode) => ReactNode-
popupClassNameClasse pour le menu déroulantstring-
data-testidID de test pour le composantstring'treeselect'
classNameClasses CSS supplémentairesstring-
PropriétéDescriptionTypeDéfaut
keyIdentifiant uniquestring-
titleTexte affichéReactNode-
childrenNœuds enfantsTreeDataNode[]-
disabledSi désactivéboolean-
isLeafSi c’est un nœud feuilleboolean-

Le composant TreeSelect suit les modèles WAI-ARIA combobox et tree avec des attributs ARIA appropriés et une navigation au clavier.

ToucheAction
Entrée / EspaceOuvrir le menu déroulant ou sélectionner l’élément focalisé
ÉchapFermer 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ébutDéplacer le focus vers le premier élément
FinDéplacer le focus vers le dernier élément

Le composant expose les attributs data-testid et data-state pour les tests :

ÉlémentID de testAttributs 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.