Saltar al contenido
menumenu tanreiexpand_morecontrasttranslate
tanreiexpand_more
Primeros pasosWebReactSwiftUIJetpack ComposeFlutterReact NativePreajustesTu propio sistema de diseñoUsar Tanrei con agentes de IAMarcaTokens de diseñoSistemas de diseño y personalizaciónTheme StudioColorTipografíaIconosFormaElevaciónMovimientoEstados de interacciónComportamientoDiseño de páginaAccesibilidadTextosTokens de colorTokens de la escala tipográficaTokens de formaTokens de elevaciónTokens de movimientoTokens de estadoTokens de espacio y de medidaComponentesBotónBotón de acción principalBotón segmentadoGrupo de botonesBotón con menúBarra de herramientasBotón de copiarCasilla de verificaciónBotón de opciónInterruptorChipMenúControl deslizanteCampo de control deslizanteCalendarioDateTimePickerGrupo de camposGrupo de botones de opciónGrupo de casillas de verificaciónSelectCampo de selecciónBarra de menúsSubida de archivosSelector de archivos AvanzadoZona de soltar archivosEntrada de texto AvanzadoCampo de textoCampo de chipsCampoCuadro combinado AvanzadoCampo de cuadro combinadoEntrada numérica AvanzadoCampo numéricoEntrada de color AvanzadoCampo de colorEntrada de código de un solo uso AvanzadoCampo de código de un solo usoEntrada de texto incrustada AvanzadoCuadro de redacción de chatTarjetaDivisorCapa modal AvanzadoDiálogoListaFila de listaHoja inferiorHoja lateralCarruselBloque de códigoTablaPopoverPasosAcordeónLista de descripcionesFiguraEstructura de la aplicaciónCabecera de páginaVista de árbolLínea de tiempoVista previa de imágenesTirador de tamañoMarco redimensionableÁrea de desplazamientoInsigniaIndicador de progresoMedidorContador animadoIndicador de cargaSnackbarTooltipAtajo de tecladoTagCódigo en líneaCalloutAvatarEstado vacíoGrupo de tagsEsqueletoElemento de archivoMuestraTexto en marquesinaPestañasVista de pestañasBarra de la aplicaciónBarra de navegaciónPanel de navegaciónBúsquedaEnlacePaginaciónEnlaces anterior y siguienteIndicador de pasosRuta de navegaciónTabla de contenidoTarjeta de enlaceMenú FABEstadoCómo se construye TanreiCómo contribuirLicencia y atribución
InicioComponentesVista de árbol

Vista de árbol

Una jerarquía de elementos que se abren y se cierran. Las filas empiezan más adentro en cada nivel, con un chevron al inicio de cada fila que contiene otras. Solo se lee y se abre, o bien en ella se eligen uno o varios elementos, y es una sola parada en el orden del foco.

content_copyVer en Markdown
Categoría
Contención
Tokens
comp.tree-view
Nivel
Base

Descripción general

Web
tanrei-tree-view
schedule
SwiftUI
TanreiTreeView
radio_button_unchecked
Jetpack Compose
TanreiTreeView
radio_button_unchecked
Flutter
TanreiTreeView
radio_button_unchecked
React Native
TreeView
radio_button_unchecked

Generado a partir de docs/status/status.json, specs/tree-view.spec.json

Un árbol de archivos: abre una carpeta con su fila, o con las teclas de flecha

  • tokens/fuente de verdad, editada a mano
    • ref/
    • sys/
    • comp/
    • tanrei.resolver.json
  • packages/
    • web/src/generated/tokens.css
    • react-native/src/generated/tokens.ts

Una vista de árbol muestra una estructura que una persona recorre o en la que elige: los archivos de un proyecto, los tokens de un sistema de diseño, las carpetas de un producto. Una fila que contiene otras tiene un chevron y se abre y se cierra. Con selection se eligen uno o varios elementos, y el árbol te dice cuáles.

No es navegación. Los lugares de un producto son un panel de navegación, los encabezados de una página son una tabla de contenido, y el contenido plegado es un acordeón. Esos conservan enlaces y botones, cada uno con su propia parada en el orden del foco. Un árbol es una sola parada, que se recorre con las teclas de flecha, porque puede contener miles de filas.

En la web es <tanrei-tree-view> alrededor de tus propias listas anidadas. Las listas se quedan en el documento, así que, donde no se ejecuta ningún script, la página muestra toda la jerarquía como una lista anidada. Las demás plataformas todavía no lo han implementado.

Uso

<link rel="stylesheet" href="@tanrei/web/icons.css" />
<link rel="stylesheet" href="@tanrei/web/tree-view.css" />

<tanrei-tree-view label="Archivos del proyecto" selection="single" value="src/index.ts">
  <ul>
    <li data-value="src" data-open>
      <span>
        <span class="tanrei-icon" aria-hidden="true">folder</span>
        <bdi>src<small data-supporting-text>lo que se publica</small></bdi>
        <span data-trailing-text>12 archivos</span>
      </span>
      <ul>
        <li data-value="src/index.ts"><span><bdi>index.ts</bdi></span></li>
      </ul>
    </li>
    <li data-value="node_modules" data-expandable><span><bdi>node_modules</bdi></span></li>
  </ul>
</tanrei-tree-view>

<!-- Un árbol que filtra sus filas: "/" en una fila lleva al campo que hay encima. Las palabras son tuyas. -->
<tanrei-tree-view label="Archivos del proyecto" filterable filter-label="Filtrar archivos" filter-placeholder="Filtrar"
  filter-count-text="Coincidencias: {count}" filter-empty-text="Sin coincidencias" filter-clear-label="Borrar">
  <ul>…</ul>
</tanrei-tree-view>

<script type="module">
  import '@tanrei/web/components/tree-view';

  const tree = document.querySelector('tanrei-tree-view');
  tree.addEventListener('change', (event) => showFile(event.detail.value));
  tree.addEventListener('toggle', (event) => {
    if (event.detail.open && event.target.dataset.expandable !== undefined) loadItemsInto(event.target);
  });
</script>
import { TreeView } from '@tanrei/react';
import '@tanrei/web/tree-view.css';

<TreeView label="Archivos del proyecto" selection="single" value={path} onChange={(event) => setPath(event.detail.value)}>
  <ul>
    {folders.map((folder) => (
      <li key={folder.path} data-value={folder.path} data-open={folder.open ? '' : undefined}>
        <span><bdi>{folder.name}</bdi></span>
        <ul>
          {folder.files.map((file) => (
            <li key={file.path} data-value={file.path}><span><bdi>{file.name}</bdi></span></li>
          ))}
        </ul>
      </li>
    ))}
  </ul>
</TreeView>

@tanrei/web/tree-view.css dibuja el árbol antes de que se ejecute ningún script, y nada se mueve cuando el script se carga. El chevron es un glifo del conjunto de iconos y necesita la fuente de iconos.

Qué escribes tú

Parte En la web
El nombre del árbol El atributo label, en el idioma de tu producto.
Un elemento Un <li>. Su primer elemento hijo es su fila: un <span> o un <div>.
La etiqueta El texto de la fila, en un solo elemento: <bdi>. Puede incluir contenido en línea, como código en línea.
El texto de apoyo Un elemento con data-supporting-text, dentro del elemento de la etiqueta, después de la etiqueta.
El icono Un .tanrei-icon en la fila, que contiene el nombre del glifo. El árbol no tiene un glifo propio para una carpeta ni para un archivo.
El icono abierto data-open-icon en el .tanrei-icon de un padre: el glifo que se dibuja mientras está abierto, como folder_open junto a folder.
El contenido final Un elemento con data-trailing en la fila: un tag, una muestra de color. Se coloca y no se le aplica ningún estilo.
El texto final Un elemento con data-trailing-text en la fila: un recuento, un tamaño, un valor. Una sola línea.
Los elementos propios de un elemento Un <ul> después de la fila, dentro del mismo <li>.

Una fila también puede contener su etiqueta como texto simple, sin un <bdi> alrededor. Usa el <bdi> donde la fila tiene un texto de apoyo, y donde la dirección de un nombre puede ser distinta de la de la página, como un nombre de archivo en una página en árabe.

En el <li> Significado
data-value Lo que identifica al elemento. Sin uno, no se puede elegir. Único dentro del árbol.
data-open Un padre muestra sus elementos. El árbol lo pone y lo quita cuando la persona abre o cierra el padre.
data-expandable El elemento va a contener elementos que todavía no has dado. Recibe un chevron; da sus elementos cuando toggle diga que se abrió.
data-loading Estás obteniendo sus elementos. Mientras está abierto se dibuja debajo de él una fila de carga, con el loading-label del árbol.
data-disabled La persona no puede elegirlo, abrirlo ni cerrarlo. Las teclas de flecha siguen llegando a él.
data-supporting-position inline pone su texto de apoyo después de su etiqueta, en su línea. Sin él, la nota va debajo de la etiqueta.
Evento Cuándo detail
change La persona cambió la selección. En el árbol. value (única) o values (múltiple), después del cambio
toggle La persona, o la búsqueda en la página del navegador, abrió o cerró un padre. En el <li>; se propaga. open
rename La persona dio un nombre nuevo a un elemento en su sitio. En el <li>; se propaga. label (el nombre nuevo, sin espacios en los extremos) y previous
create La persona dio nombre al elemento nuevo que pidió create(). En el árbol. label, parent, within y after (el <li> en el que entra y el que lo precede, o null)
filterchange La persona cambió el texto del filtro: al escribir, borrar, pegar, con el botón de borrar o con Escape. En el árbol. value, el texto nuevo (filter-value ya lo tiene)

Ninguno de estos eventos se emite por un cambio que haces tú.

Método Qué hace
edit(li) Abre el campo sobre el nombre de un elemento, como F2. Solo mientras el árbol es editable.
create({ parent, icon }) Añade una fila nueva junto al elemento seleccionado, con un campo vacío para darle nombre. Devuelve si la añadió.
focusFilter() Lleva el foco al campo del filtro, con su texto seleccionado. Solo mientras el árbol es filterable. Asígnalo a una tecla tuya para toda la ventana.

Especificaciones

Un elemento elegido: la fila elige, el chevron abre

  • Referencia212
    • palette.neutral
  • Sistema388
    • color64
      • primary#1f1f1f
      • on-primary#ffffff
      • outline-variant#d4d4d4
    • space19

Anatomía

Parte Descripción
1 tree The column that holds the rows, named by its label. It draws no fill, no edge and no space of its own, and does not scroll. One stop in the focus order.
2 filter The filter field, while filterable is true and the tree has items: a Text input of type search above the first row, with the search glyph at its start and a clear button at its end while it holds text. Pinned at the top of the scrolling box the tree stands in, above the pinned rows. A stop of its own, before the tree.
3 filter.status The line at the top of the results while a filter is applied: how many rows match, in the product's filterCountText, unless filterCountHidden; or, where no row matches, the product's filterEmptyText. Takes no focus and no state.
4 item One thing in the hierarchy (an item of the item kind): its row and, while it is a parent and open, the rows of the items it holds, which begin one level further in.
5 container An item's row: the box that carries hover, focus and press and the selected fill. With highlight indented it begins further from the start edge for each level; with highlight full it spans the tree's width. It ends at the tree's end edge; the hit area is the tree's whole width.
6 chevron The mark of a parent's open and closed, where chevron says: at the start of the row (the icon set's chevron_right, pointing toward the end of the line while closed and turned a quarter turn to point down while open) or at its very end, after the trailing content (the icon set's expand_more, turned a half turn while open, as the navigation drawer's and the accordion's). A leaf keeps the box empty, so that the names (or the values) of one level stand in one column. None where chevron is none, or where the tree is not expandable. Hidden from assistive technology, which is given the state in words.
7 icon · opcional A glyph of the system's icon set before the label, by name: what kind of thing the item is (a folder, a file, a group); a parent may name a second glyph for while it is open (folder_open beside folder). Where no icon is named, its room is kept while another item of the level has one (iconSpace). The product's choice; decorative.
8 label The item's name and its accessible name. One line, cut with an ellipsis where it does not fit (the whole name in a tooltip); with labelWrap it wraps instead and is never cut.
9 supporting-text · opcional A few words about the item: below the label (supportingPosition below, the default) or after it on its line (inline), quieter than the label. One line, cut with an ellipsis; with supportingWrap it wraps instead.
10 trailing · opcional The trailing slot's content at the end of the row: a tag, a swatch, a mark that the item changed. Not interactive; part of the row.
11 trailing-text · opcional A short value at the end of the row, after the trailing content: a count, a size, the present value. One line.
12 guide · opcional A hairline down from an open parent beside the rows it holds, under the parent's first leading mark, where guides says: always, or while the pointer is over the tree or focus is in it. Decorative.
13 loading-row · opcional A row one level further in under an open parent that is fetching what it holds: a loading indicator and the words the product gives. Not an item: it takes no focus and cannot be chosen.
14 full-text-tooltip · opcional The whole of a name or a note that is cut (TRV-50): a plain tooltip with the label, or a rich one with the label as its title and the supporting text, beside the row on hover and on keyboard focus. Only while something is cut.
15 pinned-row · opcional The row of an open parent above the rows that are shown, held at the top of the scrolling box while what it holds scrolls under it (stickyParents): the same row, with an opaque fill and a hairline under the last one (TRV-53).
16 edit-field · opcional While an item's name is being edited, or a new item named: an Embedded text input on one line in the place of the label and the supporting text, inside a box the tree draws with the focus indicator around it. The rest of the row stays as it was.
17 new-row · opcional A row the tree adds for the time a new item is being named: at the level of the selected item, after its rows, with a closed chevron for a parent, the glyph the product names and the edit field. Not an item: it is gone when the name is given or given up.
18 focus-ring Gap-then-ring indicator shown for keyboard focus of an item, drawn inside its row's container.

Propiedades

Propiedad Tipo Valor predeterminado Descripción
label string "" The accessible name of the tree: what the hierarchy is ("Project files", "Every token"). Required: a tree is one stop in the focus order and is announced by this name.
selection none | single | multiple "none" Whether people choose items. none: a tree that is read and opened — a figure of a file system in a page, a structure to look through; its leaves answer nothing and its parents open and close. single: one item is chosen (the file shown in the pane beside the tree, the token being edited). multiple: any number are chosen, each by itself. An item is chosen by its value; an item without one cannot be chosen.
value string null The value of the selected item while selection is single; null selects none. The tree sets it when an item is chosen and emits change; the product may also set it.
values strings The values of the selected items while selection is multiple: a list of strings (the platforms take a set). An empty list selects none.
density regular | compact "regular" How much room a row takes, in a table's and an accordion's words: the row's least height, its paddings and its glyphs' size, and never the gap between the icon and the label (iconGap). regular (a 48 row with a 14 label in the default system, a navigation drawer's row) is the tree of a product used by touch as well as by pointer. compact (a 32 row with a 13 label, a table's compact row) is for a tool used with a pointer, where hundreds of rows are looked through, and for a small tree inside a page of text. For touch a row is never lower than the touch target in either. A design system may add values.
chevron start | end | none "start" Where a parent's chevron stands. start: at the start of its row, before the icon (a file tree, the tree pattern). end: at the very end of the row, after the trailing content and the trailing text (a settings tree, the navigation drawer's place). none: no chevron; a parent that names an icon and an open icon shows open and closed by its glyph, which a press opens and closes, and the arrow keys always open and close (TRV-44).
expandable boolean true Whether parents open and close at all. false: every parent is shown open, no chevron is drawn, nothing toggles, and no row is exposed as expanded or collapsed — a structure that is always shown whole (an outline, a table of contents of a document). An item's own expandable is read only while this is true.
guides none | shown | hover "none" Hairlines down from each open parent beside the rows it holds, for a deep tree where the indent alone no longer shows which rows belong together. none: no lines. shown: always. hover: while a pointer is over the tree or keyboard focus is in it, faded in and out. Decorative. On the web the bare attribute, and true, are shown.
indent number null How far each level begins further in than the one above it. null (auto, the default): a child's start stands where its parent's label begins, so the step follows what the parent's row holds before its label — the chevron at the start, the icon or the icon's room. A number: that many points (px, dp), the product's explicit choice; 0 sets no level in, and then no guide is drawn. A design system sets what auto rests on through the parts' tokens and the level's indent token.
iconSpace auto | always | never "auto" Whether a row without an icon keeps the icon's room, so that the labels of a level stand in one column. auto: it does while another item of the same level has an icon. always: every row keeps it. never: only a row with an icon has the room.
iconGap number null The room between the icon (or its kept room) and the label, in points. null (auto): comp.tree-view.icon.gap, which no density changes. A number is the product's explicit choice.
highlight indented | full "indented" How far a row's fill reaches — the selected fill and the hover and press layers, and the focus ring with them. indented: from where the row's level begins to the tree's end edge, so that the fill shows the level. full: from the tree's start edge to its end edge, as file browsers draw it. The hit area is the whole width either way.
labelWrap boolean false false: a label is one line, cut with an ellipsis where it does not fit, and the whole of it is shown in a tooltip on hover and on keyboard focus while it is cut. true: it wraps onto as many lines as it needs and is never cut. The accessible name is the whole label either way.
supportingWrap boolean false As labelWrap, for the supporting text: one line cut with an ellipsis (the whole in the tooltip), or wrapping. A supporting text beside the label (inline) shares the label's line and follows labelWrap.
stickyParents boolean true Keeps the rows of the open parents that the rows at the top of the scrolling box belong to pinned at its top while what they hold scrolls under them, as an editor's sticky scroll does, so that a person deep in a long tree sees where they are. The pinned rows are the rows themselves and work as they do. On by default in the tree view (off in the navigation drawer, which is short). A tree in no scrolling box pins nothing.
stickyMax number 2 The most rows pinned at once, one per level; where more parents are above what is shown, the innermost of them are the ones pinned. 0 pins none.
editable boolean false Lets people rename items in place: a double-click on a row's label, or F2 on a focused row, puts the label into a text field; Enter or leaving the field gives the new name, Escape gives it up. The tree changes no label itself: it emits the item's rename and the product sets the label. New items are named the same way whatever this says, in a row the product asks for (TRV-48).
editLabel string "" The accessible name of the field in which a name is edited or a new item named ("Name"). Tanrei ships no words of its own. Required where editable is true or a new item may be asked for.
loadingLabel string "" The words of a loading row ("Loading…"), drawn beside its loading indicator and used as the indicator's name. Tanrei ships no words of its own. Required where any item may be loading.
filterable boolean false Draws a filter field above the rows: what a person types there narrows the tree to the rows whose label holds it, opening for the time being the groups that hold them, and the tree comes back as it was when the field is emptied. Off by default: a product that filters on a server, ranks, or matches in another way leaves it off and gives the tree the items that match, as before.
filterValue string "" The filter text: what the filter field holds. The tree sets it when the person types and emits filterChange; the product may set it too (a filter given back when a page is rendered again). Empty, or only white space, applies no filter.
filterLabel string "" Names the filter field for assistive technology, in the product's language: what it narrows ("Filter navigation", "Filter files"). Required while filterable is true. It names this one field, so it is not one of the product's words set once.
filterPlaceholder string "" The hint the filter field shows while it is empty ("Filter"), in the product's language. Never a replacement for filterLabel. The product's: Tanrei has no words for it. Empty reads the product's words; with neither, the field shows no hint.
filterEmptyText string "" What the tree draws at the top of the results and says while a filter is applied and no row matches ("No matches"), in the product's language. The product's: Tanrei has no words for it. Empty reads the product's words; with neither, nothing is drawn in its place and it is reported.
filterCountText string "" What the tree draws quietly at the top of the results (TRV-65) and says to assistive technology once the result of a filter has settled (TRV-66), with {count} where the number of rows that match goes ("Matches: {count}"), in the product's language. filterCountHidden leaves it undrawn and still said. The product's: Tanrei has no words for it. Empty reads the product's words; with neither, no count is drawn or said and it is reported.
filterCountHidden boolean false Does not draw the count at the top of the results (TRV-65); it is still said to assistive technology (TRV-66). The words for a filter that matches nothing are drawn either way. A tree whose results are counted elsewhere on the screen, or where the rows left say enough, turns it on.
filterClearLabel string "" The accessible name of the filter field's clear button ("Clear"), in the product's language. Required while the field can hold text. Empty reads the product's words.
filterShortcut strings / The key that, pressed while focus is on a row, moves focus to the filter field, in the keyboard shortcut component's key names, one chord (["/"], the default). It is a key of the tree's rows, as F2 is: the tree listens for it nowhere else and draws no hint of it (TRV-62). A product that wants a key for the whole window binds it and asks the tree to focus its filter (TRV-63). An empty list binds nothing, and "/" is then typed as any other character (TRV-23).

