Aller au contenu

Tree

Structure arborescente hiérarchique pour afficher des données imbriquées.

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

Arbre basique

Arbre simple avec des nœuds extensibles.

Parent Node
Child Node 1
Leaf Node 1
Leaf Node 2
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  return (
      <Tree treeData={basicTreeData} defaultExpandedKeys={['0', '0-0']} />
    )
}

export default App

Cochable

Arbre avec sélection par case à cocher.

Parent Node
Child Node 1
Leaf Node 1
Leaf Node 2
Child Node 2
Leaf Node 3

Checked: None

import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  const [checkedKeys, setCheckedKeys] = useState<string[]>([])
  
  return (
      <Tree
        treeData={basicTreeData}
        checkable
        checkedKeys={checkedKeys}
        onCheck={setCheckedKeys}
        defaultExpandedKeys={['0', '0-0', '0-1']}
      />
      <p className="mt-4 text-sm">Checked: {checkedKeys.join(', ') || 'None'}</p>
    )
}

export default App

Sélectionnable

Arbre avec sélection de nœuds.

Parent Node
Child Node 1
Leaf Node 1
Leaf Node 2
Child Node 2
Leaf Node 3

Selected: None

import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  const [selectedKeys, setSelectedKeys] = useState<string[]>([])
  
  return (
      <Tree
        treeData={basicTreeData}
        selectable
        selectedKeys={selectedKeys}
        onSelect={setSelectedKeys}
        defaultExpandedKeys={['0', '0-0', '0-1']}
      />
      <p className="mt-4 text-sm">Selected: {selectedKeys.join(', ') || 'None'}</p>
    )
}

export default App

Sélection multiple

Permettre la sélection de plusieurs nœuds.

Parent Node
Child Node 1
Leaf Node 1
Leaf Node 2
Child Node 2
Leaf Node 3
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  const [selectedKeys, setSelectedKeys] = useState<string[]>([])
  
  return (
      <Tree
        treeData={basicTreeData}
        selectable
        multiple
        selectedKeys={selectedKeys}
        onSelect={setSelectedKeys}
        defaultExpandedKeys={['0', '0-0', '0-1']}
      />
    )
}

export default App

Afficher les lignes

Afficher les lignes de connexion entre les nœuds.

src
components
Button.tsx
Input.tsx
App.tsx
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'

function App() {
  const fileTreeData: TreeDataNode[] = [
    {
      key: 'src',
      title: 'src',
      children: [
        {
          key: 'components',
          title: 'components',
          children: [
            { key: 'Button.tsx', title: 'Button.tsx' },
            { key: 'Input.tsx', title: 'Input.tsx' },
          ],
        },
        { key: 'App.tsx', title: 'App.tsx' },
      ],
    },
  ]
  
  return (
      <Tree
        treeData={fileTreeData}
        showLine
        defaultExpandedKeys={['src', 'components']}
      />
    )
}

export default App

Afficher les icônes

Afficher des icônes personnalisées pour les nœuds.

src
App.tsx
index.tsx
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { FolderIcon, DocumentIcon } from '@aster-ui/icons/solid'

function App() {
  const treeDataWithIcons: TreeDataNode[] = [
    {
      key: 'src',
      title: 'src',
      icon: <FolderIcon size="sm" />,
      children: [
        { key: 'App.tsx', title: 'App.tsx', icon: <DocumentIcon size="sm" /> },
        { key: 'index.tsx', title: 'index.tsx', icon: <DocumentIcon size="sm" /> },
      ],
    },
  ]
  
  return (
      <Tree treeData={treeDataWithIcons} showIcon defaultExpandedKeys={['src']} />
    )
}

export default App

Modèle composé

Utilisez Tree.Node pour une structure d'arbre déclarative.

Parent Node
Child Node 2
import { Tree } from 'asterui'

function App() {
  return (
      <Tree defaultExpandedKeys={['parent']}>
        <Tree.Node key="parent" title="Parent Node">
          <Tree.Node key="child-1" title="Child Node 1">
            <Tree.Node key="leaf-1" title="Leaf Node 1" />
            <Tree.Node key="leaf-2" title="Leaf Node 2" />
          </Tree.Node>
          <Tree.Node key="child-2" title="Child Node 2" />
        </Tree.Node>
      </Tree>
    )
}

export default App

Couleurs de case à cocher

Personnalisez l'apparence des cases à cocher avec les couleurs DaisyUI.

Parent Node
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  return (
      <Tree
        treeData={basicTreeData}
        checkable
        checkboxColor="success"
        checkboxSize="md"
        defaultExpandedKeys={['0']}
      />
    )
}

export default App

Vérification stricte

Découpler la relation parent-enfant des cases à cocher.

Parent Node
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'

function App() {
  const basicTreeData: TreeDataNode[] = [
    {
      key: '0',
      title: 'Parent Node',
      children: [
        {
          key: '0-0',
          title: 'Child Node 1',
          children: [
            { key: '0-0-0', title: 'Leaf Node 1' },
            { key: '0-0-1', title: 'Leaf Node 2' },
          ],
        },
        {
          key: '0-1',
          title: 'Child Node 2',
          children: [{ key: '0-1-0', title: 'Leaf Node 3' }],
        },
      ],
    },
  ]
  
  const [checkedKeys, setCheckedKeys] = useState<string[]>([])
  
  return (
      <Tree
        treeData={basicTreeData}
        checkable
        checkStrictly
        checkedKeys={checkedKeys}
        onCheck={setCheckedKeys}
        defaultExpandedKeys={['0']}
      />
    )
}

export default App

Chargement asynchrone

Charger les nœuds enfants de manière asynchrone lors de l'expansion.

Expand to load
Expand to load
import { Tree } from 'asterui'
import type { TreeDataNode } from 'asterui'
import { useState } from 'react'

