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