Datos
Tree
Elementos anidados que se abren y cierran: archivos, categorías, permisos, organigramas. Tres tamaños, líneas guía, modo directorio, selección simple o múltiple, casillas en cascada, carga diferida, filtro, arrastrar y soltar, renombrar, filas con detalle, secciones y virtualización.
import { Tree, TreeItem, TreeSection, TreeHeader, getTreeKeys } from '@alea/ui';
Ejemplos
Tree
Carpetas que se abren y se cierran.
Selección
Elige varios archivos; Espacio selecciona, las flechas se mueven.
Tamaños
sm (filas de 28 px) para paneles densos, md (36 px) por defecto, lg (44 px) para pantallas táctiles. Las pantallas táctiles siempre tienen filas de 44 px.
Directorio con líneas guía
directory da a carpetas y archivos sus íconos y abre una carpeta al presionarla; showLines dibuja una línea por nivel.
Estilo de selección
subtle (por defecto) tiñe la fila seleccionada; solid la rellena con el acento, para árboles de navegación.
Casillas en cascada
Marcar un padre marca todos sus hijos; un padre con solo algunos marcados muestra un guion (marcado a medias).
Checked: brand, neutral
Marcado estricto
Padres e hijos se marcan por separado: para permisos donde una sección y sus páginas son accesos distintos.
Carga diferida
Los nodos sin hijos los cargan la primera vez que se abren; un spinner reemplaza al chevron y aparece una fila de carga.
Filtrar
filterText mantiene las coincidencias y sus padres, los abre y marca la coincidencia. Bórralo y el árbol vuelve a como estaba.
Arrastrar y soltar
Arrastra una fila entre otras para reordenar, o sobre una carpeta para moverla adentro. Con el teclado: Tab hasta el asa, Enter, flechas, Enter.
Renombrar
F2 o doble clic convierte el título en un campo; Enter guarda, Escape cancela. onRename te da el nombre nuevo.
Select a row and press F2.
Filas enriquecidas
Una descripción bajo el título, y meta o acciones al final. Los botones de una fila siguen accesibles con Tab y flechas.
Secciones
Agrupa elementos bajo encabezados, como una barra lateral con Favoritos y Espacio de trabajo.
Expandir y contraer todo
Controla expandedKeys; getTreeKeys(data) lista cada padre para un botón "Expandir todo".
10.000 nodos, virtualizado
Solo las filas en pantalla están en la página; pasa la altura de fila y un maxHeight.
Deshabilitado y vacío
Un nodo deshabilitado sigue visible pero no se puede seleccionar ni abrir al presionarlo; un árbol vacío lo indica.
Partes de una fila
- Fila: la línea completa; el nivel define la sangría (indent px por nivel).
- Asa de arrastre (draggable): aparece al pasar el mouse y con foco, siempre en táctil.
- Flecha: abre y cierra; se vuelve un spinner mientras cargan los hijos.
- Casilla (selección múltiple o checkable): marcada, desmarcada o mixta.
- Ícono: el tuyo, o íconos de carpeta y archivo con directory.
- Título y descripción: el título se corta, la descripción va atenuada.
- Final: datos (conteos, badges) y acciones (IconButtons).
- Líneas guía (showLines): una por nivel, pasando por cada flecha.
Elementos en JSX o datos
Hay dos formas de llenar un Tree. JSX: anida elementos TreeItem; bueno para árboles estáticos, menús y barras laterales. Datos: pasa data, un arreglo de TreeNode ({ id, title, icon, description, end, children, isLeaf, isDisabled, href }). Los datos activan defaultExpandAll, checkable en cascada, loadChildren, filterText, draggable y renombrar, porque el árbol necesita conocer toda la estructura para hacerlo.
Con datos, mantén tu copia al día con onDataChange: se llama después de arrastrar, renombrar o cargar con el árbol nuevo.
Responsive
- Las filas ocupan todo el ancho de su contenedor; títulos y descripciones se cortan con puntos suspensivos en lugar de saltar de línea.
- En pantallas táctiles las filas miden al menos 44 px y el asa de arrastre siempre se ve.
- La sangría baja con el tamaño: 16, 20 o 24 px por nivel. En un teléfono, prefiere size="sm" con menos niveles, o pasa indent={12}.
- Dentro de un Drawer, un árbol es una buena navegación móvil: usa variant="solid" y selectionMode="single".
Configuraciones
Cada valor de cada propiedad, lado a lado. Los números coinciden con la leyenda.
- Show Lines
showLines - Size
size - Variant
variant - Selección
Anatomía
Las partes del componente y la clase que da estilo a cada una.
Tokens
Los tokens de diseño que usa este componente, con su valor en el tema actual. Cambia cualquiera para darle otro estilo.
Color
--alea-accent…--alea-accent-on…--alea-accent-solid…--alea-border-strong…--alea-focus…--alea-surface-hover…--alea-text-muted…
Radius
--alea-radius-sm…
Type
--alea-font-size-md…--alea-font-size-sm…
Component
--alea-tree-indent…--alea-tree-level…--alea-tree-row…
Props
Tree props
Elementos anidados que se abren y se cierran: archivos, categorías, esquemas, organigramas. Flecha derecha abre, Flecha izquierda cierra. Pasa TreeItems como hijos, o todo el árbol como data para tener casillas en cascada, carga diferida, filtro, arrastrar y soltar y renombrar.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
checkable | boolean | - | Casillas en cascada: marcar un padre marca sus hijos, y un padre con algunos hijos marcados muestra un guion (modo data). |
checkedKeys | Iterable<Key> | - | Las claves marcadas (controlado). |
checkStrictly | boolean | - | Padres e hijos se marcan por separado, sin cascada. |
children | ReactNode | ((item: T) => ReactNode) | - | Elementos como JSX (TreeItem) o una función que los muestra. O pasa data en su lugar. |
data | TreeNode[] | - | El árbol como datos: habilita defaultExpandAll, casillas en cascada, loadChildren, filterText, draggable y renombrar. |
defaultCheckedKeys | Iterable<Key> | - | Las claves marcadas al inicio. |
defaultExpandAll | boolean | - | Abre todos los nodos al inicio (modo data). |
directory | boolean | false | Un explorador de archivos: carpetas y archivos tienen íconos, y presionar una carpeta la abre. |
draggable | boolean | false | Las filas se pueden arrastrar para reordenar, o soltar sobre una carpeta para moverlas adentro; con el teclado se usa el asa (modo data). |
expandOnClick | boolean | - | Presionar una fila la abre o la cierra. Por defecto: activado cuando no hay selección, o con directory. |
filterText | string | '' | Muestra solo los nodos que coinciden (y sus padres), los abre y marca la coincidencia. |
indent | number | - | Sangría por nivel en px. Por defecto 16, 20 o 24 según el tamaño. |
loadChildren | ((node: TreeNode) => Promise<TreeNode[]>) | - | Carga los hijos de un nodo la primera vez que se abre (carga diferida). Aparece una fila de carga mientras espera. |
maxHeight | string | number | - | Tiene scroll dentro de esta altura. |
onCheckedChange | ((keys: Key[], info: { halfChecked: Key[]; }) => void) | - | Se llama con cada clave marcada, y los padres marcados a medias. |
onDataChange | ((data: TreeNode[]) => void) | - | Se llama con los nuevos datos después de arrastrar, renombrar o una carga diferida, para que los conserves. |
onRename | ((id: Key, title: string) => void) | - | F2 o doble clic renombra una fila; Enter guarda, Escape cancela (modo data). |
renderTitle | ((node: TreeNode, state: { isExpanded: boolean; level: number; }) => ReactNode) | - | Contenido personalizado para el título de un nodo. |
showLines | boolean | - | Líneas guía que muestran cada nivel. |
size | "sm" | "md" | "lg" | 'md' | Altura de fila: sm 28 px, md 36 px (por defecto), lg 44 px. Las pantallas táctiles tienen al menos 44 px. |
variant | "solid" | "subtle" | 'subtle' | Cómo se ve la fila seleccionada: subtle (con tinte, por defecto) o solid (acento). |
virtualized | number | - | Muestra solo las filas en pantalla: pasa la altura de fila. Necesita maxHeight. |
TreeItem props
Un elemento en un Tree; anida TreeItems adentro para los hijos.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
titleobligatoria | ReactNode | - | La etiqueta del elemento. |
children | ReactNode | - | TreeItems anidados. |
description | ReactNode | - | Una segunda línea apagada bajo el título. |
end | ReactNode | - | Meta o acciones a la derecha (siguen accesibles con el teclado). |
icon | ReactNode | - | Un ícono antes del título. |
isFolder | boolean | - | En un árbol de directorio, muestra un ícono de carpeta aunque todavía no tenga hijos. |
renderTitle | ((state: { isExpanded: boolean; level: number; }) => ReactNode) | - | Contenido personalizado del título, con el estado de la fila. |
textValue | string | - | Texto para la búsqueda por tipeo y los lectores de pantalla cuando el título no es texto simple. |
TreeSection props
Un grupo de elementos con un encabezado dentro de un Tree.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
aria-label | string | - | |
className | string | - | |
id | Key | - | |
items | Iterable<T> | - |
TreeHeader props
El título de un TreeSection.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
className | string | - |
Especificaciones
Generado desde el código: las variantes de los tipos, los estados y tokens del CSS, y los patrones de motion que aplican. Las grillas muestran el componente real en ambos temas; los números se miden en la página.
Tree
- Variantes
sizesmmdlgvariantsolidsubtle- Estados
- Keyboard focusSelectedHoverDrop target
- Oscuro y claro
- Cada color viene de tokens del tema, así que sigue a data-theme (y a presets como Graphite) en la página o en cualquier contenedor. El contraste se revisa en ambos temas.
- Clases para estilos
.alea-tree-loading.alea-tree-empty.alea-tree.alea-tree-wrap- Atributos data
data-size=smdata-size=lgdata-variant=soliddata-checkabledata-lines
TreeItem
- Estados
- HoverPressedSelectedKeyboard focusDisabledExpandedDraggingDrop target
- Motion
- expandmorphtintmore
- Oscuro y claro
- Cada color viene de tokens del tema, así que sigue a data-theme (y a presets como Graphite) en la página o en cualquier contenedor. El contraste se revisa en ambos temas.
- Clases para estilos
.alea-tree-item.alea-tree-row.alea-tree-drag.alea-tree-chevron.alea-tree-spin.alea-tree-spacer.alea-check.alea-table-check.alea-check-box.alea-tree-icon.alea-tree-rename.alea-tree-text- Atributos data
data-hrefdata-descriptiondata-variant=soliddata-checkabledata-size=lgdata-linesdata-focus-visible-within
TreeSection
- Oscuro y claro
- Cada color viene de tokens del tema, así que sigue a data-theme (y a presets como Graphite) en la página o en cualquier contenedor. El contraste se revisa en ambos temas.
- Clases para estilos
.alea-tree-section
TreeHeader
- Oscuro y claro
- Cada color viene de tokens del tema, así que sigue a data-theme (y a presets como Graphite) en la página o en cualquier contenedor. El contraste se revisa en ambos temas.
- Clases para estilos
.alea-tree-header
Accesibilidad
- Un treegrid: cada fila dice su nivel, su posición y si está abierta (aria-expanded), elegida o marcada.
- Las casillas a medio marcar se anuncian como mixtas.
- Los botones dentro de una fila (end) se alcanzan con flechas y Tab, sin salir del árbol.
- Arrastrar y soltar funciona con teclado: Tab hasta el asa, Enter para tomar, flechas para elegir dónde, Enter para soltar.
- Se anuncia una fila de carga mientras cargan los hijos.
- Renombra con F2: el campo toma el nombre de la fila como etiqueta; Enter guarda, Escape cancela y el foco vuelve a la fila.
Teclado
| Tecla | Acción |
|---|---|
| Flecha abajo / Arriba | Fila visible siguiente o anterior |
| Flecha derecha | Abre la fila, o va a su primer hijo |
| Flecha izquierda | Cierra la fila, o va a su padre |
| Inicio / Fin | Primera o última fila |
| Enter | Ejecuta la acción de la fila (la abre con expandOnClick) |
| Espacio | Elige o marca la fila |
| Shift + flecha | Amplía la selección (múltiple) |
| ⌘A / Ctrl+A | Elige todo (múltiple) |
| F2 | Renombra la fila (con onRename) |
| Escribe una letra | Salta a la siguiente fila que empieza con ella |
Qué hacer y qué evitar
Hacer
- Pasa data cuando necesitas casillas, carga diferida, filtro, arrastrar y soltar o renombrar; los TreeItem en JSX bastan para un árbol estático.
- Mantén los árboles poco profundos: tres o cuatro niveles. Los más profundos cuestan recorrerlos en un teléfono.
- Usa checkStrictly cuando un padre y sus hijos significan cosas distintas (permisos).
- Carga las ramas grandes con loadChildren, y virtualiza pasadas unas miles de filas.
- Usa size="lg" cuando la gente usa el árbol con el dedo; las pantallas táctiles ya tienen filas de 44 px.
Evitar
- No uses un árbol para una lista plana: usa ListView.
- No escondas la única forma de hacer algo detrás de un doble clic; F2 y una acción de menú también deben renombrar.
- No pongas un campo de formulario en una fila: abre un diálogo.
- No mezcles casillas y selección simple en el mismo árbol.