Eventos

Evento Descripción
change The user changed the selection — by a press, a key, a range or select-all; carries value (single) or values (multiple) after the change, once per gesture.
create The user named the new item in the row the product asked for (TRV-48): carries its label (not empty, with no white space at its ends), whether it is a parent or a leaf, the item it goes under (none for the first level) and the item it follows (none where it is the first). Emitted exactly once; the tree takes its own row away as it emits it, and the product adds the item.
filterChange The person changed the filter text — typing, deleting, pasting, dictating, an input method committing text, the clear button or Escape; carries the new text. Not emitted when the product sets filterValue.

Elementos

Los tipos de elemento que el componente repite. Un fixture enumera sus elementos en orden; cada plataforma nombra cada tipo según su propio estilo.

item · grupo: contiene elementos

One thing in the hierarchy: a row with a label and, where it holds other items, a chevron that opens and closes them. An item that holds items, or says it will, is a parent; every other item is a leaf. The fixture's content is unused.

Propiedad Tipo Valor predeterminado Descripción
value string "" What identifies the item: the tree's value (single) or values (multiple) select the item whose value they hold, and change carries it. Unique within the tree. Empty, the item cannot be chosen: a press on its row opens or closes it where it is a parent and does nothing where it is a leaf.
label string "" Its name, drawn in its row and used as its accessible name. Plain text; the label slot takes its place where the product needs inline content. Required unless the label slot is filled.
supportingText string "" A few words about the item ("the source of truth, edited by hand"), drawn below the label or beside it as supportingPosition says, and read as the item's description. Empty draws the label alone.
supportingPosition below | inline "below" Where the supporting text stands: below the label, on a line of its own (the default), or inline, after the label on the label's line.
trailingText string "" A short value at the end of the row: a count, a size, the present value. One line; read after the supporting text as the item's description.
icon string "" The name of a glyph in the system's icon set, drawn before the label: what kind of thing the item is. The tree has no glyphs of its own for a folder or a file: the product names them. Decorative.
openIcon string "" The name of a second glyph, drawn in the icon's place while the parent is open (folder_open beside folder). Ignored on a leaf and while icon is empty. Where the tree's chevron is none, the two glyphs are what shows open and closed, and the glyph is what a press opens and closes. Decorative.
open boolean false Whether the items a parent holds are shown under its row. Set by the product for a parent that starts open; the web sets it itself when the user opens or closes the parent, and a controlled platform leaves it to the caller. Ignored on a leaf.
expandable boolean false Says that the item holds items the product has not given yet: it is drawn and exposed as a parent, with a chevron, and its toggle tells the product to give them. An item that holds items is a parent whatever this says. Read only while the tree's expandable is true.
loading boolean false Says that the product is fetching what the item holds: while the item is open a loading row is drawn under it, after any items it already holds, and the item is exposed as busy. Ignored on a leaf.
disabled boolean false Makes it unavailable: it keeps its place and its open, draws its disabled look, and cannot be chosen, opened or closed by the user. The arrow keys still reach it, and the items it shows keep their own disabled.
Slot Descripción
label The product's own label content in place of the label prop: text with inline content (a code span, a part of the name marked as a match). The tree draws it in the label's style and color. No control.
trailing Content at the end of the row, before the trailing text and before an end chevron: a tag, a swatch, a mark. The tree places it and gives it no style. No control; it is part of the row and is read as part of the item's description where it has text.
Evento Descripción
toggle The parent opened or closed: by the user from its chevron, its row or the keyboard, or by the platform's search finding text under it; carries its new open state. Emitted exactly once per change, when the change begins. The moment to give the items of a parent that is expandable.
rename The user gave the item a new name in place (TRV-46): carries the new label — not empty, with no white space at its ends, and not the label it had — and the label it had. Emitted exactly once per name given. The tree draws the label it had until the product sets the new one; a product that refuses the name leaves the label as it is.
Especificación Web SwiftUI Jetpack Compose Flutter React Native
Elemento li TanreiTreeItem TanreiTreeItem TanreiTreeItem TreeItem
value · Propiedad data-value tag value value value
label · Propiedad (row text) title label label label
supportingText · Propiedad data-supporting-text supportingText supportingText supportingText supportingText
supportingPosition · Propiedad data-supporting-position supportingPosition supportingPosition supportingPosition supportingPosition
trailingText · Propiedad data-trailing-text trailingText trailingText trailingText trailingText
icon · Propiedad tanrei-icon icon icon icon icon
openIcon · Propiedad data-open-icon openIcon openIcon openIcon openIcon
open · Propiedad data-open isExpanded expanded expanded open
expandable · Propiedad data-expandable isExpandable expandable expandable expandable
loading · Propiedad data-loading isLoading loading loading loading
disabled · Propiedad data-disabled disabled enabled enabled disabled
toggle · Evento toggle isExpanded onExpandedChange onExpansionChanged onToggle
rename · Evento rename onRename onRename onRename onRename
Notas A native <li> whose first child element is its row (a <span> or a <div>) and whose next child, where it is a parent, is a <ul> of its items: <li data-value="src" data-open><span><i class="tanrei-icon">folder</i>src <small data-supporting-text>what is published</small> <span data-trailing-text>12 files</span></span><ul>…</ul></li>. The row's text is the label (the label slot: text and inline content); inside the row, an element with data-supporting-text holds the supporting text, one with data-trailing the trailing slot's content and one with data-trailing-text the trailing text; a .tanrei-icon element first in the row is the icon. data-open, data-expandable, data-loading and data-disabled are boolean attributes of the <li>, which the element mirrors as aria-expanded, aria-busy and aria-disabled; the element sets and removes data-open itself when the user opens or closes the parent. toggle is dispatched on the <li> and bubbles, with detail.open. data-open-icon is an attribute of the .tanrei-icon element (<i class="tanrei-icon" data-open-icon="folder_open">folder</i>), so that the stylesheet draws the open glyph before the element is defined. rename is dispatched on the <li> and bubbles, with detail.label and detail.previous. TanreiTreeItem(_ title: String, supportingText: String = "", trailingText: String = "", icon: String? = nil, isExpanded: Binding<Bool>, isExpandable: Bool = false, isLoading: Bool = false) { children }, tagged with .tag(value); a leaf has an initializer without the binding and the children. Toggling writes the binding, as TanreiNavigationDrawerGroup and TanreiAccordionItem do. A second initializer takes the label as a @ViewBuilder and trailing: as another (the slots). disabled follows .disabled(_:). TanreiTreeItem(label, value = "", expanded = false, onExpandedChange = {}, supportingText = "", trailingText = "", icon = null, expandable = false, loading = false, enabled = true, labelContent = null, trailing = null) { children } in the tree's scope, with the names of TanreiNavigationDrawerGroup and TanreiAccordionItem. enabled is the inverse flag; labelContent and trailing are the slots. TanreiTreeItem(label:, value: '', supportingText: '', trailingText: '', icon:, expanded: false, onExpansionChanged:, expandable: false, loading: false, enabled: true, labelWidget:, trailing:, children: const []), a description of an item and not a widget, as the list's items are; controlled, with the callback name of TanreiNavigationDrawerGroup. labelWidget and trailing are the slots. <TreeItem label="src" value="src" open={…} onToggle={…}>…</TreeItem>, with the names of NavigationDrawerGroup and AccordionItem; controlled when open is given, and defaultOpen otherwise. The label slot is the labelContent prop and the trailing slot the trailing prop; its items are children.

Estados

Comportamiento

Requisitos en formato EARS. Cada implementación de plataforma se prueba contra estos identificadores. El texto de los requisitos se muestra tal como está en la especificación, en inglés.

