Saltar al contenido principal

Tree

Datos jerárquicos con nodos expandibles, selección y navegación por teclado.

src
components
button.tsx
card.tsx
tree.tsx
index.ts
package.json
tsconfig.json
1'use client';
2
3import { Tree } from '@/components/ui/tree';
4
5export function Default() {
6 return (
7 <Tree defaultExpanded={['src', 'src/components']} className="max-w-xs">
8 <Tree.Item value="src" label="src">
9 <Tree.Item value="src/components" label="components">
10 <Tree.Item value="src/components/button.tsx" label="button.tsx" />
11 <Tree.Item value="src/components/card.tsx" label="card.tsx" />
12 <Tree.Item value="src/components/tree.tsx" label="tree.tsx" />
13 </Tree.Item>
14 <Tree.Item value="src/hooks" label="hooks">
15 <Tree.Item value="src/hooks/use-local-storage.ts" label="use-local-storage.ts" />
16 </Tree.Item>
17 <Tree.Item value="src/index.ts" label="index.ts" />
18 </Tree.Item>
19 <Tree.Item value="package.json" label="package.json" />
20 <Tree.Item value="tsconfig.json" label="tsconfig.json" />
21 </Tree>
22 );
23}

Instalación

pnpm dlx nachui add tree

Anatomía

1import { Tree } from '@/components/ui/tree';
1<Tree defaultExpanded={['src']}>
2 <Tree.Item value="src" label="src">
3 <Tree.Item value="src/index.ts" label="index.ts" />
4 </Tree.Item>
5 <Tree.Item value="package.json" label="package.json" />
6</Tree>
Un item con hijos es una rama: al hacer clic alterna la expansión. Un item sin hijos es una hoja: al hacer clic se selecciona y dispara onSelectedChange en la raíz. Las flechas recorren las filas visibles, ArrowRight expande, ArrowLeft colapsa o salta al padre, Home y End van a los extremos.

Composición

Usa la siguiente composición para construir un Tree:
Tree
└── Tree.Item
└── Tree.Item

Variantes

Líneas

showLines dibuja una guía a lo largo de cada nivel.
app
docs
elements
page.tsx
layout.tsx
page.tsx
layout.tsx
globals.css
proxy.ts
1'use client';
2
3import { Tree } from '@/components/ui/tree';
4
5export function Lines() {
6 return (
7 <Tree showLines defaultExpanded={['app', 'app/docs', 'app/docs/elements']} className="max-w-xs">
8 <Tree.Item value="app" label="app">
9 <Tree.Item value="app/docs" label="docs">
10 <Tree.Item value="app/docs/elements" label="elements">
11 <Tree.Item value="app/docs/elements/page.tsx" label="page.tsx" />
12 <Tree.Item value="app/docs/elements/layout.tsx" label="layout.tsx" />
13 </Tree.Item>
14 <Tree.Item value="app/docs/page.tsx" label="page.tsx" />
15 </Tree.Item>
16 <Tree.Item value="app/layout.tsx" label="layout.tsx" />
17 <Tree.Item value="app/globals.css" label="globals.css" />
18 </Tree.Item>
19 <Tree.Item value="proxy.ts" label="proxy.ts" />
20 </Tree>
21 );
22}

Iconos