function App() {
  const [treeData, setTreeData] = useState<TreeDataNode[]>([
    { key: '0', title: 'Expand to load' },
    { key: '1', title: 'Expand to load' },
  ])
  
  const loadData = async (node: TreeDataNode) => {
    await new Promise(resolve => setTimeout(resolve, 1000))
    setTreeData(prev => {
      const update = (nodes: TreeDataNode[]): TreeDataNode[] =>
        nodes.map(n => n.key === node.key
          ? { ...n, children: [
              { key: `${n.key}-0`, title: 'Child 1', isLeaf: true },
              { key: `${n.key}-1`, title: 'Child 2', isLeaf: true },
            ]}
          : { ...n, children: n.children ? update(n.children) : undefined }
        )
      return update(prev)
    })
  }
  
  return (
      <Tree treeData={treeData} loadData={loadData} />
    )
}

export default App
PropriétéDescriptionTypeDéfaut
treeDataStructure de données d’arbre (alternative au modèle composé)TreeDataNode[][]
childrenEnfants Tree.Node pour le modèle composéReact.ReactNode-
checkableAfficher une case à cocher pour chaque nœudbooleanfalse
checkboxColorCouleur de la case à cocher (DaisyUI)'primary' | 'secondary' | 'accent' | 'neutral' | 'info' | 'success' | 'warning' | 'error''primary'
checkboxSizeTaille de la case à cocher (DaisyUI)'xs' | 'sm' | 'md' | 'lg' | 'xl''sm'
checkedKeysClés cochées contrôléesstring[]-
defaultCheckedKeysClés cochées par défautstring[][]
checkStrictlyDécoupler la relation parent-enfant des cases à cocherbooleanfalse
onCheckCallback lorsqu’un nœud est coché(keys: string[], info: { node, checked }) => void-
selectableActiver la sélection de nœudsbooleantrue
selectedKeysClés sélectionnées contrôléesstring[]-
defaultSelectedKeysClés sélectionnées par défautstring[][]
onSelectCallback lorsqu’un nœud est sélectionné(keys: string[], info: { node, selected }) => void-
multiplePermettre la sélection multiplebooleanfalse
expandedKeysClés étendues contrôléesstring[]-
defaultExpandedKeysClés étendues par défautstring[][]
defaultExpandAllDévelopper tous les nœuds par défautbooleanfalse
autoExpandParentDévelopper automatiquement les nœuds parentsbooleantrue
onExpandCallback lorsqu’un nœud est développé(keys: string[], info: { node, expanded }) => void-
showLineAfficher les lignes de connexionbooleanfalse
showIconAfficher les icônes de nœudbooleanfalse
blockNodeFaire en sorte que les nœuds remplissent l’espace horizontalbooleanfalse
switcherIconIcône personnalisée de développer/réduireReactNode | ((expanded: boolean) => ReactNode)-
titleRenderFonction de rendu de titre personnalisée(node: TreeDataNode) => ReactNode-
filterTreeNodeFonction de filtrage pour mettre en évidence les nœuds(node: TreeDataNode) => boolean-
loadDataFonction de chargement de données asynchrone(node: TreeDataNode) => Promise<void>-
onRightClickGestionnaire de clic droit(info: { event, node }) => void-
fieldNamesNoms de champs personnalisés pour le mappage de données{ key?: string; title?: string; children?: string }-
classNameClasses CSS supplémentairesstring-
PropriétéDescriptionTypeDéfaut
keyIdentifiant uniquestring-
titleTitre affichéReact.ReactNode-
childrenNœuds enfantsTreeDataNode[]-
iconIcône personnaliséeReact.ReactNode-
disabledDésactiver le nœudbooleanfalse
disableCheckboxDésactiver la case à cocher pour le nœudbooleanfalse
selectableSi le nœud peut être sélectionnébooleantrue
checkableSi le nœud affiche une case à cocherbooleantrue
isLeafForcer le nœud à être une feuille (pas d’icône de développement)boolean-
PropriétéDescriptionTypeDéfaut
keyIdentifiant unique (prop key React)string-
titleTitre affichéReact.ReactNode-
childrenÉléments enfants Tree.NodeReact.ReactNode-
iconIcône personnaliséeReact.ReactNode-
disabledDésactiver le nœudbooleanfalse
disableCheckboxDésactiver la case à cocher pour le nœudbooleanfalse
selectableSi le nœud peut être sélectionnébooleantrue
checkableSi le nœud affiche une case à cocherbooleantrue
isLeafForcer le nœud à être une feuille (pas d’icône de développement)boolean-

Le composant Tree implémente le modèle d’arbre WAI-ARIA complet :

  • role="tree" sur le conteneur et role="treeitem" sur les nœuds
  • aria-expanded indique l’état d’expansion du nœud
  • aria-selected indique l’état de sélection
  • aria-checked indique l’état de la case à cocher (avec "mixed" pour indéterminé)
  • aria-disabled indique l’état désactivé
  • aria-level indique la profondeur d’imbrication
ToucheAction
↓Déplacer le focus vers le nœud visible suivant
↑Déplacer le focus vers le nœud visible précédent
→Développer un nœud réduit, ou se déplacer vers le premier enfant
←Réduire un nœud développé
Entrée / EspaceBasculer la case à cocher, sélectionner le nœud ou développer/réduire
DébutDéplacer le focus vers le premier nœud
FinDéplacer le focus vers le dernier nœud visible

Le composant inclut des attributs de données pour les tests :

  • data-testid="tree" sur le conteneur de l’arbre
  • data-testid="tree-node-{key}" sur chaque nœud
  • data-state="selected|expanded|collapsed" indique l’état du nœud
  • data-key="{key}" fournit la clé du nœud