ID Requisito
TRV-1 THE tree view SHALL lay out the rows of its items in one column, in the order given and depth first: an item's row and then, WHILE the item is a parent and open, the rows of the items it holds, before the row of the item that follows it. It SHALL be as wide as the layout it is placed in gives it, with its start edge on the start edge of what is around it; SHALL bring no outer space, no fill and no edge of its own (PRS-15: the space between it and its neighbours is its container's); SHALL have no minimum width, no maximum width and no height of its own; and SHALL NOT scroll: it is as tall as the rows it shows, and the product places a long tree in a scrolling box of its own, at whose top the rows of the open parents above what is shown are pinned (TRV-53). Rows SHALL touch: there is no space and no line between two rows.
TRV-2 THE tree view SHALL draw each item's row as a container at least as high as its density gives (comp.tree-view.container.height.regular for regular and comp.tree-view.container.height.compact for compact) and growing with its text, with corners comp.tree-view.container.shape, padded at its start and end by comp.tree-view.container.padding-inline.regular for regular and comp.tree-view.container.padding-inline.compact for compact and above its first line and below its last by comp.tree-view.container.padding-block.regular for regular and comp.tree-view.container.padding-block.compact for compact. Inside it SHALL lay out, from the start: the chevron's box WHILE chevron is start (TRV-4); the icon, or its kept room (TRV-5, TRV-43); the text, which takes the remaining width and holds the label and the supporting text (TRV-6, TRV-7); the trailing slot's content, where there is any; the trailing text, where the item has one (TRV-7); and the chevron's box WHILE chevron is end (TRV-4). Between the icon (or its room) and the text it SHALL keep iconGap — comp.tree-view.icon.gap while iconGap is null, the same in every density — and between each other two of them comp.tree-view.container.gap.regular for regular and comp.tree-view.container.gap.compact for compact. THE tree view SHALL centre the chevron, the icon, the trailing content and the trailing text on the label's first line and keep them there however tall the text grows, and any height a row has beyond its text SHALL be shared equally above and below it.
TRV-3 THE tree view SHALL show an item's depth by where its row's content begins: the content of an item of the first level SHALL begin where the tree's start edge and its padding put it, and the content of every deeper item SHALL begin one step further from that edge than its parent's. WHILE indent is null (auto) the step SHALL be the length from the parent's content start to where the parent's label begins — the chevron's box and a gap WHILE chevron is start and the tree is expandable, plus the icon's box (or its kept room, TRV-43) and iconGap WHERE the parent's row has an icon or keeps its room — so that a child's start stands where its parent's label begins, and comp.tree-view.level.indent.regular for regular and comp.tree-view.level.indent.compact for compact where the parent's row holds nothing before its label; WHILE indent is a number the step SHALL be that number of points, and 0 SHALL set no level in. WHILE highlight is indented the row's container (its fill, its state layer and its focus indicator) SHALL begin where its content's level begins, its padding before the content; WHILE highlight is full every container SHALL begin at the tree's start edge (TRV-51). Every container SHALL end at the tree's end edge. WHILE the steps of an item's levels would begin its label past half of the tree's width THE tree view SHALL begin that row no further in than puts its label at half of the width, so that a deep tree in a narrow window keeps half of its width for names, SHALL still expose the item's true level (TRV-32), and in debug builds SHALL report the depth once.
TRV-4 WHILE the tree is expandable and chevron is start or end THE tree view SHALL keep a box of comp.tree-view.chevron.size.regular for regular and comp.tree-view.chevron.size.compact for compact in every row, at its start WHILE chevron is start and at its very end — after the trailing content and the trailing text — WHILE chevron is end. In the row of a parent — an item that holds items, or whose expandable is true — it SHALL draw in that box, in the chevron color of the item's condition (comp.tree-view.unselected.chevron.color, comp.tree-view.selected.chevron.color), with sys.icon.family.unselected and sys.icon.fill.unselected, sys.icon.weight and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max: at the start, the glyph chevron_right as the icon helper draws it WHILE the parent is closed, pointing toward the end of the line, turned a quarter turn to point down WHILE it is open; at the end, the glyph expand_more WHILE closed, turned a half turn WHILE open. In the row of a leaf it SHALL draw nothing in the box and keep the box, so that the labels (at the start) or the trailing texts (at the end) of one level stand in one column. WHILE chevron is none, or the tree is not expandable, THE tree view SHALL keep no chevron's box. The chevron, and the icon of an item that names an open icon (TRV-5), SHALL be the only things about a row that show whether its item is open: the container, the label and the texts SHALL be the same open and closed. THE tree view SHALL keep the chevron from assistive technology, which is given the state in words (TRV-32), and a disabled parent SHALL keep its chevron.
TRV-5 WHILE an item's icon is not empty THE tree view SHALL draw that glyph of the system's icon set after the chevron's box (or first, where there is none), in a box of comp.tree-view.icon.size.regular for regular and comp.tree-view.icon.size.compact for compact, in the icon color of the item's condition (comp.tree-view.unselected.icon.color, comp.tree-view.selected.icon.color), with the family and fill of that condition (sys.icon.family.selected and sys.icon.fill.selected for a selected item, sys.icon.family.unselected and sys.icon.fill.unselected otherwise), sys.icon.weight and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max, and SHALL keep it from assistive technology. WHILE icon is empty THE tree view SHALL draw no glyph and keep its room as TRV-43 says. THE tree view SHALL have no glyph of its own for any kind of item. WHILE an item is a parent, is open and its openIcon is not empty THE tree view SHALL draw the openIcon glyph instead of icon, in the same place, box, color, family and fill, and SHALL draw icon again WHEN the parent closes; the glyph SHALL change at once, WHEN the change of open begins, with no motion of its own. THE tree view SHALL ignore openIcon on a leaf and WHILE icon is empty, and SHALL draw icon alone WHILE openIcon is empty.
TRV-6 THE tree view SHALL draw an item's label in the text style of its density (comp.tree-view.label.typescale.regular for regular and comp.tree-view.label.typescale.compact for compact) and the label color of its condition (comp.tree-view.unselected.label.color, comp.tree-view.selected.label.color). WHILE labelWrap is false the label SHALL be one line, cut at the end of its own direction with an ellipsis where it does not fit, and shown whole in the tooltip of TRV-50 while it is cut; WHILE labelWrap is true it SHALL wrap and SHALL never be cut, and a name with no place to break (a path, an identifier) SHALL break where it must rather than widen the tree. The accessible name SHALL be the whole label either way. WHERE the item's label slot holds content THE tree view SHALL draw that content in the label's place, size and color instead of the label, on one line or wrapping as labelWrap says, and SHALL leave a code span in it its own typeface. The label slot and the trailing slot SHALL hold no control: IF either holds a link, a button or a field THE tree view SHALL still render it and in debug builds report that a row holds no control; a platform that cannot inspect its slot content SHALL state the rule in its README and docs page.
TRV-7 WHILE an item's supportingText is not empty THE tree view SHALL draw it in comp.tree-view.supporting-text.typescale and the supporting-text color of the item's condition (comp.tree-view.unselected.supporting-text.color, comp.tree-view.selected.supporting-text.color): WHILE supportingPosition is below, on a line of its own under the label, starting where the label starts — one line cut with an ellipsis (the whole in the tooltip of TRV-50) WHILE supportingWrap is false, wrapping and never cut WHILE it is true; WHILE supportingPosition is inline, after the label in the same block of text and comp.tree-view.container.gap.regular for regular and comp.tree-view.container.gap.compact for compact after the label's last word, on the label's baseline, sharing the label's line and its cut (TRV-6). WHILE an item's trailingText is not empty THE tree view SHALL draw it on one line, in comp.tree-view.trailing-text.typescale and the trailing-text color of the item's condition (comp.tree-view.unselected.trailing-text.color, comp.tree-view.selected.trailing-text.color), after the trailing slot's content and before an end chevron; it SHALL NOT wrap, and WHILE it would take more than half of the row's inner width it SHALL be cut at the end of its own direction with an ellipsis, so that the label always keeps at least half. THE tree view SHALL give the trailing slot's content no style, and SHALL apply a disabled item's opacity to it with the rest of the row.
TRV-8 WHILE guides is shown or hover, and the step of a level is not 0 (TRV-3), THE tree view SHALL draw, for each open parent that shows at least one row under it, one line comp.tree-view.guide.width wide in comp.tree-view.guide.color, from the lower edge of the parent's row to the lower edge of the last row shown under it (the rows of its open descendants and a loading row included), centred under the parent's first leading thing: its chevron WHILE chevron is start; else its icon, where it has one; else the start of its label. The line SHALL lie in the indent of the rows it runs beside, SHALL keep its color and its full opacity in every state and condition of the rows beside it (a disabled item's opacity does not reach it), SHALL grow and shrink with the rows it runs beside as they are revealed and hidden (TRV-11), SHALL pass under a pinned row (TRV-53), SHALL be hidden from assistive technology, and SHALL take no space: a tree is laid out the same with and without guides. WHILE guides is hover THE tree view SHALL draw the lines WHILE a pointer is anywhere over the tree or keyboard focus is in it, and not otherwise, fading them in and out over comp.tree-view.motion.state-duration with comp.tree-view.motion.state-easing, at once where motion is reduced. WHILE guides is none THE tree view SHALL draw no line.
TRV-9 THE tree view SHALL draw a parent's open as the state of that parent alone: WHILE open is true the rows of the items it holds are shown under its row, and WHILE open is false they are not drawn, take no space, cannot take focus and are not exposed to assistive technology, whatever their own open says; a closed parent SHALL keep its descendants' open, so that it opens again as it was. WHEN the tree first appears it SHALL draw every parent as its open says, in its first frame, without the motion of TRV-11 and without emitting toggle. THE tree view SHALL ignore the open of a leaf. On a platform that keeps what it does not draw (the web, where the items stay in the document) THE tree view SHALL NOT remove or rebuild a closed parent's items.
TRV-10 WHEN the user presses the chevron of a parent that is not disabled, by pointer or touch, THE tree view SHALL emit that item's toggle exactly once with its new open state, SHALL NOT change the selection, and on the web SHALL set the item's open itself (a controlled platform leaves it to the caller). WHEN the user presses the row of a parent that cannot be chosen (TRV-15) anywhere, or presses Enter or Space while focus is on it, THE tree view SHALL do the same: a row that has nothing to choose opens and closes. WHEN the user presses the row of an item that can be chosen outside its chevron THE tree view SHALL change the selection (TRV-16, TRV-17) and SHALL NOT open or close it: the chevron opens and the row chooses, and one press never does both. WHILE chevron is none the press rules of TRV-44 SHALL apply in place of this one. THE tree view SHALL NOT open a parent because the pointer rests on it, and SHALL NOT open or close anything for a second press that follows the first quickly: each press is answered by itself.
TRV-11 WHEN a parent's open changes THE tree view SHALL reveal or hide the rows under it from its row downward, the rows after them moving with their lower edge, and SHALL turn its chevron (a quarter turn at the start, a half turn at the end), over comp.tree-view.motion.disclosure-duration with comp.tree-view.motion.disclosure-easing, at once where motion is reduced. The rows SHALL be laid out once, at the size they have when shown, and the motion SHALL only change how much of them is seen: no label SHALL wrap again and nothing SHALL be measured again from frame to frame. Rows that are being hidden SHALL stay drawn until the motion ends and SHALL leave the arrow keys and assistive technology when it begins. WHEN open changes again before the motion ends THE tree view SHALL go on from where the motion is toward the new state, without a jump. toggle SHALL be emitted when the change begins, not when the motion ends.
TRV-12 WHEN a parent opens or closes THE tree view SHALL keep that parent's row where it is in the view, as far as the scrolling of what holds the tree allows, and move only what follows it; it SHALL NOT scroll for any other reason of its own, and the rows of a parent that opens MAY reach below the view's edge. WHEN a parent closes, or its items are taken away, while keyboard focus is on a row under it THE tree view SHALL move focus to that parent's row; WHEN the item that has focus is removed and no parent of it closed THE tree view SHALL move focus to the row that follows it or, where none does, the row before it. WHEN keyboard focus moves to a row that is not wholly in view — or lies under the pinned rows of TRV-53 — THE tree view SHALL have the scrolling box that holds it bring that row into view, below the pinned rows, by the least distance that shows it whole.
TRV-13 WHILE a parent is open and its loading is true THE tree view SHALL draw one loading row under it, after the rows of any items it already holds and one level further in than its own row: a container of that level and of the tree's density (TRV-2, TRV-3) holding, at the start of its content, a Loading indicator component of the small size named by loadingLabel, which the tree lays out and does not restyle, and after it loadingLabel in comp.tree-view.supporting-text.typescale and comp.tree-view.unselected.supporting-text.color. The loading row is not an item: it SHALL take no focus, answer no pointer and no key, SHALL NOT be counted among its parent's items, and SHALL be shown and hidden by the motion of TRV-11 with the rows beside it. THE tree view SHALL expose the parent as busy WHILE its loading is true, open or closed, and SHALL announce nothing itself when loading begins or ends. THE tree view SHALL fetch nothing: a parent whose expandable is true and that holds no items opens onto no rows, or onto the loading row, and what it holds is the product's to give, which it learns from toggle. WHILE an item may be loading and loadingLabel is empty THE tree view SHALL still draw the indicator, and in debug builds report that it has no name.
TRV-14 WHERE the platform can search the text of what is shown and reports a match that lies in rows it does not draw (on the web, the browser's find-in-page), WHEN the match is under a closed parent THE tree view SHALL open that parent and every closed parent above it, at once and without the motion of TRV-11, SHALL emit each one's toggle exactly once with true, and SHALL leave bringing the match into view to the platform; it SHALL do so for a disabled parent too, whose rows are still part of the page. On a platform that has no such search or cannot report such a match THE tree view SHALL NOT open anything for it. Rows that a filter hides are not part of what the platform searches (TRV-70).
TRV-15 THE tree view SHALL let an item be chosen exactly WHILE selection is single or multiple, the item's value is not empty and its disabled is false, a parent and a leaf alike. It SHALL render an item as selected, from the selected condition (comp.tree-view.selected.container.color and the selected tokens TRV-4 to TRV-7 name), WHILE selection is single and value equals the item's value, or selection is multiple and values holds it, and every other item from the unselected condition (comp.tree-view.unselected.container.color and the unselected tokens). WHEN value or values names no item THE tree view SHALL select nothing for that name, and WHEN two items carry the same value it SHALL still render them, both selected where that value is; in debug builds it SHALL report each of these. The selected fill SHALL be drawn on the item's own row and on no other: THE tree view SHALL NOT mark a parent because an item under it is selected, and SHALL NOT open a closed parent to show a selection; opening the parents of the item it selects is the product's, which knows the path. WHEN the tree first appears it SHALL draw every item in the condition value and values give it, in its first frame and without the motion of TRV-31: appearing is no change of selection.
TRV-16 WHEN the user activates — by a press on its row outside the chevron, or by Enter or Space while focus is on it — an item that can be chosen in a tree whose selection is single and whose value is not that item's value THE tree view SHALL set value to the item's value, so that the item that was selected becomes unselected, and emit change exactly once; WHEN the item is already selected THE tree view SHALL change nothing and SHALL NOT emit change, because a single choice is never cleared by its own item.
TRV-17 WHEN the user activates — by a press on its row outside the chevron, with no modifier or with Ctrl (Command on Apple platforms), or by Space or Enter while focus is on it — an item that can be chosen in a tree whose selection is multiple THE tree view SHALL add the item's value to values, or remove it when values holds it, make that item the anchor of TRV-52, and emit change exactly once. Each item SHALL be chosen by itself: choosing a parent SHALL NOT choose the items it holds, a parent SHALL NOT show a mixed state for them, and closing a parent SHALL NOT change values.
TRV-18 WHILE selection is none THE tree view SHALL render every item from the unselected condition, SHALL ignore value and values, and SHALL expose no selected state. A leaf — and, in a tree whose selection is single or multiple, a leaf that cannot be chosen — SHALL then answer nothing: THE tree view SHALL draw no hover and no press answer on its row, SHALL emit nothing for a press on it, and SHALL still let the arrow keys reach it and show its keyboard focus (TRV-24, TRV-25), so that a person who reads the tree with a keyboard or a screen reader meets every row. A parent SHALL answer hover, focus and press on its whole row, which opens and closes it (TRV-10).
TRV-19 THE tree view SHALL be one stop in the focus order however many items it shows: Tab SHALL move focus into it to one row — the row that had focus last, or else the first selected item that is shown, or else the first row — and Tab again SHALL leave it; no other row, and nothing inside a row, SHALL be a stop. Focus that enters the tree SHALL NOT change the selection and SHALL NOT open or close anything. WHILE the tree shows no row it SHALL NOT be a stop. The filter field (TRV-54) is not a row: WHILE it is drawn it is a stop of its own, before the tree, and TRV-68 says where focus enters while a filter hides the row that had it.
TRV-20 WHEN focus is on a row and the user presses Down Arrow or Up Arrow THE tree view SHALL move focus to the next or the previous row that is shown, in the order the rows are drawn, whatever its level and whether or not it is disabled, without wrapping at the first and the last; WHEN the user presses Home or End it SHALL move focus to the first or the last row that is shown. It SHALL open and close nothing for these keys and SHALL NOT change the selection: selection does not follow focus. THE tree view SHALL NOT take these keys from the platform WHILE focus is not on one of its rows.
TRV-21 WHEN focus is on a row and the user presses the arrow key toward the end of the line (Right in a left-to-right layout) THE tree view SHALL act by the row it is on — whatever chevron says, so that a tree with no chevron still opens by the keyboard (TRV-44); WHILE the tree is not expandable every parent counts as open and nothing opens or closes (TRV-49): on a closed parent that is not disabled, open it as TRV-10 says and keep focus on it; on an open parent that shows at least one item, move focus to the first of them; on a leaf, on a disabled closed parent and on an open parent that shows none, do nothing. WHEN the user presses the arrow key toward the start of the line it SHALL likewise act by the row: on an open parent that is not disabled, close it as TRV-10 says and keep focus on it; on any other row that has a parent, move focus to that parent's row; on a row of the first level, do nothing.
TRV-22 WHEN focus is on a row and the user presses Enter or Space THE tree view SHALL do what a press on that row outside its chevron does: choose the item where it can be chosen (TRV-16, TRV-17), open or close it where it is a parent that cannot be chosen (TRV-10), and nothing on a leaf that cannot be chosen or on a disabled item. WHEN the user presses the asterisk key THE tree view SHALL open every closed parent that is not disabled among the focused row's siblings, itself included, emitting each one's toggle exactly once with true, and SHALL keep focus where it is. THE tree view SHALL leave every key it does not name here or in TRV-20, TRV-21, TRV-23, TRV-45 and TRV-52, and every key pressed with a modifier that those rules do not name, to the platform; WHILE an edit field is open (TRV-46) every key typed in it SHALL be the field's.
TRV-23 WHEN the user types printable characters while focus is on a row THE tree view SHALL move focus to the next row that is shown, after the focused one and going on from the first row after the last, whose label begins with the characters typed within one second of each other, compared without regard to case as the platform's locale does; one character typed again SHALL go on to the next such row; IF no label matches THE tree view SHALL keep focus where it is. It SHALL NOT open a closed parent to find a match, SHALL NOT change the selection, and SHALL NOT take a space typed inside such a run as an activation. WHILE filterable is true the chord of filterShortcut SHALL NOT be taken as type-ahead (TRV-62).
TRV-24 WHILE a row is hovered, keyboard-focused or pressed THE tree view SHALL render its container, label, supporting text, trailing text, icon, chevron and opacity from the component tokens of its condition in the highest-precedence active state, with precedence pressed over focused over hovered; focus gained by pointer or touch SHALL NOT select the focused state. Hover and press over any part of the row's hit area (TRV-26) SHALL answer on the whole container, as far as highlight says (TRV-51), the chevron's included; a row that answers nothing (TRV-18) SHALL take the focused state alone. The guide lines and the rows beside it SHALL NOT change under a pointer, a press or focus.
TRV-25 WHEN a row receives keyboard focus THE tree view SHALL show the focus ring inside the row's container — indented or full as highlight says (TRV-51) — following comp.tree-view.container.shape, so that neither a neighbouring row nor a scrolling ancestor cuts it, without animation, and at full strength on a disabled row too (TRV-27); focus gained by pointer or touch SHALL NOT show it.
TRV-26 THE tree view SHALL make each row's hit area the tree's whole width, however far its content and its container are set in (TRV-3), and the row's whole height, with no gap between the hit areas of two rows. WHERE input is touch, or the platform cannot tell the input type, a row SHALL be at least sys.target.touch high, drawn so, in both densities, because rows that touch cannot extend a hit area over each other; for a fine pointer a row SHALL be at least sys.target.pointer high WHILE density is regular, and WHILE density is compact as high as its density gives, the one place where a row of the tree is lower than the pointer target. In the row of a parent that can be chosen, the chevron's own hit area SHALL be, WHILE chevron is start, the part of the row's hit area from its start edge to the middle of the gap after the chevron's box, and WHILE chevron is end, the part from the middle of the gap before the chevron's box to the row's end edge; WHILE chevron is none, the icon's hit area of TRV-44 is the part from the row's start edge to the middle of the gap after the icon. Each SHALL be at least sys.target.touch wide for touch and sys.target.pointer wide for a fine pointer, reaching over what stands beside the mark where the box gives less.
TRV-27 WHILE an item's disabled is true THE tree view SHALL render its container, label, supporting text, trailing text, icon, chevron and opacity from the disabled component tokens of its condition, and SHALL apply that opacity to the whole row, its trailing content included, and to nothing else: the focus ring of TRV-25 SHALL be drawn at full strength on a disabled row that has keyboard focus, because the arrow keys reach it and the ring says where focus is; SHALL NOT emit change or toggle for a press, a key or a touch on it; SHALL draw no hover and no press answer on it; and SHALL expose it as disabled. The arrow keys SHALL still reach it, so that people learn it exists. The item SHALL keep its place, its selection and its open: a disabled parent that is open still shows the items it holds, which keep their own disabled, and the product MAY still set its open and select it. A row that draws no fill at rest SHALL draw none while disabled.
TRV-28 WHEN an item's row is pressed by pointer, touch, Enter or Space THE tree view SHALL show its pressed state without delay and SHALL keep it visible for at least sys.motion.duration.press-hold, even when the press ends sooner.
TRV-29 WHILE an item's row is pressed THE tree view SHALL answer as sys.behavior.pressed-feedback names: overlay applies the pressed tokens to the whole container at once; ripple grows the pressed state layer, clipped to the container (indented or full as highlight says), from the point of contact (from the center for keyboard activation); dim applies the pressed opacity to the whole row and draws no state layer; none draws no answer to the press. Under ripple and dim only the container color stays with the state under the press; label, supporting text, trailing text, icon, chevron and opacity still come from the pressed tokens. Under none every part stays with the state under the press. The ripple grows over comp.tree-view.motion.feedback-duration with comp.tree-view.motion.state-easing, fades over comp.tree-view.motion.state-duration with comp.tree-view.motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced.
TRV-30 THE tree view SHALL ease its rows' container corners by sys.shape.corner-smoothing (0 is a quarter circle, 0.6 the iOS continuous corner; a platform with only the OS curve draws it for any amount above 0) and show a row's keyboard focus as sys.behavior.focus-style names (ring or glow); a platform that cannot draw a choice SHALL fall back to the first value and state that in its README.
TRV-31 WHEN the colors of a row change between states, or between the unselected and the selected condition, THE tree view SHALL animate them over comp.tree-view.motion.state-duration with comp.tree-view.motion.state-easing, and SHALL change them at once where motion is reduced. The selected fill SHALL NOT slide from one row to another.
TRV-32 THE tree view SHALL expose itself as a tree named by label, and as one in which several items may be selected WHILE selection is multiple; each item as one tree item named by its label (the text of the label slot's content where the product gave one), described by its supporting text, then the text of its trailing content, then its trailing text, with its level, its place among the items of its parent and their number; a parent with its expanded or collapsed state WHILE the tree is expandable, and with none WHILE it is not (TRV-49), and the items it shows as a group that belongs to it in either case; WHILE selection is single or multiple, each item that can be chosen with its selected state, true or false, and an item that cannot with none; a disabled item as disabled and a loading parent as busy; and the chevron, the icon and the guide lines hidden. WHILE a name is being edited the edit field SHALL be exposed as a text field inside the row it stands in, named by editLabel, and keyboard focus SHALL be in it; a new row (TRV-48) SHALL be exposed as a tree item at its level holding that field. WHILE editLabel is empty and a field is open THE tree view SHALL still open the field, and in debug builds report that it has no name. On the web these are the tree, treeitem and group roles with aria-expanded, aria-selected, aria-multiselectable, aria-disabled and aria-busy, the level, the set size and the position coming from the nesting of the elements. WHERE a platform has no tree semantics THE tree view SHALL expose each row as one element in the order drawn, with that name and description, the expanded or collapsed state, the selected state and the disabled state as the platform says them, and its level by the platform's own means where it has one; it SHALL NOT invent words for a level, and the platform's README SHALL say what a person is not told. WHILE label is empty THE tree view SHALL still render, and in debug builds report that the tree has no accessible name; WHILE an item's label is empty and its label slot holds nothing it SHALL report that the item has none.
TRV-33 WHEN a parent opens or closes, and WHEN the selection changes, THE tree view SHALL let the changed state of the row be the only thing assistive technology is told: it SHALL announce nothing itself, SHALL have no live region other than the status of a filter (TRV-66), and SHALL NOT move keyboard or screen-reader focus, except as TRV-12 says for a row that goes away and TRV-45 to TRV-48 say for an edit field.
TRV-34 WHILE the text size is enlarged THE tree view SHALL grow its labels, its supporting texts and its trailing texts with it, keep its paddings, gaps and indents, and grow each row in height; a label and a supporting text on one line (TRV-6, TRV-7) SHALL be cut with an ellipsis and shown whole in the tooltip of TRV-50, and with labelWrap and supportingWrap they SHALL wrap and the rows grow; it SHALL keep the chevron's and the icon's boxes at their token sizes, both still centred on the label's first line (TRV-2), SHALL set no fixed height, SHALL lose no content when the reader raises line height, paragraph spacing, letter spacing or word spacing (a one-line text is cut, and is whole in its tooltip and its accessible name), and SHALL need no horizontal scrolling at a width of 320 points with text at 200 %, where TRV-3 keeps half of the width for names.
TRV-35 WHERE the platform draws with a person's own forced colors (the web's forced-colors mode, and a platform's equivalent where it has one) THE tree view SHALL draw its labels, texts, icons and chevrons in the platform's text color; the guide lines in that text color; a selected row in the platform's colors for a selected item, fill and text, and in addition with an edge in the text color inside its container, because the mode may remove a fill; a disabled row in the platform's color for disabled text; and a row's hover, press and focus in the platform's own colors, with the focus ring still inside the row. Open and closed SHALL still be told apart by the chevron's turn, which no color carries.
TRV-36 WHERE the layout direction is right-to-left THE tree view SHALL mirror a row and apply its paddings and its indent by logical start and end: the tree's start edge is its right edge, each level begins further to the left, the chevron's box at the start is at the right of its row with the icon, the text, the trailing content, the trailing text and an end chevron after it toward the left, and the guide lines stand under the parents' first leading things. A closed parent's start chevron SHALL point to the left, drawn so by the icon helper, which mirrors the glyph because the icon set marks chevron_right (TRV-38), and an open parent's SHALL point down. The arrow keys of TRV-21 SHALL follow the direction: Left opens and steps in, Right closes and steps out; Up, Down, Home and End SHALL be the same in both directions. A ripple SHALL still grow from the point of contact.
TRV-37 THE tree view SHALL take its layout direction from where it is used — the direction of the nearest ancestor that sets one, and the platform's own where none does — and SHALL have no direction setting of its own; WHEN that direction changes while the tree view is shown THE tree view SHALL draw itself for the new direction at once, without a motion of its own, keeping its selection, every parent's open and its focus.
TRV-38 WHERE the layout direction is right-to-left THE tree view SHALL draw an item's icon and a parent's chevron mirrored left to right exactly when the system's icon set marks that glyph's name as mirrored or the product forces mirroring for that use, and unmirrored when the product forbids it: the icon helper mirrors the glyph inside its own box, about the box's vertical centre line, changing neither its place, size, color and fill nor the order TRV-2 gives. THE tree view SHALL NOT mirror a glyph itself, and SHALL NOT mirror content the product gives as an image or a view of its own rather than by a glyph's name. The quarter turn of an open parent's chevron (TRV-4) is the tree's and SHALL end pointing down in both directions.
TRV-39 THE tree view SHALL lay out an item's label, its supporting text and its trailing text, and the words of a loading row, each as text of its own direction, isolated from the text around it: each takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right file name, a path, a number with its unit and a version keep their own order in a right-to-left layout and reorder nothing beside them; THE tree view SHALL still place each and align its lines by the layout direction, not by the text's own, and SHALL cut a trailing text that does not fit (TRV-7) at the end of its own direction.
TRV-40 WHILE the system's icon set cannot yet draw a glyph of the tree view (its font is still loading) THE tree view SHALL draw nothing in that glyph's place, never the glyph's name as text, SHALL keep the glyph's box, and SHALL draw the glyph once the set can; a parent SHALL open and close all the same.
TRV-41 WHEN density names a value that the active design system does not have THE tree view SHALL render with the default density's tokens, and WHEN selection names a value the tree view does not define it SHALL render with none, WHEN chevron names one it SHALL render as start, WHEN guides names one as none, WHEN highlight names one as indented and WHEN iconSpace names one as auto; WHEN indent, iconGap or stickyMax is not a number of zero or more it SHALL render as its default; in debug builds it SHALL report the unknown value. WHEN selection changes while the tree is shown THE tree view SHALL draw the new form at once, keeping every parent's open and its focus, and SHALL emit no change for it.
TRV-42 IF the tree view has no items THE tree view SHALL draw nothing, take no space, expose nothing and be no stop in the focus order: the words for an empty hierarchy are the product's, beside the tree. IF an item holds no items and its expandable is false THE tree view SHALL treat it as a leaf whatever its open and loading say. WHEN items are added to or removed from a shown tree THE tree view SHALL draw them at once, without the motion of TRV-11, keeping the selection, every other parent's open and, as far as TRV-12 allows, its focus.
TRV-43 THE tree view SHALL keep the room of an icon (comp.tree-view.icon.size.regular for regular and comp.tree-view.icon.size.compact for compact, and iconGap after it) in the row of an item whose icon is empty WHILE iconSpace is always, and WHILE iconSpace is auto and another item of the same level — the items of the same parent, or of the first level — has an icon, so that the labels of a level stand in one column; WHILE iconSpace is never, and WHILE it is auto and no item of the level has an icon, it SHALL keep no such room. The kept room SHALL draw nothing and SHALL count as the icon's for the step of TRV-3 and for the guides of TRV-8 only as room: a guide stands under an icon that is drawn, and under the label's start where the room is empty.
TRV-44 WHILE chevron is none THE tree view SHALL draw no chevron and keep no chevron's box, and SHALL open and close a parent that is not disabled as follows. By the keyboard, the arrows of TRV-21 SHALL always open and close it, whether or not it can be chosen. By pointer or touch: WHERE the parent's row has an icon, a press on the icon SHALL open or close it, emit its toggle once and never choose, its hit area being TRV-26's; WHERE it has no icon and cannot be chosen, a press anywhere on its row SHALL open or close it (TRV-10); WHERE it has no icon and can be chosen, a press on its row SHALL choose it (TRV-16, TRV-17) and SHALL NOT open or close it — selection wins, and the keyboard still opens it. A parent that names an icon and an open icon shows open and closed by its glyph (TRV-5); a parent with neither shows it by the expanded state alone, which assistive technology is told (TRV-32), and in debug builds THE tree view SHALL report a parent that has no icon and no open icon once, because nothing on screen shows whether it is open.
TRV-45 WHILE editable is true THE tree view SHALL open an edit field on an item's name (TRV-46) WHEN the user double-clicks or double-taps the label of its row, WHEN the user presses F2 while keyboard focus is on its row, and WHEN the product asks the tree view to edit that item (the platform's method for it). It SHALL NOT open one on a disabled item, on the loading row, or on an item whose label is given by content of the label slot rather than by plain text, whose inline content is the product's to edit; and WHILE editable is false it SHALL open none, leaving F2 and a double-click to the platform and doing nothing when asked. The two presses of a double-click SHALL each be answered as TRV-10 to TRV-17 say, and the field SHALL open after the second. Only one field SHALL be open in a tree at a time: opening one, by any of these means or by TRV-48, SHALL first commit the one that is open.
TRV-46 WHILE an edit field is open on an item THE tree view SHALL draw an Embedded text input component of one line over the item's label, in the box of the label's first line — the same font, line height, start and width, so that opening and closing the field moves nothing in the row or beside it — in the label's text style and color, the label and a supporting text inline after it not drawn under it, holding the label, with keyboard focus in it and — for a leaf whose label holds a dot after its first character — the text before the last dot selected, and for any other item the whole label selected; and SHALL draw around the field's box the focus indicator of TRV-25 (sys.behavior.focus-style), inside the row, while the chevron or its box, the icon, the trailing content, the trailing text, the row's selection and the row's open stay as they were. The row SHALL keep at least its height, and a long name SHALL scroll inside the field rather than widen the tree. Every key typed in the field SHALL be the field's: WHEN the user presses Enter, or WHEN focus leaves the field by any other means (Tab, a press elsewhere, the window losing focus), THE tree view SHALL commit the field; WHEN the user presses Escape it SHALL close the field without emitting; WHILE an input method is composing Enter and Escape SHALL be the input method's. WHEN the field commits THE tree view SHALL close it and, WHERE its text with white space removed at both ends is not empty and differs from the label, emit the item's rename exactly once with that text and the label it had; otherwise it SHALL close the field without emitting. THE tree view SHALL NOT change the label itself: it SHALL draw the label it had until the product sets the new one. WHEN the field closes on Enter or Escape keyboard focus SHALL return to the item's row; WHEN it closes because focus left it, focus SHALL stay where it went. WHILE the field is open THE tree view SHALL NOT answer a press inside it as a press on the row (TRV-10), and WHEN the item is removed, becomes disabled, or is hidden because a parent above it closes, or editable becomes false, it SHALL close the field without emitting.
TRV-47 WHILE an edit field is open on an item THE tree view SHALL keep that item where it is and keep its row's state of selection, open, hover and press as they were; SHALL take none of the keys of TRV-20 to TRV-23 from the field; and SHALL change nothing about the selection or about any parent's open because a field opened, committed or closed. WHEN the product sets the item's label in answer to rename THE tree view SHALL draw it at once, without a motion of its own (the label of a row is the product's, TRV-6).
TRV-48 WHEN the product asks the tree view for a new item (the platform's method for it, saying whether the new item is a parent or a leaf and, where it likes, the glyph of its icon) THE tree view SHALL commit any field that is open and add a new row of its own at the level of the reference item, directly after the rows the reference item shows, holding an edit field (TRV-46) that is empty and has keyboard focus. The reference item SHALL be the first of these that is shown: the selected item (single: the item value names; multiple: the row that has or last had focus where it is selected, else the first selected item in the order drawn), the row that has or last had focus, and none, in which case the new row is the last row of the first level. The new row SHALL be drawn as a row of its level and of the tree's density: for a parent a closed chevron in the chevron's box where chevron is start or end, for a leaf the box as TRV-4 says, and the glyph the product named in the icon's place. WHEN its field commits with a text that, with white space removed at both ends, is not empty THE tree view SHALL take the new row away and emit create exactly once with that text, whether it is a parent, the item it goes under (none at the first level) and the item it follows (none where it is first); WHEN the product adds an item in the new row's place in answer, before the next frame is drawn, focus SHALL move to that item's row. WHEN the field closes on Escape or commits empty THE tree view SHALL take the new row away, emit nothing, and return focus to the row that had it. The new row is not an item: it SHALL NOT be chosen or opened, the arrow keys SHALL NOT reach it while its field is open, and the tree SHALL change no selection and no parent's open for it. A new item SHALL be asked for whatever editable says.
TRV-49 WHILE expandable is false THE tree view SHALL draw every parent as open whatever its open says, draw no chevron and keep no chevron's box, emit no toggle, open and close nothing for a press, a key or the platform's search, and expose no parent as expanded or collapsed: each item is a tree item at its level, a parent's items a group that belongs to it (the tree pattern's tree items without the expanded state are end nodes to a screen reader, and their groups still tell the level). The arrow toward the end of the line SHALL move focus to a parent's first item and the one toward the start to an item's parent (TRV-21), and the asterisk SHALL do nothing. A press on a row SHALL choose an item that can be chosen and do nothing on any other. An item's own expandable SHALL be read only WHILE the tree's expandable is true. WHEN expandable becomes true the tree SHALL draw each parent as its open says, at once.
TRV-50 WHILE a row's label, or its supporting text, is cut (TRV-6, TRV-7) THE tree view SHALL show the whole of it in a Tooltip component beside the row's text WHEN a fine pointer rests on the row for the tooltip's show delay and WHEN the row receives keyboard focus, and SHALL hide it WHEN the pointer leaves the row and the tooltip for the hide delay, WHEN focus leaves the row, WHEN the user presses Escape (which does nothing else), and WHEN the row is pressed; the tooltip SHALL stay while the pointer is over it (WCAG 1.4.13: dismissible, hoverable, persistent). It SHALL hold the label alone WHERE the item has no supporting text, and the label as the title and the supporting text as the text of a rich tooltip WHERE it has one. WHILE nothing of the row is cut THE tree view SHALL show no tooltip for it. The tooltip SHALL be hidden from assistive technology, which is given the whole label as the row's name and the whole supporting text as its description (TRV-32); no touch long-press opens it, because a long-press on a row is the platform's.
TRV-51 WHILE highlight is indented THE tree view SHALL draw a row's container — its fill (selected or of a state), its state layer and ripple, and its focus indicator — from where the row's content's level begins, less the row's padding, to the tree's end edge; WHILE highlight is full it SHALL draw them from the tree's start edge to its end edge whatever the row's level, the content still beginning one step further in for each level (TRV-3). The corners (comp.tree-view.container.shape) and the focus ring follow the container in both.
TRV-52 WHILE selection is multiple THE tree view SHALL answer, besides TRV-17, the keys and presses of the tree pattern's multi-select model, each emitting change exactly once where values changed and never opening or closing anything: Shift with Down Arrow or Up Arrow SHALL move focus to the next or previous row shown and select every item that can be chosen from the anchor to the focused row, deselecting the items of the range it selected before that are no longer in it, and leaving every other value as it was; Shift with Space SHALL do the same from the anchor to the focused row without moving focus; Ctrl (Command on Apple platforms) with Shift and Home or End SHALL select every item that can be chosen from the focused row to the first or the last row shown and move focus there; Ctrl (Command) with A SHALL select every item that can be chosen among the rows shown; a press with Shift SHALL select from the anchor to the pressed row as Shift with Space does; a press with Ctrl (Command) SHALL toggle the pressed item as a plain press does (TRV-17). The anchor SHALL be the item last chosen or unchosen by a plain press, a press with Ctrl (Command), Space or Enter, and where there is none the focused row. Items that cannot be chosen (no value, disabled) SHALL be passed over in a range and keep their state. WHILE selection is single or none these keys and modifiers SHALL be the platform's, except that a press with a modifier SHALL do what a plain press does.
TRV-53 WHILE stickyParents is true and stickyMax is more than 0, and the tree stands in a scrolling box, THE tree view SHALL pin at the top of that box the rows of the open parents that hold the topmost row shown below the pinned rows, one per level in the order of their levels, the innermost stickyMax of them where more parents are open above it, each held in place while what it holds scrolls under it and leaving with its last row; it SHALL pin the rows themselves — the same rows, with their own fill, state, selection, focus, press and the events of a press, never a copy in the accessibility tree — drawn over the rows that scroll under them with comp.tree-view.sticky.container.color under their own fill and a line comp.tree-view.sticky.divider.width wide in comp.tree-view.sticky.divider.color under the last of them. WHEN keyboard focus moves onto a row that lies under the pinned rows THE tree view SHALL have the scrolling box bring that row into view below them by the least distance. A guide line SHALL pass under a pinned row (TRV-8). Nothing about pinning SHALL move by itself: there is no motion to reduce. A tree that stands in no scrolling box of its own, or whose stickyParents is false, SHALL pin nothing. A platform whose scrolling list cannot hold a row in place SHALL draw the pinned rows as an overlay hidden from assistive technology that keeps focus on the real rows, and SHALL say so in its README.
TRV-54 WHILE filterable is true and the tree has items THE tree view SHALL draw a filter field above its first row, as wide as the tree, and what stands under it — the status line of TRV-65 while there is one, then its first row — comp.tree-view.filter.gap below it: a Text input component of type search in its default variant and the small size, showing the glyph search of the system's icon set in its leading-icon slot, filterPlaceholder as its placeholder and filterValue as its value, drawn and answering as that text input draws and answers (its own sentences hold, its tokens are its own). WHILE the tree stands in a scrolling box THE tree view SHALL keep the field, and the gap below it, pinned at the top of that box on comp.tree-view.sticky.container.color, with the rows TRV-53 pins directly under it and the edge of TRV-53 drawn under the last of them — under the gap below the field WHILE no row is pinned and rows scroll under it.
TRV-55 WHEN the person changes the filter field's text — by typing, deleting, pasting, cutting, dictating, an input method committing text, the clear button (TRV-64) or Escape (TRV-61, TRV-69) — THE tree view SHALL emit filterChange exactly once per change with the new text, setting filterValue itself first on the web (a controlled platform leaves filterValue to the caller), and SHALL apply the filter to the new text at once. WHEN the product sets filterValue THE tree view SHALL show that text in the field and apply it, and SHALL NOT emit filterChange. WHILE an input method is composing THE tree view SHALL filter by the text the field reports, and SHALL leave the composition, Enter, Escape and the arrow keys to the input method (TXI-4).
TRV-56 THE tree view SHALL apply a filter WHILE filterable is true and filterValue holds a character that is not white space, and SHALL read the filter text as words: the runs of characters between white space. An item SHALL match WHILE its label (the text of its label slot's content, where the product gave one) contains every word, each anywhere in it and in any order, compared without regard to case, to the width of a character or to the marks on a letter, as the label's language compares (as the combobox compares, CMB-25). THE tree view SHALL compare nothing else of an item — not its supporting text, its trailing text, the text of its trailing content or its value. A disabled item SHALL match as any other item and stay disabled. It SHALL match only the items it holds: the items of a parent that loads them when it opens (TRV-13) are not searched until they are given. THE tree view SHALL NOT fetch, wait, debounce, rank or reorder anything for a filter.
TRV-57 WHILE a filter is applied THE tree view SHALL show, in the order given: each row that matches; each parent's row that holds an item that matches, at any depth; and every item inside a parent whose own row matches, so that a parent found by its name is shown whole. Every other row SHALL be hidden — not drawn, taking no space, not focusable and not exposed to assistive technology — together with what it holds. A hidden item SHALL keep its open, its disabled state and its selection, and WHEN no filter is applied any more every row SHALL be shown as it was.
TRV-59 WHILE a filter is applied THE tree view SHALL draw open, for the filter, each closed parent that holds an item that matches and is shown, at any depth, so that every match is in view without the person opening anything, and SHALL draw every other parent as its open says. Opening a parent for the filter SHALL write nothing to the item's open, SHALL emit no toggle, and SHALL be drawn at once, without the motion of TRV-11; the row SHALL be exposed as expanded while it is drawn open. WHEN the person opens or closes a parent while a filter is applied — by its chevron, its row or an arrow key (TRV-10, TRV-21, TRV-44) — THE tree view SHALL answer as those sentences say, setting open itself on the web and emitting toggle exactly once where open changes, and SHALL stop opening that parent for the filter until the filter text changes. WHEN no filter is applied any more THE tree view SHALL draw every parent as its open says: the parents the filter opened close again, at once, and a parent the person opened or closed stays as the person left it.
TRV-60 WHILE a filter is applied THE tree view SHALL draw each row it shows as it draws that row without a filter, and SHALL NOT mark, in a label, the characters that a word of the filter text matched: no color, weight, fill or element of their own. What the filter leaves is the answer, as in a file tree's filter and a site's sidebar filter; a row SHALL be told from the others only by its own states (TRV-15, TRV-24) and as the active match (TRV-61). THE tree view SHALL leave the product's content as it is: where the label is the product's own text in the document (the web), it SHALL add, split and remove no node of it.
TRV-61 WHILE keyboard focus is in the filter field, a filter is applied and a row shown matches and is not disabled, THE tree view SHALL make the first such row, in the order the rows are drawn, the active match — as soon as there is one, and the new first one whenever the result changes — and SHALL draw it as it draws that row while the row has keyboard focus, its focused tokens and its focus ring (TRV-25), without animation, while focus stays in the field, so that typing goes on editing the filter text; THE tree view SHALL NOT tell assistive technology of it — no active descendant, no focus and no announcement — until the person moves to it, as a search's automatic choice is not read out; a pointer over a row SHALL NOT make it the active match, and WHILE focus is not in the field no row SHALL be drawn as one. WHILE no input method is composing, WHEN the person presses Enter THE tree view SHALL take the active match as Enter on that row takes it (TRV-22): choose it where it can be chosen, or open or close it where it is a parent that cannot be chosen; and SHALL keep focus in the field; WHEN the person presses Down Arrow THE tree view SHALL move focus to the active match itself, not past it, making it the tree's focused row (TRV-19), where it is read as any focused row is, and do nothing more. WHILE there is no active match the two keys SHALL do nothing of the tree's own. WHEN the person presses Escape WHILE the field holds text THE tree view SHALL empty it, emit filterChange once with the empty text, and keep focus in the field, as a native search field does; WHEN the person presses Escape WHILE the field is empty THE tree view SHALL return focus to the row that had it before the filter shortcut moved it to the field (TRV-62), and otherwise SHALL do nothing of its own and let the key pass on. Up Arrow, Home, End and the arrow keys along the line SHALL stay the field's.
TRV-62 WHILE filterable is true and filterShortcut holds exactly one chord, WHEN the person presses that chord while keyboard focus is on a row and no edit field is open (read as KBS-1 reads a chord; not a key repeating while held, and not during an input-method composition) THE tree view SHALL move focus to the filter field with its text selected, and SHALL NOT take the press as type-ahead (TRV-23). THE tree view SHALL listen for the chord nowhere else, SHALL draw no hint of it, and SHALL expose it as no keyboard shortcut of the field: it is a key of the tree's rows, as F2 is (TRV-45), and a hint would promise it from anywhere. WHILE filterShortcut is empty or holds more than one chord the tree view SHALL bind nothing, reporting more than one chord in debug builds.
TRV-63 WHEN the product asks the tree view to focus its filter (the platform's method for it) WHILE filterable is true and the field is drawn THE tree view SHALL move focus to the field with its text selected, whether or not filterShortcut is empty, so that a product can bind a key of its own for the whole window.
TRV-64 WHILE the filter field holds text THE tree view SHALL draw, in the field's trailing-icon slot, an icon-only Tanrei Button of the text variant and the small size showing the glyph close of the system's icon set, not mirrored, named by filterClearLabel. WHEN it is activated THE tree view SHALL empty the field, emit filterChange once with the empty text, and move focus to the field. WHILE filterClearLabel is empty and the product's words give none THE tree view SHALL still draw the button, and in debug builds report that it has no accessible name.
TRV-65 WHILE a filter is applied THE tree view SHALL draw a status line at the top of the results, where its first row would stand, the rows following it: filterCountText with its place {count} filled by the number of rows that match WHILE a row matches and filterCountHidden is false, and filterEmptyText WHILE no row matches, in place of the rows, all of them hidden, so that the tree shows no row and is no stop in the focus order (TRV-19). It SHALL draw the line in comp.tree-view.filter.status.typescale and comp.tree-view.filter.status.color, inset as a row's content is (comp.tree-view.container.padding-inline.regular for regular and comp.tree-view.container.padding-inline.compact for compact), wrapping and growing with enlarged text, as text of its own direction (TRV-39), taking no focus and no state, and hidden from assistive technology, which TRV-66 tells the same words. WHILE a row matches and filterCountHidden is true it SHALL draw no line. WHILE the words it would draw are empty and the product's words give none THE tree view SHALL draw nothing in their place and in debug builds report it.
TRV-66 WHEN the result of a filter changes — the filter text or the items change while a filter is applied — and has then stayed as it is for one second (the pause of TRV-23), THE tree view SHALL tell assistive technology once, politely and without moving focus, filterCountText with its place {count} filled by the number of rows that match, or filterEmptyText WHILE no row matches; WHEN no filter is applied any more it SHALL say nothing. It SHALL say them whether or not filterCountHidden is true, through one status of its own that is not drawn (the line of TRV-65 is what is drawn) — on the web an element with the status role and aria-atomic true, beside the tree's element and outside it — which is the only thing the tree view ever announces (TRV-33). WHILE filterCountText is empty and the product's words give none THE tree view SHALL say no count and in debug builds report it.
TRV-67 THE tree view SHALL change nothing but what it draws for a filter: value, values, every item's open (except where the person opens or closes one, TRV-59) and its labels SHALL stay as they were, and it SHALL keep filterValue no longer than its own lifetime and write it to no storage. A selected item that the filter hides SHALL stay selected, and change SHALL NOT be emitted for it; Shift with the arrows, Shift with Space and Ctrl (Command) with A SHALL act on the rows shown only (TRV-52). WHEN the filter text changes while a filter is applied THE tree view SHALL have the scrolling box that holds it bring the field and the first row shown into view; WHEN no filter is applied any more it SHALL, WHILE keyboard focus is on a row, keep that row where it is in the view, as TRV-12 keeps a parent's row, and SHALL NOT scroll for it otherwise.
TRV-68 WHEN a filter comes to hide the row that has keyboard focus (the product sets filterValue, or changes the items) THE tree view SHALL move focus to the filter field. WHEN focus enters the tree by Tab WHILE a filter is applied and the row that had focus last is hidden THE tree view SHALL give focus to the first row shown that matches and is not disabled (the active match of TRV-61), or else the first row shown, in place of TRV-19's first choice. WHILE an edit field is open on an item, and on the new row of TRV-48, THE tree view SHALL keep that row shown, whether or not it matches, until its field closes, and SHALL then apply the filter to it.
TRV-69 WHILE a filter is applied and keyboard focus is on a row, WHEN the person presses Escape (and no tooltip of TRV-50 is shown) THE tree view SHALL open, as the person would (open set and toggle emitted for each), the parents the filter had opened around that row, so that it stays shown, then empty the filter — setting filterValue to empty and emitting filterChange once — and keep focus on that row, which TRV-67 keeps where it is, so that a person who found an item by the filter sees it among its neighbours.
TRV-70 THE tree view SHALL draw every change a filter makes — rows hidden and shown, parents opened for the filter and closed again — at once, without the motion of TRV-11, whether or not motion is reduced; a parent the person opens or closes during a filter moves as TRV-11 says. Rows the filter hides SHALL NOT be found by the platform's own search of what is shown (on the web, find-in-page), and TRV-14 SHALL NOT open anything for them.
TRV-71 THE tree view SHALL expose the filter field as a search field — on the web an input of type search, which has the searchbox role — named by filterLabel, with filterPlaceholder as its placeholder, controlling the tree (aria-controls on the web), naming no active descendant (the active match of TRV-61 is read once the person moves to it), before the tree in reading order and a stop of its own in the focus order, outside the tree's one stop (TRV-19); each shown item with its level and its position among the shown items of its parent and their number; and the rows the filter hides not at all. WHILE filterable is true and filterLabel is empty THE tree view SHALL still draw the field, and in debug builds report that it has no accessible name.
TRV-72 WHERE the platform has ARIA attributes (the web), the host carries its tree role (TRV-32) itself — while no filter field stands in it; while one does, its first list carries the role and the label (TRV-54, TRV-71), and the host, which then carries no role, holds the product's name and writes none of its own — so what the product writes on it is not moved, but for a name: WHILE label is not empty THE tree view SHALL hold the product's aria-label and aria-labelledby on that host as their data-aria- twins, so that label is its whole name although the platform gives aria-labelledby the precedence, and WHEN label is emptied SHALL give them back as they were written; WHILE label is empty a name the product gives so — aria-label, or aria-labelledby naming an element — SHALL be its name and SHALL NOT be reported as having none in debug builds (TRV-32). WHEN the product removes one, or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaLabelledByElements) to null, THE tree view SHALL take it away.

Correspondencia de nombres por plataforma

Paridad no significa API idénticas. Cada plataforma expresa el mismo contrato con su propio estilo.

Especificación Web SwiftUI Jetpack Compose Flutter React Native
Componente tanrei-tree-view TanreiTreeView TanreiTreeView TanreiTreeView TreeView
label · Propiedad label label label semanticLabel accessibilityLabel
selection · Propiedad selection selection selection selection selection
value · Propiedad value selection value value value
values · Propiedad values selection values values values
density · Propiedad density density density density density
chevron · Propiedad chevron chevron chevron chevron chevron
expandable · Propiedad expandable isExpandable expandable expandable expandable
guides · Propiedad guides guides guides guides guides
indent · Propiedad indent indent indent indent indent
iconSpace · Propiedad icon-space iconSpace iconSpace iconSpace iconSpace
iconGap · Propiedad icon-gap iconGap iconGap iconGap iconGap
highlight · Propiedad highlight highlight highlight highlight highlight
labelWrap · Propiedad label-wrap labelWrap labelWrap labelWrap labelWrap
supportingWrap · Propiedad supporting-wrap supportingWrap supportingWrap supportingWrap supportingWrap
stickyParents · Propiedad sticky-parents stickyParents stickyParents stickyParents stickyParents
stickyMax · Propiedad sticky-max stickyMax stickyMax stickyMax stickyMax
editable · Propiedad editable isEditable editable editable editable
editLabel · Propiedad edit-label editLabel editLabel editLabel editLabel
loadingLabel · Propiedad loading-label loadingLabel loadingLabel loadingLabel loadingLabel
filterable · Propiedad filterable isFilterable filterable filterable filterable
filterValue · Propiedad filter-value filterText filterValue filterValue filterValue
filterLabel · Propiedad filter-label filterLabel filterLabel filterLabel filterLabel
filterPlaceholder · Propiedad filter-placeholder filterPrompt filterPlaceholder filterPlaceholder filterPlaceholder
filterEmptyText · Propiedad filter-empty-text filterEmptyText filterEmptyText filterEmptyText filterEmptyText
filterCountText · Propiedad filter-count-text filterCountText filterCountText filterCountText filterCountText
filterCountHidden · Propiedad filter-count-hidden isFilterCountHidden filterCountHidden filterCountHidden filterCountHidden
filterClearLabel · Propiedad filter-clear-label filterClearLabel filterClearLabel filterClearLabel filterClearLabel
filterShortcut · Propiedad filter-shortcut filterShortcut filterShortcut filterShortcut filterShortcut
change · Evento change selection onValueChange onChanged onChange
create · Evento create onCreate onCreate onCreate onCreate
filterChange · Evento filterchange filterText onFilterValueChange onFilterChanged onFilterChange
Notas Form: <tanrei-tree-view> is a custom element with **no shadow root**, around the product's own nested lists in the light DOM — <tanrei-tree-view label="Project files" selection="single" value="src/index.ts"><ul><li data-value="src" data-open><span>src</span><ul><li data-value="src/index.ts"><span>index.ts</span></li></ul></li></ul></tanrei-tree-view> — the third component of this form after the table and the accordion. A hierarchy is a nested list: that is what a Markdown renderer emits, what a crawler and a reader mode keep, and what the page shows where script does not run. Everything drawn comes from one stylesheet, @tanrei/web/tree-view.css, whose selectors start at tanrei-tree-view and are wrapped in :where(); the element adopts the same sheet into the root it is connected to, so it also works inside another component's shadow root. Before the element is defined the stylesheet already draws the whole look: the indent from the nesting depth (a counter-free rule per nesting step through a custom property the nested ul raises), the chevron as the row's ::before in the icon font on an li that holds a ul or has data-expandable, turned under li[data-open], the rows under an li without data-open not shown, the guide line as the nested ul's ::before, the selected fill from aria-selected once the element has set it and from [value] matching only after definition (a selected row is the one thing drawn at upgrade: the product that renders on a server writes aria-selected="true" itself to have it in the first frame). Under @media (scripting: none) every level is shown and no chevron is drawn: a plain nested list in the tree's type and spacing. The element, once defined, adds what a stylesheet cannot: role="tree" and aria-label on itself (aria-multiselectable for multiple), role="none" on each <ul> directly inside it and role="group" on each nested one, role="treeitem", aria-expanded, aria-selected, aria-disabled and aria-busy on each <li> (level, set size and position come from the nesting; they are written as aria-level, aria-setsize and aria-posinset only where a product marks a list as partial), the roving tabindex (0 on one <li>, -1 on the others) with the focus ring drawn on the row by li:focus-visible > :first-child, the keys of TRV-20 to TRV-23, the pointer rules of TRV-10 (the chevron's hit area is the row's ::before box extended by the indent), change with detail.value or detail.values, the shared press primitive on the row (ripple and dim, TRV-29), the loading row (a <tanrei-loading-indicator size="small"> and the label in an element of its own after the nested list, aria-hidden apart from the indicator's name), opening for find-in-page where the browser reports it (closed lists are hidden with hidden="until-found" where the browser has it and answered on beforematch; elsewhere closed rows are not found, TRV-14), the motion of TRV-11 (the nested list's height from 0 to auto under interpolate-size: allow-keywords where the browser can, one measured Web Animations run elsewhere, at once where neither is available) and every debug report. A MutationObserver on the subtree keeps roles and the tab stop right when the product adds or removes items. value and values are properties and attributes (values as a space-separated list is not taken: a value may hold a space; the attribute is JSON, the property an array). Inside .tanrei-prose the element is an island by its tag name (PRS-16). Markdown: the product wraps a nested list in <tanrei-tree-view> at build time and wraps each item's own text in its row element (a step of a few lines, shown in the README); Tanrei does not transform content. React: TreeView and TreeItem render the same elements. indent and icon-gap take a number of pixels, or auto (the default). guides takes none, shown or hover; the bare attribute is shown. expandable and sticky-parents are on by default: expandable="false" and sticky-parents="false" turn them off. data-supporting-position="inline" on an <li> puts its supporting text after its label. A one-line label is the row's label element (<bdi>, <span>): a label written as the row's own text wraps, and is reported in debug builds. The full-text tooltip is a <tanrei-tooltip> the element puts in the row it shows it for. Pinned rows are the rows themselves, held by position: sticky (the element marks the innermost sticky-max parents above what is shown). Editing: edit(item) opens the edit field on an <li> (F2 and a double-click on the label do the same while editable); create({ parent, icon }) adds the new row and returns whether it did; create is dispatched on the tree with detail.label, detail.parent, detail.within and detail.after (the <li> elements, or null). The edit field is a <tanrei-embedded-text-input> the element puts in the row and takes away again; its own change does not leave the row. The new row is an <li data-tanrei-new> of the element's own, as the loading row is. Filter (TRV-54 to TRV-71): the element inserts, before its first list, a box of its own (data-tanrei-filter) holding a <tanrei-text-input type="search" size="small">, the status line (data-tanrei-filter-status, hidden from assistive technology) and a visually hidden status (role="status", aria-atomic="true"), and removes it when filterable becomes false; the input carries aria-controls (the tree), set through the element properties of its native input, and no aria-activedescendant (TRV-61). It hides a row with an attribute of its own on the <li> (data-tanrei-filtered, display: none in tree-view.css; never hidden="until-found", TRV-70) and opens a parent for the filter with another (data-tanrei-filter-open), writing neither data-open nor hidden, and draws the active match with data-tanrei-filter-active on its row. It marks no match and touches none of the product's text nodes (TRV-60). While the filter box is there the tree role is not on the element: a field and a status may not stand inside a tree, so role="tree", its aria-label and aria-multiselectable move to the first root list (the other root lists are owned through ariaOwnsElements), and back to the element when filterable becomes false; a product's own aria-labelledby on the element is not carried over. The field's aria-controls names that list. The filter box carries data-tanrei-sticky where the tree stands in a scrolling box and data-tanrei-stuck while rows scroll under it and none is pinned. filter-shortcut is a space-separated list of chords; filterchange carries detail.value; focusFilter() is the method of TRV-63. TanreiTreeView(_ label: String, selection: Binding<Value?>, density:, showsGuides:, loadingLabel:) { TanreiTreeItem(…) { … } }, with an initializer taking Binding<Set<Value>> for multiple and one without a selection for none, as TanreiList spells its three forms; a data-driven initializer takes a collection and a key path to its children, as the platform's outline views do. Built on a lazy stack of rows, not on List or OutlineGroup, whose rows, disclosure mark and selection are the platform's own look. Not used for the same reason: DisclosureGroup. Semantics: no tree trait exists for custom views; each row is one element with the selected trait and a value of expanded or collapsed, in order; on macOS the row also carries its disclosure level through the AppKit accessibility protocol. On iOS the level is not told (TRV-32's fallback), which the README states. Keys (TRV-19 to TRV-23) apply with a hardware keyboard and on macOS; .focusable() on the tree with a focused-row state gives the single stop. Not yet built: the shared row model — chevron, expandable, guides none/shown/hover, indent auto or a number, iconSpace, iconGap, highlight, one-line labels and notes with their tooltip, supportingPosition, stickyParents and stickyMax, the multi-select keys (TRV-2 to TRV-8, TRV-43, TRV-44, TRV-49 to TRV-53) — and openIcon (TRV-5), and editing in place — the edit field, rename, the method that opens the field and the one that asks for a new row, create (TRV-45 to TRV-48) — are proposed spellings, decided when the platform is built. Filter (TRV-54 to TRV-71), not built yet: as the navigation drawer's on this platform (the field, the polite announcement, the method that focuses the field). TanreiTreeView(label, selection, value, onValueChange, …) { TanreiTreeItem(…) { … } }, controlled; the multiple form takes values: Set<String> and onValuesChange. The scope flattens the shown items into a LazyColumn (the product's scrolling box where it gives none). Semantics: collectionInfo on the tree and collectionItemInfo on each row, selected, stateDescription left to the platform's expanded state through expand() and collapse() actions, disabled(); the platform's hierarchical collection flag where the toolkit exposes it, otherwise the level is not told (TRV-32's fallback), which the README states. Keys through onKeyEvent on the tree with a FocusRequester per shown row and one row in the focus order. Not yet built: the shared row model — chevron, expandable, guides none/shown/hover, indent auto or a number, iconSpace, iconGap, highlight, one-line labels and notes with their tooltip, supportingPosition, stickyParents and stickyMax, the multi-select keys (TRV-2 to TRV-8, TRV-43, TRV-44, TRV-49 to TRV-53) — and openIcon (TRV-5), and editing in place — the edit field, rename, the method that opens the field and the one that asks for a new row, create (TRV-45 to TRV-48) — are proposed spellings, decided when the platform is built. Filter (TRV-54 to TRV-71), not built yet: as the navigation drawer's on this platform (the field, the polite announcement, the method that focuses the field). TanreiTreeView(semanticLabel:, selection:, value:, values:, onChanged:, density:, guides:, loadingLabel:, items: [TanreiTreeItem(…)]). Not built on the framework's TreeSliver or the Material library's ExpansionTile, whose rows and marks are their own look; it may read how the framework's tree lays out and reveals rows. Shrink-wrapped by default; a TanreiTreeView.sliver form builds rows lazily in the product's scroll view. Semantics: the tree and tree-item roles where the framework has them, with expanded, selected and enabled; otherwise one node per row in order with those flags and no level (TRV-32's fallback), stated in the README. Keys through Focus and Shortcuts on the tree with one focus node in the traversal order. Not yet built: the shared row model — chevron, expandable, guides none/shown/hover, indent auto or a number, iconSpace, iconGap, highlight, one-line labels and notes with their tooltip, supportingPosition, stickyParents and stickyMax, the multi-select keys (TRV-2 to TRV-8, TRV-43, TRV-44, TRV-49 to TRV-53) — and openIcon (TRV-5), and editing in place — the edit field, rename, the method that opens the field and the one that asks for a new row, create (TRV-45 to TRV-48) — are proposed spellings, decided when the platform is built. Filter (TRV-54 to TRV-71), not built yet: as the navigation drawer's on this platform (the field, the polite announcement, the method that focuses the field). <TreeView accessibilityLabel="Project files" selection="single" value={…} onChange={…}> with TreeItem children; value is controlled when given, with defaultValue otherwise, and values likewise. Rows are views in a column; a TreeView.Flat form takes the shown rows as data for the product's FlatList. Semantics: accessibilityState={{ expanded, selected, disabled, busy }} on each row and the tree and tree item roles where the platform maps them; the level is not told on iOS and Android (TRV-32's fallback), stated in the README. Keys apply where a hardware keyboard is present (and on the web through React Native for Web). Follows the app's direction where an ancestor's is not known. Not yet built: the shared row model — chevron, expandable, guides none/shown/hover, indent auto or a number, iconSpace, iconGap, highlight, one-line labels and notes with their tooltip, supportingPosition, stickyParents and stickyMax, the multi-select keys (TRV-2 to TRV-8, TRV-43, TRV-44, TRV-49 to TRV-53) — and openIcon (TRV-5), and editing in place — the edit field, rename, the method that opens the field and the one that asks for a new row, create (TRV-45 to TRV-48) — are proposed spellings, decided when the platform is built. Filter (TRV-54 to TRV-71), not built yet: as the navigation drawer's on this platform (the field, the polite announcement, the method that focuses the field).

Tokens

Token Alias de Valor resuelto (claro)
--tanrei-comp-tree-view-chevron-size-compact sys.icon.extra-small 16px
--tanrei-comp-tree-view-chevron-size-regular sys.icon.small 20px
--tanrei-comp-tree-view-container-gap-compact sys.space.space100 8px
--tanrei-comp-tree-view-container-gap-regular sys.space.space150 12px
--tanrei-comp-tree-view-container-height-compact — 32px
--tanrei-comp-tree-view-container-height-regular — 48px
--tanrei-comp-tree-view-container-padding-block-compact — 6px
--tanrei-comp-tree-view-container-padding-block-regular — 12px
--tanrei-comp-tree-view-container-padding-inline-compact sys.space.space100 8px
--tanrei-comp-tree-view-container-padding-inline-regular sys.space.space150 12px
--tanrei-comp-tree-view-container-shape sys.shape.corner.small 6px
--tanrei-comp-tree-view-disabled-opacity — 0.38
--tanrei-comp-tree-view-filter-gap sys.space.space100 8px
--tanrei-comp-tree-view-filter-status-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-tree-view-focused-opacity — 1
--tanrei-comp-tree-view-guide-color sys.color.outline-variant #000000 · 8%
--tanrei-comp-tree-view-guide-width sys.border.hairline 1px
--tanrei-comp-tree-view-hovered-opacity — 1
--tanrei-comp-tree-view-icon-gap sys.space.space150 12px
--tanrei-comp-tree-view-icon-size-compact sys.icon.extra-small 16px
--tanrei-comp-tree-view-icon-size-regular sys.icon.small 20px
--tanrei-comp-tree-view-level-indent-compact sys.space.space300 24px
--tanrei-comp-tree-view-level-indent-regular sys.space.space400 32px
--tanrei-comp-tree-view-motion-disclosure-duration sys.motion.role.disclosure 400ms
--tanrei-comp-tree-view-motion-disclosure-easing sys.motion.easing.spatial cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-tree-view-motion-feedback-duration sys.motion.role.feedback 450ms
--tanrei-comp-tree-view-motion-state-duration sys.motion.role.state.large 250ms
--tanrei-comp-tree-view-motion-state-easing sys.motion.easing.state cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-tree-view-pressed-opacity — 1
--tanrei-comp-tree-view-selected-chevron-color sys.color.on-secondary-container #262626
--tanrei-comp-tree-view-selected-container-color sys.color.secondary-container #262626 · 16%
--tanrei-comp-tree-view-selected-disabled-chevron-color — #262626
--tanrei-comp-tree-view-selected-disabled-container-color — #262626 · 16%
--tanrei-comp-tree-view-selected-disabled-icon-color — #262626
--tanrei-comp-tree-view-selected-disabled-label-color — #262626
--tanrei-comp-tree-view-selected-disabled-state-layer-color — #262626
--tanrei-comp-tree-view-selected-disabled-supporting-text-color — #262626
--tanrei-comp-tree-view-selected-disabled-trailing-text-color — #262626
--tanrei-comp-tree-view-selected-focused-chevron-color — #262626
--tanrei-comp-tree-view-selected-focused-container-color — #262626 · 24.4%
--tanrei-comp-tree-view-selected-focused-icon-color — #262626
--tanrei-comp-tree-view-selected-focused-label-color — #262626
--tanrei-comp-tree-view-selected-focused-state-layer-color — #262626
--tanrei-comp-tree-view-selected-focused-supporting-text-color — #262626
--tanrei-comp-tree-view-selected-focused-trailing-text-color — #262626
--tanrei-comp-tree-view-selected-hovered-chevron-color — #262626
--tanrei-comp-tree-view-selected-hovered-container-color — #262626 · 22.7%
--tanrei-comp-tree-view-selected-hovered-icon-color — #262626
--tanrei-comp-tree-view-selected-hovered-label-color — #262626
--tanrei-comp-tree-view-selected-hovered-state-layer-color — #262626
--tanrei-comp-tree-view-selected-hovered-supporting-text-color — #262626
--tanrei-comp-tree-view-selected-hovered-trailing-text-color — #262626
--tanrei-comp-tree-view-selected-icon-color sys.color.on-secondary-container #262626
--tanrei-comp-tree-view-selected-label-color sys.color.on-secondary-container #262626
--tanrei-comp-tree-view-selected-pressed-chevron-color — #262626
--tanrei-comp-tree-view-selected-pressed-container-color — #262626 · 24.4%
--tanrei-comp-tree-view-selected-pressed-icon-color — #262626
--tanrei-comp-tree-view-selected-pressed-label-color — #262626
--tanrei-comp-tree-view-selected-pressed-state-layer-color — #262626
--tanrei-comp-tree-view-selected-pressed-supporting-text-color — #262626
--tanrei-comp-tree-view-selected-pressed-trailing-text-color — #262626
--tanrei-comp-tree-view-selected-state-layer-color comp.tree-view.selected.label.color #262626
--tanrei-comp-tree-view-selected-supporting-text-color sys.color.on-secondary-container #262626
--tanrei-comp-tree-view-selected-trailing-text-color sys.color.on-secondary-container #262626
--tanrei-comp-tree-view-sticky-container-color sys.color.surface #ffffff
--tanrei-comp-tree-view-sticky-divider-color sys.color.outline-variant #000000 · 8%
--tanrei-comp-tree-view-sticky-divider-width sys.border.hairline 1px
--tanrei-comp-tree-view-unselected-chevron-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-tree-view-unselected-container-color — #000000 · 0%
--tanrei-comp-tree-view-unselected-disabled-chevron-color — #4b4b4b
--tanrei-comp-tree-view-unselected-disabled-container-color — #000000 · 0%
--tanrei-comp-tree-view-unselected-disabled-icon-color — #4b4b4b
--tanrei-comp-tree-view-unselected-disabled-label-color — #1b1b1b
--tanrei-comp-tree-view-unselected-disabled-state-layer-color — #1b1b1b
--tanrei-comp-tree-view-unselected-disabled-supporting-text-color — #4b4b4b
--tanrei-comp-tree-view-unselected-disabled-trailing-text-color — #4b4b4b
--tanrei-comp-tree-view-unselected-focused-chevron-color — #4b4b4b
--tanrei-comp-tree-view-unselected-focused-container-color — #1b1b1b · 10%
--tanrei-comp-tree-view-unselected-focused-icon-color — #4b4b4b
--tanrei-comp-tree-view-unselected-focused-label-color — #1b1b1b
--tanrei-comp-tree-view-unselected-focused-state-layer-color — #1b1b1b
--tanrei-comp-tree-view-unselected-focused-supporting-text-color — #4b4b4b
--tanrei-comp-tree-view-unselected-focused-trailing-text-color — #4b4b4b
--tanrei-comp-tree-view-unselected-hovered-chevron-color — #4b4b4b
--tanrei-comp-tree-view-unselected-hovered-container-color — #1b1b1b · 8%
--tanrei-comp-tree-view-unselected-hovered-icon-color — #4b4b4b
--tanrei-comp-tree-view-unselected-hovered-label-color — #1b1b1b
--tanrei-comp-tree-view-unselected-hovered-state-layer-color — #1b1b1b
--tanrei-comp-tree-view-unselected-hovered-supporting-text-color — #4b4b4b
--tanrei-comp-tree-view-unselected-hovered-trailing-text-color — #4b4b4b
--tanrei-comp-tree-view-unselected-icon-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-tree-view-unselected-label-color sys.color.on-surface #1b1b1b
--tanrei-comp-tree-view-unselected-pressed-chevron-color — #4b4b4b
--tanrei-comp-tree-view-unselected-pressed-container-color — #1b1b1b · 10%
--tanrei-comp-tree-view-unselected-pressed-icon-color — #4b4b4b
--tanrei-comp-tree-view-unselected-pressed-label-color — #1b1b1b
--tanrei-comp-tree-view-unselected-pressed-state-layer-color — #1b1b1b
--tanrei-comp-tree-view-unselected-pressed-supporting-text-color — #4b4b4b
--tanrei-comp-tree-view-unselected-pressed-trailing-text-color — #4b4b4b
--tanrei-comp-tree-view-unselected-state-layer-color comp.tree-view.unselected.label.color #1b1b1b
--tanrei-comp-tree-view-unselected-supporting-text-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-tree-view-unselected-trailing-text-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-tree-view-filter-status-typescale sys.typescale.body-small 400 13px/1.5385
--tanrei-comp-tree-view-label-typescale-compact sys.typescale.body-small 400 13px/1.5385
--tanrei-comp-tree-view-label-typescale-regular sys.typescale.body 400 14px/1.5714
--tanrei-comp-tree-view-supporting-text-typescale sys.typescale.body-small 400 13px/1.5385
--tanrei-comp-tree-view-trailing-text-typescale sys.typescale.body-small 400 13px/1.5385

Fixtures

Representaciones canónicas. Todas las plataformas capturan cada fixture con el mismo identificador para poder comparar los resultados.

Generado a partir de specs/tree-view.spec.json, tokens/comp/tree-view.tokens.json, design/tokens/

Pautas

¿Es una vista de árbol?

Tienes Usa
Una estructura que recorrer o en la que elegir Vista de árbol
Los lugares de un producto, como enlaces Panel de navegación
Los encabezados de una página Tabla de contenido
Contenido plegado bajo unas pocas cabeceras Acordeón
Elementos de un solo nivel Lista

Qué hace una pulsación

El elemento Una pulsación en su fila Una pulsación en su chevron
Se puede elegir, es un padre Lo elige Lo abre o lo cierra
Se puede elegir, es una hoja Lo elige —
No se puede elegir, es un padre Lo abre o lo cierra Lo abre o lo cierra
No se puede elegir, es una hoja Nada —

Una pulsación nunca hace dos cosas. Una persona que elige una carpeta no pierde el punto en que estaba porque además se haya cerrado.

Un elemento se puede elegir cuando selection es single o multiple, tiene un data-value y no está deshabilitado. En una selección única, pulsar de nuevo el elemento elegido no cambia nada. En una selección múltiple, cada elemento se elige por sí solo: elegir un padre no elige lo que contiene.

Lo que hace una elección es cosa tuya. Responde a change para mostrar el archivo elegido, o el editor del token elegido, en un panel junto al árbol. Una fila no contiene ningún control: pon la acción junto al árbol.

La selección y los padres cerrados

El árbol dibuja el relleno de selección en la propia fila del elemento. No marca un padre porque un elemento que tiene debajo esté seleccionado, y no abre un padre cerrado para mostrar una selección. Si el elemento elegido debe estar a la vista, pon data-open en los padres que tiene por encima: tú conoces el camino.

Densidad

density Una fila de una línea Úsala para
regular (predeterminada) 48 Un producto que se usa tanto con el tacto como con un puntero.
compact 32 Una herramienta que se recorre con un puntero, y un árbol pequeño dentro de una página de texto.

Una fila compacta es más baja que el objetivo de puntero. Se acepta porque se pide por su nombre y nunca es el valor predeterminado. Para el tacto, una fila tiene la altura del objetivo táctil en las dos densidades.

Chevron

chevron end: la marca después del valor, como la dibuja un menú

  • src12
    • components9
      • button.ts4 KB
    • index.ts1 KB
  • package.json2 KB
chevron Dónde está Úsalo para
start (predeterminado) Antes del icono; gira un cuarto de vuelta Árboles de archivos y el patrón de árbol.
end Después del texto final; expand_more, que gira media vuelta Ajustes y otros árboles que se leen como un menú: el lugar del cajón de navegación.
none En ningún sitio Carpetas que muestran su estado con su propio glifo.

chevron none: el glifo de la carpeta muestra si está abierta; las guías aparecen bajo el puntero

  • src
    • components
      • button.ts
    • index.ts
  • package.json

Con chevron="none", un padre cuyo icono nombra un glifo abierto (data-open-icon="folder_open") muestra si está abierto o cerrado con su glifo, y una pulsación en el glifo lo abre y lo cierra. Un padre sin icono se abre con una pulsación en su fila, salvo que su fila elija: entonces gana la selección, y las teclas de flecha lo abren. Las teclas de flecha siempre abren y cierran.

expandable="false" quita abrir y cerrar: todos los padres se muestran abiertos, sin chevron ni alternancia, y ninguna fila dice que está expandida o contraída. Úsalo para una estructura que siempre se muestra entera.

Guías

guides="shown" (o el atributo sin valor) dibuja una línea fina que baja desde cada padre abierto, junto a las filas que contiene. guides="hover" solo las dibuja mientras el puntero está sobre el árbol o el foco está en él. Úsalas en un árbol profundo, donde la sangría por sí sola ya no muestra qué filas van juntas. La línea queda bajo el primer elemento inicial del padre: el chevron del inicio; si no, su icono; si no, el comienzo de su etiqueta. No ocupa espacio, y no se dibuja ninguna línea mientras la sangría es 0.

Sangría

indent Dónde empieza un hijo
auto (predeterminado) Donde empieza la etiqueta de su padre: el paso sigue a lo que la fila del padre tiene antes de su etiqueta, el chevron del inicio y el icono. Una fila sin nada antes de su etiqueta mete a sus elementos el token de sangría del nivel.
un número Esos píxeles más adentro que su padre. 0 no mete ningún nivel y no dibuja guías.

Los iconos y su espacio

icon-space="auto" (el predeterminado) reserva el espacio de un icono en una fila sin icono mientras otra fila de su nivel tenga uno, para que las etiquetas de un nivel queden en una columna. always lo reserva en todas las filas, y never solo donde hay icono. icon-gap fija en píxeles el espacio entre el icono y la etiqueta; con auto es el token comp.tree-view.icon.gap, el mismo en las dos densidades.

Resaltado

highlight="indented" (el predeterminado) dibuja el relleno de una fila, su hover y su pulsación y su anillo de foco desde donde empieza su nivel, de modo que el relleno muestra el nivel. highlight="full" los dibuja en todo el ancho del árbol, como los exploradores de archivos. El área de pulsación es todo el ancho en ambos casos.

Una línea

Una etiqueta y su nota ocupan una línea cada una, cortadas con puntos suspensivos donde no caben. Una cortada se muestra entera en un tooltip al pasar el puntero y con el foco del teclado, que Escape oculta; el nombre accesible es siempre la etiqueta entera. label-wrap y supporting-wrap hacen que salten de línea. La nota va debajo de su etiqueta; data-supporting-position="inline" en el <li> la pone después de la etiqueta, en su línea. Da a la etiqueta su elemento (<bdi>): una etiqueta escrita como texto propio de la fila salta de línea.

Padres fijados

En una caja con desplazamiento, las filas de los padres abiertos que están por encima de lo que se ve quedan fijadas arriba mientras sus elementos se desplazan por debajo, como el desplazamiento fijo de un editor. Se fijan como mucho sticky-max filas (2), las de los padres más internos. Son las filas mismas: una pulsación en un padre fijado lo cierra, y una fila a la que el teclado llega bajo ellas se desplaza hasta quedar debajo. sticky-parents="false" lo desactiva. Un árbol que no está en una caja con desplazamiento propia no fija nada.

Elegir varios

Tecla o pulsación En una selección múltiple
Espacio, Enter, una pulsación Elige el elemento o lo quita, y lo hace el ancla.
Mayús+Abajo, Mayús+Arriba Mueve el foco y selecciona desde el ancla hasta la fila con el foco; al volver, el rango se encoge.
Mayús+Espacio, una pulsación con Mayús Selecciona desde el ancla hasta la fila.
Ctrl+Mayús+Inicio, Ctrl+Mayús+Fin Selecciona desde la fila con el foco hasta la primera o la última fila mostrada.
Ctrl+A Selecciona todas las filas mostradas que se pueden elegir.

En las plataformas de Apple, Comando ocupa el lugar de Ctrl. Cada gesto emite un change.

Cambiar nombres y elementos nuevos

Con editable, un doble clic en la etiqueta de una fila, o F2 en una fila con el foco, pone el nombre en un campo de texto, con la parte anterior a la extensión seleccionada. Enter, o salir del campo, da el nombre nuevo; Escape lo descarta. El árbol no cambia ninguna etiqueta por sí mismo: emite rename, y tú pones la etiqueta si aceptas el nombre.

tree.addEventListener('rename', (event) => {
  const li = event.target;
  if (renameFile(li.dataset.value, event.detail.label)) li.querySelector('bdi').textContent = event.detail.label;
});

newFileButton.addEventListener('click', () => tree.create({ icon: 'draft' }));
newFolderButton.addEventListener('click', () => tree.create({ parent: true, icon: 'folder' }));
tree.addEventListener('create', (event) => {
  const li = makeItem(event.detail.label, event.detail.parent);
  event.detail.after ? event.detail.after.after(li) : tree.querySelector('ul').append(li);
});

create() añade una fila propia del árbol junto al elemento seleccionado, en su nivel, con un campo vacío. No se añade nada a tus datos hasta que se da un nombre: create lleva el nombre, y el elemento que añades en respuesta recibe el foco. Escape, o un nombre vacío, no deja nada. Da nombre al campo con edit-label («Nombre») o con setWords({ editLabel }).

Árboles grandes

El árbol muestra lo que se le da, no se desplaza y no dibuja solo las filas que están a la vista. Ponlo en tu propia caja de desplazamiento.

  • Da los elementos de un padre grande cuando se abra: márcalo con data-expandable y añade su <ul> cuando toggle diga que se abrió. Pon data-loading mientras los obtienes.
  • Solo cuestan algo las filas que se muestran. A los elementos de un padre cerrado no se les aplican estilos, no se disponen y no se leen hasta que el padre se abre.
  • Un cambio en una fila vuelve a aplicar estilos solo a esa fila, sea cual sea el tamaño del árbol.

Filtrado

filterable dibuja un campo de filtro encima de la primera fila, fijado en la parte superior de tu caja de desplazamiento, con los padres fijados debajo. Lo que la persona escribe reduce el árbol a las filas cuya etiqueta lo contiene; al vaciar el campo, el árbol vuelve a quedar como estaba.

  • Qué coincide. Una fila coincide cuando su etiqueta contiene todas las palabras escritas, cada una en cualquier lugar y en cualquier orden, sin distinguir mayúsculas de minúsculas, el ancho de un carácter ni los signos diacríticos. Solo se compara la etiqueta, no el texto de apoyo, el texto final ni el valor. No se busca en los elementos de un padre que todavía no los ha recibido (data-expandable).
  • Lo que queda. Las filas que no coinciden se ocultan. Los padres que contienen una coincidencia se quedan, y un padre encontrado por su propio nombre se queda entero.
  • Los padres se abren de forma temporal. Un padre cerrado que contiene una coincidencia se dibuja abierto para el filtro. Su data-open no cambia y no se emite toggle, así que al vaciar el campo vuelve a cerrarse. Un padre que la persona abre o cierra mientras filtra es suyo: se queda como lo dejó.
  • La primera coincidencia está lista para tomarla. Mientras el foco está en el campo, la primera fila que coincide se dibuja como la fila con el foco. No se lee mientras la persona escribe: las tecnologías de apoyo la anuncian cuando Flecha abajo lleva el foco a ella. Enter la toma, como lo haría Enter en esa fila: la elige, o abre o cierra un padre que no se puede elegir. Flecha abajo lleva el foco a esa misma fila, dentro del árbol. Escape vacía el campo; Escape en una fila vacía el filtro y deja a la persona en el elemento que encontró, entre sus vecinos.
  • “/” en una fila lleva el foco al campo; cualquier otra letra sigue llevando a la siguiente fila que empieza por ella. El árbol no escucha esa tecla en ningún otro sitio ni dibuja ninguna pista de ella. filter-shortcut cambia la tecla, y focusFilter() te permite asignar una para toda la ventana.
  • El recuento. Mientras hay un filtro aplicado, una línea discreta al principio de los resultados dice cuántas filas coinciden (filter-count-text), o filter-empty-text cuando no coincide ninguna. filter-count-hidden no dibuja el recuento; se sigue comunicando a la tecnología de apoyo.
  • Las coincidencias no se marcan. Las filas que deja el filtro son la respuesta, así que cada fila se ve igual que sin filtro, como en el árbol de archivos de una revisión de código o en la barra lateral de un sitio de documentación. El árbol nunca toca el texto de tus etiquetas.

Si decides las coincidencias de otra manera (en un servidor, con una clasificación, comparando algo más que la etiqueta), deja filterable desactivado, da al árbol los elementos que coinciden, pon data-open en los padres que los contienen y di cuántos coincidieron en un mensaje de estado propio.

Árboles profundos y ventanas estrechas

Cada nivel empieza más adentro. Donde eso llevaría la etiqueta de una fila más allá de la mitad del ancho del árbol, la fila no entra más de lo que deja su etiqueta en la mitad del ancho, así que los nombres conservan la mitad del ancho. A la tecnología de asistencia se le sigue comunicando el nivel real.

Renderizado en un servidor

Todo se dibuja antes de que el script se cargue, salvo el relleno de selección, que aparece cuando el elemento se define. Para tenerlo en el primer fotograma, escribe tú aria-selected="true" en la fila del elemento seleccionado.

Recomendado

  • Escribe label, loading-label donde algún elemento pueda estar cargándose y edit-label donde se cambien nombres o se nombren elementos nuevos, en el idioma de tu producto. loading-label y edit-label también se pueden dar una sola vez para todo el producto, con setWords({ loadingLabel, editLabel }).
  • Nombra tú los glifos: una carpeta y un archivo son tipos de tu producto, no del árbol.
  • Mantén los nombres enteros. Una etiqueta salta de línea y nunca se corta.

Evita

  • No pongas un enlace, un botón ni un campo en una fila. Ninguna tecla del árbol llega a él.
  • No uses un árbol para las páginas de un sitio. Los enlaces se encuentran por las vías con las que un navegador y un lector de pantalla enumeran los enlaces.
  • No selecciones al mover el foco. Las teclas de flecha mueven; Enter y Espacio eligen.
  • No asignes “/” a otra cosa tuya en las filas de un árbol que se puede filtrar. Pon otra tecla en filter-shortcut, o ninguna.

Accesibilidad

Rol
tree
Etiquetado
The tree is named by label. An item's label (or the text of its label slot) is its accessible name; its supporting text, the text of its trailing content and its trailing text are its description, in that order. A parent carries the expanded or collapsed state, a loading parent is busy, and in a selectable tree an item that can be chosen carries the selected state. The chevron, the icon and the guide lines are decorative. The words of a loading row are the product's (loadingLabel); Tanrei ships none. The edit field is named by editLabel, the product's words ("Name"); a new row is a tree item at its level holding that field. The filter field is a search field named by filterLabel, the product's words, controlling the tree; its clear button is named by filterClearLabel. The field names no active descendant: the active match is read once the person moves to it with Down Arrow. How many rows match is drawn at the top of the results, hidden from assistive technology, and said by a status beside the tree, in the product's filterCountText or filterEmptyText — the one thing the tree announces.
Objetivo mínimo
El área de pulsación cumple el tamaño mínimo de objetivo aunque el tamaño visual sea menor. minimum 32px · pointer 44px · spacing 8px · touch 48px

Teclado

Teclas Acción
Tab / Shift+Tab Moves focus into the tree (to the row focused last, the first selected item that is shown, or the first row) and out of it. The tree is one stop; no row and nothing in a row is another.
Down Arrow / Up Arrow Moves focus to the next or previous row that is shown, whatever its level, without wrapping. Opens nothing and does not change the selection.
Right Arrow (Left Arrow in right-to-left layouts) On a closed parent, opens it; on an open parent, moves focus to the first item it shows; on a leaf, nothing.
Left Arrow (Right Arrow in right-to-left layouts) On an open parent, closes it; on any other row below the first level, moves focus to its parent; on a row of the first level, nothing.
Home / End Moves focus to the first or the last row that is shown.
Enter / Space What a press on the row does: chooses the item where it can be chosen (single: selects it; multiple: adds it to or removes it from the selection); opens or closes a parent that cannot be chosen; nothing on a leaf that cannot be chosen.
* (asterisk) Opens every closed parent among the focused row's siblings. Focus stays.
Printable characters Moves focus to the next shown row whose label begins with the characters typed.
Shift+Down Arrow / Shift+Up Arrow (multiple) Moves focus and selects from the anchor to the focused row; going back shrinks the range.
Shift+Space (multiple) Selects from the anchor to the focused row.
Ctrl+Shift+Home / Ctrl+Shift+End (multiple; Command on Apple platforms) Selects from the focused row to the first or the last row shown, and moves focus there.
Ctrl+A (multiple; Command on Apple platforms) Selects every item that can be chosen among the rows shown.
Escape (over a tooltip) Hides the tooltip of a cut label or note.
F2 WHILE editable is true: opens the edit field on the focused row's name. Enter in the field gives the new name, Escape gives it up, and focus returns to the row.
Enter / Escape (in an edit field) Enter gives the name typed (rename, or create for a new row); Escape gives it up. Leaving the field by Tab or a press elsewhere also gives the name. While an input method is composing, both are the input method's.
/ (the filterShortcut chord, on a row) WHILE filterable is true: moves focus to the filter field. Not taken as type-ahead.
Enter (in the filter field) Takes the first row that matches — the active match, drawn as a focused row while focus stays in the field and not read out until the person moves to it — as Enter on that row would: chooses it, or opens or closes a parent that cannot be chosen.
Down Arrow (in the filter field) Moves focus to the active match itself, where it is read as a focused row.
Escape (in the filter field) With text: empties the field and keeps focus there. Empty: returns focus to the row it came from by "/", or passes on.
Escape (on a row, while a filter is applied) Empties the filter and keeps focus on the row, which stays in place among its neighbours.

Notas

  • A tree view is the tree pattern: one stop in the focus order, the arrow keys moving through the rows that are shown, the horizontal arrows opening, closing and stepping between levels. It is the opposite choice from the navigation drawer and the accordion, on purpose. A drawer navigates: its destinations are links and buttons, each its own stop, found by the ways a browser and a screen reader list links, and its groups are disclosures. An accordion folds content: each header is a button and its own stop, and the arrow keys stay the page's. A tree reveals or selects a hierarchy: it may hold hundreds of rows, which no person should have to Tab through, and what it holds are items of one structure, not controls. Use the drawer for the places of a product, the accordion for folded content, and the tree for a structure a person looks through or chooses in.
  • A row holds no control (TRV-6): the tree role gives each row one name and one action, and a link, a button or a field inside it could be reached by no key of the pattern. An item is therefore not a link and has no destination: a hierarchy of pages is a navigation drawer or a table of contents, which keep the platform's links. What a press on an item does beyond choosing it — opening the chosen file in a pane, showing the chosen token's editor — is the product's answer to change.
  • The chevron opens and the row chooses (TRV-10). Where an item cannot be chosen — every item of a tree whose selection is none, and an item without a value in any tree — the whole row opens and closes it, so that a tree that is only read has rows as easy to hit as an accordion's. One press never does two things: a person who chooses a folder does not lose their place because it also closed.
  • Selection does not follow focus (TRV-20): moving through a tree with the arrow keys changes nothing, so that a person can read it without the pane beside it changing at every row. Enter or Space chooses.
  • The selected state is drawn by the quiet fill, the on-fill color of the label and the glyphs, and the filled form of the icon, as a selected destination of a navigation drawer is; to assistive technology it is the selected state. Under forced colors the row takes the platform's selected colors and an edge (TRV-35). A product that needs each chosen item of a multiple selection to carry a mark of its own puts one in the trailing slot.
  • WCAG 2.5.8 (target size): for touch every row is at least the touch target high in both densities (TRV-26). The compact density is lower than the pointer target for a fine pointer, by design: it is the density of a tool looked through with a mouse, it stays above the 24 by 24 the criterion asks, and its rows reach across the tree's whole width. A product that cannot accept that uses regular.
  • WCAG 1.4.10 (reflow) and 1.4.4 (resize text): labels wrap and are never cut, rows grow, and the indent never takes more than half of the tree's width (TRV-3), so a deep tree stays readable at 320 wide and at 200 % text. Past that depth the indent no longer shows the level; assistive technology is still told it.
  • WCAG 1.4.1 (use of color): open and closed are told by the chevron's turn and by the expanded state, never by color. Disabled is told by the faded row and by the disabled state.
  • WCAG 1.4.3 and 1.4.11 (contrast) in the default system: the label is on-surface and the supporting text, trailing text, icon and chevron are on-surface-variant, on the surface the tree stands on; on the selected fill, a layer of that color over the surface, every part is on-secondary-container. Each pair is held to 4.5:1 by the token invariants, the selected text on its fill as it is drawn over each surface role, and the selected fill stands 1.1:1 at least from a hovered row. The guide lines are decorative: the hierarchy is told by the indent and by the structure.
  • A loading parent is busy and nothing is announced when its items arrive (TRV-13, TRV-33): a person who opened it finds them with the next Down Arrow. A fetch that fails is the product's to say, beside the tree or as an item whose label says it.
  • With filterable, the tree narrows itself to what a person types: the field is a search field before the tree and a stop of its own, so the tree stays one stop; as in a search, the first row that matches is active as soon as there is one while focus stays in the field — drawn as a focused row and, as the search's automatic choice, not read out until the person moves — Enter takes it as Enter on its row would, and Down Arrow moves focus to it, where it is read; the rows a filter hides are gone from what assistive technology is told, so every level, position and size a person hears is the filter's (WCAG 1.3.1); the parents that hold a match are opened for the time being and closed again when the field is emptied, so a filter never rearranges what a person opened; Escape on a row empties the filter and leaves the person on the item they found, among its neighbours. The count is a status message (WCAG 4.1.3), said politely once typing pauses, and drawn quietly at the top of the results unless the product hides it. The rows that match are not marked: what the filter leaves is the answer, and the row Enter takes is drawn as a focused row (TRV-60, TRV-61), so nothing is told by color alone (WCAG 1.4.1). A product that matches in another way — on a server, by a ranking, by more than the label — leaves filterable off, gives the tree the items that match and sets open on the parents that hold them, and says how many matched in a status of its own, as before.
  • The tree does not scroll and does not draw only the rows in view: the product places it in its own scrolling box, and gives a parent's items when it opens (expandable, toggle) where the hierarchy is too large to give at once. A platform that builds rows lazily states each item's level, position and set size where the structure no longer gives them.
  • Web: the items are the product's own nested lists in the document — a `<ul>` of `<li>` elements, each holding its row and, where it is a parent, a `<ul>` of its own — inside `<tanrei-tree-view>`. Without script the page shows the whole hierarchy as the nested list it is, every level shown; with the script the element gives the lists the tree's roles, states and keys. The stylesheet draws the whole look before the element is defined, so nothing moves when it is upgraded.
  • How a state looks is a value decision of the active design system; components read the state's tokens and never compute the effect themselves.
  • Renaming in place follows the file managers people already know: F2 opens the field (Windows Explorer, and VS Code on Windows and Linux), a double-click on the label opens it where the product makes the tree editable, the name without its extension is selected (Finder, Explorer, VS Code), Enter or leaving the field gives the name and Escape gives it up. Enter is not the key that opens the field, as it is in Finder: in the tree pattern Enter chooses (TRV-22), and a tree that renamed on Enter would take the one key that chooses. The tree never changes a label itself: the product owns the data, and the field only proposes a name (rename).
  • A new item is named in a row of its own before it exists (create), as VS Code's explorer names a new file: nothing is added to the product's data until a name is given, and Escape leaves nothing behind. The new row is placed beside the selected item, at its level.
  • A name and a note are one line by default (TRV-6, TRV-7, TRV-50): the whole text is the row's accessible name and description, and while it is cut it is shown in a tooltip on hover and on keyboard focus, which Escape dismisses and the pointer can move into (WCAG 1.4.13). A product whose names must always be read whole on screen sets labelWrap and supportingWrap (WCAG 1.4.10 at 320 wide reads best wrapped).
  • Multiple selection follows the tree pattern: Space and a press toggle one item, Shift with the arrows, Space or a press selects a range from the anchor, Ctrl (Command) with Shift and Home or End to the first or last row, Ctrl (Command) with A everything shown; the tree is multiselectable and every item that can be chosen carries its selected state (TRV-52).
  • Pinned parent rows (TRV-53) are the rows themselves, not copies: assistive technology meets each once, in its place, and a row the keyboard reaches under them is scrolled into view below them.
  • With expandable false the tree is a structure always shown whole: no tree item carries an expanded state, and the groups still tell each level (TRV-49).
  • With chevron none, open and closed are told by the glyph (folder, folder_open) and by the expanded state, never by color; the arrow keys always open and close, and a parent with no glyph is reported in debug builds because nothing on screen tells its state (WCAG 1.3.1, 1.4.1).
  • "/" on a row moves to the filter, and every other printable character keeps moving by type-ahead (TRV-23), as the tree pattern recommends: the two answer different questions — "where is the next row that begins so" and "show me only what holds this".

Generado a partir de specs/tree-view.spec.json, tokens/sys/measure.tokens.json

De qué se encarga el componente

  • El elemento es un tree que recibe su nombre de label. Cada fila es un treeitem y cada lista anidada, un group, de modo que el nivel procede del anidamiento.
  • La fila de un padre lleva aria-expanded. Una fila que se puede elegir lleva aria-selected, true o false. Una fila deshabilitada lleva aria-disabled, y un padre que se está cargando, aria-busy.
  • La etiqueta es el nombre de la fila. El texto de apoyo, el texto del contenido final y el texto final son su descripción, en ese orden.
  • El árbol es una sola parada. Tab entra en él por la fila que tuvo el foco la última vez, o por la primera fila seleccionada que se muestra, o por la primera fila.
  • Flecha abajo y Flecha arriba recorren las filas que se muestran. Flecha derecha abre un padre y después entra en él. Flecha izquierda lo cierra y después sale de él. En un diseño de derecha a izquierda, Flecha izquierda y Flecha derecha se intercambian.
  • Inicio y Fin van a la primera y a la última fila. Al escribir letras, el foco pasa a la siguiente fila cuya etiqueta empieza por ellas. * abre todos los padres cerrados que están al mismo nivel que la fila que tiene el foco.
  • Enter y Espacio hacen lo mismo que una pulsación en la fila. La selección nunca sigue al foco.
  • Con editable, F2 abre un campo de texto sobre el nombre de la fila con el foco. Enter da el nombre y Escape lo descarta, y el foco vuelve a la fila. Mientras un método de entrada está componiendo, ambas teclas son del método de entrada. El campo se nombra con edit-label, y una fila nueva es un elemento del árbol de su nivel que contiene el campo.
  • Con chevron="none", abierto y cerrado se comunican con el glifo y con aria-expanded, nunca solo con el color, y las teclas de flecha siempre abren y cierran. Con expandable="false" ninguna fila lleva aria-expanded; los grupos siguen comunicando el nivel.
  • En una selección múltiple, Mayús con las flechas o con Espacio selecciona un rango desde el ancla, Ctrl (Comando) con Mayús e Inicio o Fin selecciona hasta la primera o la última fila, y Ctrl (Comando) con A selecciona todo lo mostrado.
  • Las filas de los padres fijados son las filas mismas, así que la tecnología de asistencia encuentra cada una una sola vez, en su sitio.
  • Abrir, cerrar y elegir se comunican mediante el propio estado de la fila. No se anuncia nada y el foco no se mueve.
  • Un padre que se cierra con la fila que tiene el foco dentro recibe el foco. Una fila con el foco que se quita da el foco a la fila que la sigue.
  • El anillo de foco se dibuja dentro de la fila, así que una caja de desplazamiento no lo recorta. En una fila deshabilitada se dibuja con toda su intensidad: la fila se atenúa, su anillo no.
  • El chevron, los iconos y las guías quedan ocultos para la tecnología de apoyo. La fila de carga también queda oculta: el padre dice que está ocupado.
  • Una etiqueta y una nota ocupan una línea cada una; una cortada se muestra entera en un tooltip al pasar el puntero y con el foco del teclado, que Escape oculta y al que se puede llevar el puntero, y el nombre accesible es siempre entero. Con label-wrap y supporting-wrap, con el texto al 200% saltan de línea y las filas crecen.
  • Con colores forzados, una fila seleccionada toma los colores de selección del sistema y un borde.
  • El campo del filtro es un campo de búsqueda con el nombre de filter-label, delante del árbol y con su propia parada de tabulación, así que el árbol sigue siendo una sola parada. Indica que controla el árbol y no señala ningún descendiente activo: la primera coincidencia se lee cuando Flecha abajo lleva el foco a ella. Su botón de borrar se nombra con filter-clear-label.
  • Las filas que oculta un filtro desaparecen también para la tecnología de apoyo, así que cada nivel, posición y tamaño que oye la persona son los del filtro. Cuando se deja de escribir durante un segundo, un estado junto al árbol dice cuántas filas coinciden, o que no coincide ninguna, de forma cortés y sin mover el foco: lo único que el árbol anuncia. El recuento dibujado al principio de los resultados está oculto para la tecnología de apoyo, que oye el estado en su lugar.
  • Una fila que coincide no se marca, así que nada se comunica solo con el color, y el nombre de la fila sigue siendo su etiqueta entera.
  • Las compilaciones de depuración notifican un label vacío, un elemento sin etiqueta, una etiqueta escrita como texto propio de la fila, un control en una fila, un valor que no nombra ningún elemento, dos elementos con un mismo valor, un density, selection, chevron, guides, icon-space o highlight desconocidos, un indent o un icon-gap que no es un número, un padre sin icono con chevron="none", un campo sin edit-label, un campo de filtro sin filter-label, un botón de borrar sin nombre y un filter-shortcut de más de una combinación.

Qué debes hacer tú

  • Da a cada elemento que se pueda elegir un data-value que sea único en el árbol.
  • Di tú que una carga ha fallado, junto al árbol o como un elemento cuya etiqueta lo diga. El árbol no anuncia nada cuando llegan los elementos.
  • Da una marca propia en el contenido final donde cada elemento elegido de una selección múltiple deba distinguirse por algo más que su relleno.
  • Pon un árbol largo en una caja de desplazamiento con un nombre o un encabezado, para que las personas sepan qué contiene la caja.
  • Con filterable, da al campo un filter-label que diga qué filtra («Filtrar archivos»), y da tus palabras para filter-count-text, filter-empty-text, filter-clear-label y filter-placeholder, en el árbol o una sola vez con setWords().