Pasa icon en cada nodo y iconOpen en las ramas que cambian al expandirse, como las carpetas.
packages
ui
tree.tsx
frame.tsx
turbo.json
1'use client';
2
3import { File01Icon, Folder01Icon, Folder02Icon } from '@hugeicons/core-free-icons';
4import { HugeiconsIcon } from '@hugeicons/react';
5import { Tree } from '@/components/ui/tree';
6
7const folderClosed = <HugeiconsIcon icon={Folder01Icon} size={16} />;
8const folderOpen = <HugeiconsIcon icon={Folder02Icon} size={16} />;
9const file = <HugeiconsIcon icon={File01Icon} size={16} />;
10
11export function Icons() {
12 return (
13 <Tree defaultExpanded={['packages', 'packages/ui']} className="max-w-xs">
14 <Tree.Item value="packages" label="packages" icon={folderClosed} iconOpen={folderOpen}>
15 <Tree.Item value="packages/ui" label="ui" icon={folderClosed} iconOpen={folderOpen}>
16 <Tree.Item value="packages/ui/tree.tsx" label="tree.tsx" icon={file} />
17 <Tree.Item value="packages/ui/frame.tsx" label="frame.tsx" icon={file} />
18 </Tree.Item>
19 <Tree.Item value="packages/cli" label="cli" icon={folderClosed} iconOpen={folderOpen}>
20 <Tree.Item value="packages/cli/index.ts" label="index.ts" icon={file} />
21 </Tree.Item>
22 </Tree.Item>
23 <Tree.Item value="turbo.json" label="turbo.json" icon={file} />
24 </Tree>
25 );
26}

Más y menos

toggleIcon="plus-minus" cambia el chevron por conmutadores de más y menos.
content
docs
README.md
1'use client';
2
3import { File01Icon, Folder01Icon, Folder02Icon } from '@hugeicons/core-free-icons';
4import { HugeiconsIcon } from '@hugeicons/react';
5import { Tree } from '@/components/ui/tree';
6
7const folderClosed = <HugeiconsIcon icon={Folder01Icon} size={16} />;
8const folderOpen = <HugeiconsIcon icon={Folder02Icon} size={16} />;
9const file = <HugeiconsIcon icon={File01Icon} size={16} />;
10
11export function PlusMinus() {
12 return (
13 <Tree
14 toggleIcon="plus-minus"
15 showLines
16 defaultExpanded={['content', 'content/docs']}
17 className="max-w-xs"
18 >
19 <Tree.Item value="content" label="content" icon={folderClosed} iconOpen={folderOpen}>
20 <Tree.Item value="content/docs" label="docs" icon={folderClosed} iconOpen={folderOpen}>
21 <Tree.Item value="content/docs/en" label="en" icon={folderClosed} iconOpen={folderOpen}>
22 <Tree.Item value="content/docs/en/tree.mdx" label="tree.mdx" icon={file} />
23 </Tree.Item>
24 <Tree.Item value="content/docs/es" label="es" icon={folderClosed} iconOpen={folderOpen}>
25 <Tree.Item value="content/docs/es/tree.mdx" label="tree.mdx" icon={file} />
26 </Tree.Item>
27 </Tree.Item>
28 </Tree.Item>
29 <Tree.Item value="README.md" label="README.md" icon={file} />
30 </Tree>
31 );
32}

Referencia de API

Tree

PropTypeDefaultDescription
defaultExpandedstring[][]Ramas expandidas al montar
defaultSelectedstring-Hoja seleccionada inicialmente
selectedstring-Hoja seleccionada en modo controlado
onSelectedChange(value: string) => void-Callback al seleccionar una hoja
indentnumber16Píxeles de sangría por nivel
toggleIcon'chevron' | 'plus-minus''chevron'Estilo del icono de expandir y colapsar
showLinesbooleanfalseDibuja guías entre niveles
labelstring'Tree'Nombre accesible del árbol
classNamestring-Clases CSS adicionales

Tree.Item

PropTypeDefaultDescription
valuestring-Valor único, usado para expansión y selección
labelReactNode-Contenido de la fila
iconReactNode-Icono inicial
iconOpenReactNode-Icono mientras la rama está expandida
disabledbooleanfalseDeshabilita la fila
onSelect() => void-Callback al seleccionar esta hoja
classNamestring-Clases CSS adicionales
¿Encontraste algo que mejorar?

¿Notaste un error, tipografía o detalle faltante en esta página? Ayúdanos a mejorar la documentación abriendo un issue en GitHub.

Crear un Issue
Ctrl+I