Tabla de contenido
Enumera los encabezados de la página que se está leyendo como enlaces a ellos y marca aquel cuya sección se está leyendo. Donde no hay sitio junto al texto, una sola fila da el nombre de la sección actual y abre la misma lista.
- Categoría
- Navegación
- Tokens
comp.table-of-contents- Nivel
- Base
- Web
tanrei-table-of-contentsschedule - SwiftUI
TanreiTableOfContentsradio_button_unchecked - Jetpack Compose
TanreiTableOfContentsradio_button_unchecked - Flutter
TanreiTableOfContentsradio_button_unchecked - React Native
TableOfContentsradio_button_unchecked
Generado a partir de docs/status/status.json, specs/table-of-contents.spec.json
Las secciones de esta página: desplázate y el marcador te sigue
Una tabla de contenido muestra qué contiene una página larga y en qué parte está quien la lee. Cada elemento es un enlace a un encabezado; los subencabezados van con sangría bajo su encabezado. El elemento actual tiene un marcador en la línea guía y una etiqueta de más peso. No es la navegación del producto entre páginas: eso es un panel de navegación.
En la web es <tanrei-table-of-contents> alrededor de tu propia lista anidada de anclas. Las anclas se quedan en el documento, así que, antes de que se ejecute ningún script, la página contiene una lista de enlaces sin más, y funcionan. Las demás plataformas todavía no la han implementado.
<link rel="stylesheet" href="@tanrei/web/table-of-contents.css" />
<tanrei-table-of-contents label="En esta página">
<ul>
<li><a href="#top">Descripción general</a></li>
<li>
<a href="#install">Instalar</a>
<ul>
<li><a href="#npm">npm</a></li>
</ul>
</li>
<li><a href="#configure">Configurar</a></li>
</ul>
</tanrei-table-of-contents>
<script type="module">
import '@tanrei/web/components/table-of-contents';
</script>import { TableOfContents } from '@tanrei/react';
import '@tanrei/web/table-of-contents.css';
<TableOfContents label="En esta página" density="compact">
<ul>
{headings.map((heading) => (
<li key={heading.id}>
<a href={`#${heading.id}`}>{heading.text}</a>
</li>
))}
</ul>
</TableOfContents>@tanrei/web/table-of-contents.css dibuja el título y la lista antes de que se ejecute ningún script, y la lista no se mueve cuando el script se carga. El elemento personalizado añade por sí solo esa misma hoja de estilos a la página. El chevron de la forma compacta es un glifo del conjunto de iconos y necesita la fuente de iconos.
| Parte | En la web |
|---|---|
| El título | El atributo label, en el idioma de tu producto. También da nombre a la región de referencia (landmark) de navegación. |
| Un elemento | Un <li> cuyo primer hijo es su <a href>. La etiqueta es el texto del ancla, como texto sin más. |
| Los elementos propios de un elemento | Un <ul> después del ancla, dentro del mismo <li>. |
| El elemento del principio de la página | Un elemento cuyo href es #top o #. Es el actual hasta que se llega al primer encabezado. |
| Un título que es un encabezado | Un hijo con slot="title", como <h2 slot="title">En esta página</h2>. label sigue dando nombre a la región de referencia. |
| Cuál es el elemento actual | Nada: lo decide el elemento personalizado. Con tracking="manual", pones tú en current el href de un elemento. |
Los elementos se dan, no se descubren. Una página construida por un generador de sitios o por un framework conoce sus encabezados cuando se construye, así que la lista está en la página desde el principio y un rastreador la lee.
| Evento | Cuándo | detail |
|---|---|---|
currentchange |
El elemento actual cambió mientras tracking es auto. |
href: el del nuevo elemento, o una cadena vacía |
select |
Se activó un elemento, antes de que el navegador siga el enlace. Cancélalo para mover la vista por tu cuenta. | href |
toggle |
Quien usa la página mostró u ocultó la lista de la forma compacta. | open |
La forma compacta: pulsa la fila
Anatomía
| Parte | Descripción |
|---|---|
1 title · opcional | What the list is, in the product's words ("On this page"). Text above the list, and the label of the compact form's row. It names the navigation landmark. Not a heading unless the product gives one of its own. |
2 list | The items in the page's order, one column as wide as the layout gives. It has no fill and no edge of its own in the list presentation. |
3 container | One item's row: the part that shows hover, focus and press. It runs from the rail to the list's end edge at every level of nesting, and has no fill at rest. |
4 label | An item's text: the heading it leads to, set in further for each level of nesting. It wraps and is never cut. |
5 rail | One hairline along the list's start edge, as long as the list. The track the marker sits on. Decorative. |
6 marker | A heavier stroke on the rail beside the current item's row, as high as that row. With the label's heavier weight it is what tells the current item from the others. Decorative: the current state is exposed by the item. |
7 disclosure-row · opcional | The compact presentation's row: the title, the name of the current section and a chevron. A button that shows and hides the list below it. |
8 supporting-text · opcional | The name of the current section in the disclosure row, on one line, cut where it does not fit. Empty while no item is current. |
9 icon · opcional | The disclosure row's chevron (expand_more), turned half a turn while the list is shown. Decorative. |
10 focus-ring | The indicator shown for keyboard focus, inside the focused row's container. |
Propiedades
| Propiedad | Tipo | Valor predeterminado | Descripción |
|---|---|---|---|
label | string | "" | The title, in the product's language ("On this page"): drawn above the list and in the compact form's row, and the accessible name of the navigation landmark. Tanrei ships no words of its own. Required; a table of contents without one still renders and is reported (TOC-40). |
labelHidden | boolean | false | True draws no title above the list and keeps label as the landmark's name: for a layout whose own heading already says what the list is. The compact form's row always shows the title, which is that row's label. |
presentation | list | compact | "list" | How the table of contents stands. list: the title and the whole list, for a column beside the text. compact: one row that shows the title and the name of the current section, and opens the same list below it; for a window with no room beside the text. Which one a window width gets is decided by the layout that places it (an app shell, the product), which also decides where it stands and whether it stays in view. |
density | regular | compact | "regular" | How tall a row of the list is, in a table's, an accordion's and a tree view's words; it is not the compact presentation, and applies to the list of either presentation. regular (a 44 row in the default system) holds the pointer target, as every control of the default look does. compact (a 32 row) is for a long list of headings beside the text of a product read with a pointer: it is lower than the pointer target, which is acceptable because it is asked for by name and is never what a product gets by default. For touch a row is never lower than the touch target in either. The label's text style, the indent and the inline padding are the same in both. A design system may add values. |
open | boolean | false | In the compact presentation, whether the list is shown below the row. The web sets it itself when the user opens, closes or chooses; a controlled platform leaves it to the caller. Ignored in the list presentation, where the list is always shown. |
current | string | "" | The href of the item whose section the person is in; empty while none is. While tracking is auto the table of contents sets it by the rule of TOC-9 and tells the product with currentChange; while tracking is manual it is the product's to set. |
tracking | auto | manual | "auto" | Who decides which item is current. auto: the table of contents, from where the items' targets are in the view that scrolls them (TOC-9 to TOC-16). manual: the product, through current — for a page whose sections are not places in one scrolling view (steps shown one at a time, a virtual list), or a product that already knows where its reader is. |
Slots
| Slot | Descripción |
|---|---|
title | The product's own title content in place of the label prop's text above the list: a heading of the level the page's outline needs. Drawn in the title's text style whatever its level; its role and level are kept. label still names the landmark and is still the compact form's row label. No control. |
Eventos
| Evento | Descripción |
|---|---|
currentChange | The current item changed while tracking is auto: by the person's scrolling, by an item being chosen, or by the address naming a target. Carries the new item's href, or an empty string when no item is current. Emitted exactly once per change, never for a value the product set, and never while tracking is manual. |
select | An item was activated by pointer, touch, Enter or assistive technology; carries its href. Emitted before the platform follows the link. A product that moves the view itself (a router, a scroll view the platform's links do not reach) cancels it and moves. |
toggle | The compact presentation's list was shown or hidden: by the user from the row, by an item being chosen, or by Escape; carries the new open. Emitted exactly once per change, when the change begins. |
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 heading of the page: a link to it. An item may hold items, the sub-headings of its section, which are drawn one level further in.
| Propiedad | Tipo | Valor predeterminado | Descripción |
|---|---|---|---|
href | string | "" | The destination: the heading's place on the page. On the web a fragment of the page's address ("#installation"); on the other platforms the identifier the product registered that section's heading under. An item whose destination is the top of the page (on the web the fragment the platform reads as the top) is the item for what comes before the first heading (TOC-10). Required and unique within the table of contents. |
label | string | "" | The heading's text, as plain text: what the item shows and its accessible name. A heading that holds inline code, a tag or a link is given as its text alone. Required. |
| Especificación | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| Elemento | li | TanreiTableOfContentsItem | TanreiTableOfContentsItem | TanreiTableOfContentsItem | TableOfContentsItem |
href · Propiedad | href | id | id | id | id |
label · Propiedad | a | label | label | label | label |
| Notas | An <li> of the product's list whose first child is its anchor, <a href="#installation">Installation</a>: href is the anchor's own attribute and the label its text. The item's own items are a <ul> after the anchor, inside the same <li>. The element writes aria-current="location" on the current item's anchor and removes it from the others; a product that sets tracking="manual" writes it itself or sets the element's current. | TanreiTableOfContentsItem(id:, label:, items: []), a value. id is what the product's headings are registered under. | TanreiTableOfContentsItem(id, label, items = emptyList()), a data class. | TanreiTableOfContentsItem(id: …, label: …, items: const []), a value. | An object of the items prop: { id, label, items? }. |
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 |
|---|---|
TOC-1 | THE table of contents SHALL lay out, in the list presentation, its title and below it, comp.table-of-contents.container.gap away, its items in one column in the order given, each item's own items directly after it and before the item that follows it, the whole as wide as the layout it is placed in; it SHALL draw no fill, no edge and no padding of its own around them, SHALL NOT place itself, keep itself in view or limit its own width, and SHALL NOT decide its presentation from the window: where it stands, that it stays while the page scrolls, and which presentation a width gets are the layout's that places it. |
TOC-2 | WHILE labelHidden is false THE table of contents SHALL draw its title above the list in comp.table-of-contents.title.typescale and comp.table-of-contents.title.color: the label's text, or the content of the title slot where the product filled it, drawn in the same style whatever its level and keeping its role and level. WHILE labelHidden is true THE table of contents SHALL draw no title in the list presentation and SHALL still name its landmark by label (TOC-31). |
TOC-3 | THE table of contents SHALL draw each item as a row whose container runs from the rail to the list's end edge at every level of nesting, at least as high as its density gives (comp.table-of-contents.row.height.regular for regular and comp.table-of-contents.row.height.compact for compact) and as high as its label needs, with corners comp.table-of-contents.row.shape, holding its label in comp.table-of-contents.label.typescale with the padding of its density above and below it (comp.table-of-contents.row.padding-block.regular for regular and comp.table-of-contents.row.padding-block.compact for compact), comp.table-of-contents.row.padding-inline after it, and before it comp.table-of-contents.row.padding-inline plus comp.table-of-contents.row.indent for each level of nesting; only the label is set in, so that every row's state layer, focus ring and marker start at the same edge and the marker of a nested item sits on the one rail. Rows follow one another with no space between them, so that no place between two rows takes no press. Density changes a row's height and nothing else: the label's text style, where it starts and the rail are the same in both. |
TOC-4 | THE table of contents SHALL wrap a label that is wider than its row onto further lines that start where its first line starts, breaking where the label's language allows a break and, for a run with no such place that is longer than the line (a long identifier, an address), inside the run; in the list it SHALL NOT cut a label, draw an ellipsis or scroll sideways, and the row SHALL grow by the lines it holds. |
TOC-5 | THE table of contents SHALL draw the rail along the list's start edge, from the top of the first row to the bottom of the last, comp.table-of-contents.rail.width wide in comp.table-of-contents.rail.color, once for the whole list and not once per level, and SHALL hide it from assistive technology. |
TOC-6 | THE table of contents SHALL make each item the platform's own link to its href (on the web an anchor element in the document itself, kept there and not copied into a shadow root; on the other platforms an element with the platform's link semantics), exposing the link role, so that whatever the platform gives a link — on the web its context menu, copying its address, opening it in a new tab, a crawler that reads it, and a list of links that works before any script has run — is the platform's; it SHALL draw an item's label without an underline, because an item is a row of a list in a navigation landmark and is not told from text beside it, and SHALL NOT draw a visited state. |
TOC-7 | WHILE an item is current THE table of contents SHALL draw that item's row from the tokens of the current part in place of the item part's, its label at the weight of comp.table-of-contents.label.typescale plus sys.typescale.emphasis.body, and the marker on the rail beside that row, as high as the row, comp.table-of-contents.marker.width wide in comp.table-of-contents.marker.color, covering the rail there; at most one item SHALL be drawn as current, an item that holds the current item SHALL be drawn as any other item, and no row's lines SHALL break at another place and no row SHALL change its height because an item became or stopped being current, so that the list does not move while the page scrolls. WHEN the current item changes THE table of contents SHALL change the two rows over comp.table-of-contents.motion.state-duration with comp.table-of-contents.motion.state-easing, and at once where motion is reduced; the marker SHALL NOT travel between rows. |
TOC-8 | THE table of contents SHALL expose the current item as the current location within its set (on the web aria-current with the value location; a platform without that state, the selected state) and every other item without it; WHEN the current item changes THE table of contents SHALL announce nothing, so that scrolling a page is not narrated. |
TOC-9 | WHILE tracking is auto THE table of contents SHALL take as current the last item, in the page's order, whose target has reached the line, where an item's target is the place its href leads to in the view that scrolls it, the line is where that target comes to rest when a link moves the view to it — the view's start edge, below whatever the product keeps fixed there, plus the space the target keeps before itself (PRS-23) — and a target has reached the line when its start edge is at the line or before it, within one unit of the platform's layout; WHILE no target has reached the line THE table of contents SHALL have no current item. It SHALL NOT take an item as current because its target is merely in view. |
TOC-10 | WHERE an item's destination is the top of the page (on the web a fragment the platform reads as the top of the document; elsewhere the identifier the product registered for the start of the content) THE table of contents SHALL treat its target as having always reached the line, so that it is current from the start of the page until the first heading reaches the line and the part before the first heading has a name. |
TOC-11 | WHILE tracking is auto, the view has room to scroll and is at the end of its range THE table of contents SHALL take the last item as current, whether or not its target has reached the line, because a last section shorter than the view never can; WHEN the view leaves the end of its range THE rule of TOC-9 SHALL apply again. A view with no room to scroll SHALL follow TOC-9 and TOC-10 alone. |
TOC-12 | WHEN the user activates an item by pointer, touch, Enter or assistive technology THE table of contents SHALL emit select exactly once with that item's href and then, unless the product cancelled it, let the platform follow the link as it follows any link (on the web the browser moves the view and the address; the table of contents SHALL NOT scroll the view itself and SHALL NOT hold the navigation back for sys.motion.duration.press-hold); WHILE tracking is auto it SHALL make that item current at once and keep it current while the view moves to the target and after it has arrived — also where the target cannot reach the line — until the view next moves by the person's own scrolling (a wheel, a drag, a key, the scroll bar), from which TOC-9 to TOC-11 apply again. While the view moves to the target THE table of contents SHALL NOT mark the items it passes. |
TOC-13 | WHEN the table of contents first appears while the page's address names the target of one of its items, or the address comes to name one while it is shown (a link elsewhere on the page, a heading's own anchor, a step back or forward in the history), THE table of contents SHALL, WHILE tracking is auto, make that item current and keep it as TOC-12 keeps a chosen item; it SHALL draw that item as current in its first drawing where the platform knows the address then, and SHALL NOT show another item as current first. |
TOC-14 | THE table of contents SHALL add no motion of the view of its own: whether the view glides or jumps to a target is the platform's and the product's (on the web the page's own scroll behaviour, which the product turns off where motion is reduced), and TOC-12 holds for either. It SHALL NOT write the address, add an entry to the history or move the view because the person scrolled. |
TOC-15 | WHILE tracking is manual THE table of contents SHALL draw and expose as current the item whose href equals current, and none WHILE current is empty; it SHALL NOT observe the view, SHALL NOT change current and SHALL NOT emit currentChange, and SHALL still emit select and follow links as TOC-12 says. WHILE tracking is auto and the product sets current THE table of contents SHALL draw that item as current until the rule next gives another. |
TOC-16 | WHEN the place of a target changes without the person scrolling — content above it loads or is folded away, the window is resized, the text size changes, an item is added or removed — THE table of contents SHALL, WHILE tracking is auto, decide the current item again by TOC-9 to TOC-11, keeping an item that TOC-12 or TOC-13 is holding. IF an item's href leads to no place on the page THE table of contents SHALL still draw it as a link, SHALL never take it as current by the rule, and in debug builds report it. |
TOC-17 | WHEN the current item changes while its row is not wholly inside the visible part of a scrolling region that holds the list — the table of contents' own in the compact presentation (TOC-27), or the layout's — THE table of contents SHALL scroll that region, and no other, by the least distance that shows the row whole, at once where motion is reduced; it SHALL NOT scroll the view that holds the targets, and SHALL NOT scroll the list WHILE the pointer is over it or keyboard focus is inside it, so that a row is not moved from under a hand. |
TOC-18 | WHILE an item's row or the disclosure row is hovered, keyboard-focused or pressed THE table of contents SHALL render that row's container, label and opacity from the component tokens of the highest-precedence active state of its part (item, current or disclosure), with precedence pressed over focused over hovered; hover and press anywhere on a row SHALL answer on that row's container; focus gained by pointer or touch SHALL NOT select the focused state. |
TOC-19 | WHEN a row receives keyboard focus THE table of contents SHALL show the focus ring without animation inside that row's container, following comp.table-of-contents.row.shape, sys.focus.outer-width wide with the inner stroke of sys.focus.inner-width where the system has one, so that the ring is not cut by the neighbouring rows or by the edge of a scrolling region; focus gained by pointer or touch SHALL NOT show it. |
TOC-20 | WHEN an item's row is pressed by pointer, touch or Enter, or the disclosure row by pointer, touch, Enter or Space, THE table of contents SHALL show the pressed state without delay and SHALL keep it visible for at least sys.motion.duration.press-hold, even when the press ends sooner. Space on an item does what it does on any link (on the web it scrolls the page) and SHALL NOT show the pressed state. |
TOC-21 | WHILE pressed THE table of contents 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 from the point of contact (from the center for keyboard activation); dim applies the pressed opacity to the whole control 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, opacity and shape still come from the pressed tokens. Under none every part stays with the state under the press. The ripple grows over comp.table-of-contents.motion.feedback-duration with motion.state-easing, fades over motion.state-duration with motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced. |
TOC-22 | THE table of contents SHALL ease its rows' container corners and the compact form's 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 its 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. |
TOC-23 | THE table of contents SHALL change a row between its states over comp.table-of-contents.motion.state-duration with comp.table-of-contents.motion.state-easing, and at once where motion is reduced. |
TOC-24 | THE table of contents SHALL make each row its hit area across the list's whole width, whatever the level of its label, 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 (comp.table-of-contents.row.height.compact), the one place where a row of the list is lower than the pointer target: the density is asked for by name and is never the default; the disclosure row SHALL be at least comp.table-of-contents.compact.row.height high and never lower than sys.target.touch for touch or sys.target.pointer for a fine pointer. |
TOC-25 | WHILE presentation is compact THE table of contents SHALL draw one block as wide as its layout, filled with comp.table-of-contents.compact.container.color with corners comp.table-of-contents.compact.container.shape, holding first the disclosure row: at least comp.table-of-contents.compact.row.height high, comp.table-of-contents.compact.row.padding-inline at its start and end, and in reading order, comp.table-of-contents.compact.row.gap apart, the title in comp.table-of-contents.title.typescale in the disclosure part's label color, the current item's label in comp.table-of-contents.compact.supporting-text.typescale and comp.table-of-contents.compact.supporting-text.color taking the room that is left, on one line and cut with an ellipsis at the end of its own direction where it does not fit, and at the row's end the icon set's expand_more in a box of comp.table-of-contents.compact.icon.size in comp.table-of-contents.compact.icon.color, turned half a turn WHILE open is true. WHILE no item is current the row SHALL show the title and the chevron alone. The title SHALL NOT be cut before the current item's label has been cut to nothing. |
TOC-26 | WHEN the user activates the disclosure row by pointer, touch, Enter or Space THE table of contents SHALL emit toggle exactly once with the new open and, where it owns open, show or hide the list: WHILE open is true the list of TOC-3 to TOC-7 is drawn below the row inside the block, comp.table-of-contents.compact.list.padding-inline from the block's start and end edges and with comp.table-of-contents.compact.list.padding-block below it, the block growing and what follows it in the layout moving; WHILE open is false the list is not drawn, not exposed to assistive technology and not focusable. The change SHALL take comp.table-of-contents.motion.disclosure-duration with comp.table-of-contents.motion.disclosure-easing, the chevron turning with it, and happen at once where motion is reduced. The table of contents SHALL NOT draw a scrim, SHALL NOT keep focus inside itself and SHALL NOT close because a press landed outside it: whether an open list that the layout keeps over the text closes on such a press is that layout's, through open. |
TOC-27 | WHILE presentation is compact and open is true THE table of contents SHALL NOT let its block be taller than the room its layout gives it: where the list needs more, the list SHALL scroll inside the block while the disclosure row stays in place, and WHEN the list is shown THE table of contents SHALL bring the current item's row into its visible part without a motion (TOC-17). |
TOC-28 | WHEN the user activates an item WHILE presentation is compact THE table of contents SHALL hide the list (emitting toggle with false) and follow the link as TOC-12 says, and SHALL NOT move keyboard focus to the disclosure row: the next move of focus continues from the section that was chosen, as it does after any link to a place on the page. |
TOC-29 | WHEN the user presses Escape WHILE presentation is compact, open is true and keyboard focus is on the disclosure row or inside the list THE table of contents SHALL hide the list, emit toggle with false, and move focus to the disclosure row where it was inside the list. Moving focus out of the table of contents by Tab SHALL NOT hide the list. |
TOC-30 | WHEN presentation changes while the table of contents is shown THE table of contents SHALL keep its current item, draw the new presentation at once without a motion of its own, set open to false without emitting toggle, and keep keyboard focus on the item it was on where that item is still shown, moving it to the disclosure row where it is not. |
TOC-31 | THE table of contents SHALL expose itself as a navigation landmark named by label, holding its items as a list in which an item's own items are a list inside that item, each item one link named by its label with its position in its list; the rail, the marker and the chevron SHALL be hidden from assistive technology. WHILE presentation is compact THE table of contents SHALL expose the disclosure row as one button named by label, described by the current item's label, with its expanded or collapsed state, controlling the list. The title SHALL be exposed once: as the landmark's name, and as a heading only where the product gave a heading in the title slot. |
TOC-32 | IF the table of contents has no items THE table of contents SHALL draw nothing, take no space and expose nothing, in either presentation — no title, no landmark and no disclosure row — so that a page without headings has no empty list. IF it has one item THE table of contents SHALL render as it does for several. |
TOC-33 | WHILE the text size is enlarged THE table of contents SHALL grow its title, its labels and the disclosure row's texts with it, keep its paddings, comp.table-of-contents.row.indent, comp.table-of-contents.rail.width and comp.table-of-contents.marker.width, wrap its labels as TOC-4 says and let its rows and the disclosure row grow in height; nothing SHALL be cut in the list, and at twice the text size every label SHALL still be readable in a column that held it at the ordinary size. |
TOC-34 | 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 table of contents SHALL draw its items' labels in the platform's link color, the current item's label, the title and the disclosure row's texts in the platform's text color, the rail and the marker in the platform's text color with the marker kept comp.table-of-contents.marker.width wide and drawn as a stroke the mode does not remove, the compact form with an edge in the platform's text color in place of its fill, and its focus ring in the platform's highlight color. |
TOC-35 | WHERE the layout direction is right-to-left THE table of contents SHALL mirror its layout and apply its paddings by logical start and end: the rail and the marker at the right edge, each level's label set in further from the right, lines aligned to the right, and in the disclosure row the title at the right, the current item's label after it and the chevron at the left. The chevron SHALL NOT be mirrored: it turns, and shows no direction along the line. |
TOC-36 | THE table of contents 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 table of contents is shown THE table of contents SHALL draw itself for the new direction at once, without a motion of its own, keeping its current item, its open and its focus. |
TOC-37 | THE table of contents SHALL lay out its title, each item's label and the current item's label in the disclosure row each as text of its own direction, isolated from the text around it: it takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right name, a version or a number keeps its own order in a right-to-left layout and reorders nothing beside it; THE table of contents SHALL still place each text and align its lines by the layout direction, so that the labels of one level start at one edge whatever language each is in. |
TOC-38 | WHILE the system's icon set cannot yet draw the chevron (its font is still loading) THE table of contents SHALL draw nothing in its place, never the glyph's name as text, and SHALL keep its box, so that the disclosure row's texts do not move when the glyph appears. |
TOC-39 | WHEN presentation or tracking names a value the table of contents does not have THE table of contents SHALL behave as the default value (list, auto), and WHEN density names a value that the active design system does not have it SHALL render with the default density's tokens; in debug builds it SHALL report the unknown value. WHEN density changes while the table of contents is shown THE table of contents SHALL draw the new heights at once, keeping its current item, its open state and its focus. IF current names no item's href WHILE tracking is manual THE table of contents SHALL draw no item as current and in debug builds report it. IF two items have the same href THE table of contents SHALL render both, take the first as the one that can be current, and in debug builds report it. IF items nest more than three levels deep THE table of contents SHALL still render them, setting each level's label in by comp.table-of-contents.row.indent, and in debug builds report the depth. |
TOC-40 | IF label is empty THE table of contents SHALL still render, drawing no title and, in the compact presentation, a disclosure row that shows the current item's label alone, and in debug builds report that the landmark and the row have no name, unless the product names the landmark (TOC-41). IF an item's label is empty THE table of contents SHALL NOT draw that item or its items, and in debug builds report it. |
TOC-41 | WHERE the platform has ARIA attributes (the web), WHEN the product sets an aria- attribute on the host, by the attribute or by the ARIA property that reflects it, THE table of contents SHALL move it to the data-aria- attribute of the same name, so that the host is no second node with its name, description or state, and SHALL expose it on its navigation landmark — an id reference by the elements it names in the host's tree or a tree around it, a description after its own. WHILE label is not empty it is the landmark's name, over a name given so; WHILE label is empty, a name given so names the landmark, and the compact disclosure row by that name followed by the current item's label it shows, so that the row's name holds what it draws; neither is then reported as having no name (TOC-40). WHEN the product removes the aria- attribute or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaDescribedByElements…) to null, THE table of contents SHALL take it off that element. |
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-table-of-contents | TanreiTableOfContents | TanreiTableOfContents | TanreiTableOfContents | TableOfContents |
label · Propiedad | label | label | label | label | label |
labelHidden · Propiedad | label-hidden | labelHidden | labelHidden | labelHidden | labelHidden |
presentation · Propiedad | presentation | presentation | presentation | presentation | presentation |
density · Propiedad | density | density | density | density | density |
open · Propiedad | open | isOpen | open | open | open |
current · Propiedad | current | current | current | current | current |
tracking · Propiedad | tracking | tracking | tracking | tracking | tracking |
currentChange · Evento | currentchange | current | onCurrentChange | onCurrentChanged | onCurrentChange |
select · Evento | select | onSelect | onSelect | onSelected | onSelect |
toggle · Evento | toggle | isOpen | onOpenChange | onOpenChanged | onOpenChange |
| Notas | Form: <tanrei-table-of-contents label="On this page"> around the product's own list in the light DOM — <tanrei-table-of-contents label="On this page"><ul><li><a href="#install">Install</a><ul><li><a href="#npm">npm</a></li></ul></li></ul></tanrei-table-of-contents>. The anchors stay in the document (TOC-6): before the element is defined, and with scripting off, the page holds a plain nested list of links that work, which a crawler, a search index and a static site generator's own heading list all read and write as they are; nothing is copied, and a framework that renders the list keeps owning it. The element has a small shadow root that holds only what the product did not write — a <nav> named by label around the title, the disclosure row (a <button> with aria-expanded and aria-controls) and one <slot> for the list — so the landmark, the title and the compact form need no markup from the product; the title slot takes the product's heading. Everything drawn on the list comes from one stylesheet of the package, @tanrei/web/table-of-contents.css, whose selectors start at tanrei-table-of-contents and are wrapped in :where(): it styles the list before definition too, so the list presentation does not change place when the script loads. Before definition the compact presentation shows its whole list (there is no row yet); a layout that must not show that for a moment hides tanrei-table-of-contents[presentation="compact"]:not(:defined) itself. Level is the nesting of the <ul>s; the label's inset is padding-inline-start computed from a depth custom property the stylesheet sets per nested list. The marker is the anchor's ::before on the rail (a border-inline-start, so forced colors keep it, TOC-34); the heavier weight of the current label must not reflow the list (TOC-7) — reserve the heavier text's width with a hidden copy of the label (::after with content: attr(data-label), written by the element) or an equivalent the three engines agree on. Tracking (TOC-9 to TOC-16): the element resolves each anchor's fragment with document.getElementById, finds the nearest scrolling ancestor of the targets (else the viewport), and reads the line from each target's own computed scroll-margin-block-start plus the view's scroll-padding-block-start, which is where the browser itself rests a target — so prose's heading margin (PRS-23) and the product's fixed header are declared once, in CSS, and never passed to the element. It decides on scroll through one passive listener coalesced to a frame (or an IntersectionObserver per target; no frame is asked for at rest), on resize, and through a ResizeObserver on the scrolled content (TOC-16). TOC-12's hold begins on the anchor's click and on hashchange/popstate, and ends at the first wheel, touchmove, scrolling key or scroll-bar press after scrollend (a timer where scrollend is missing). The element never calls scrollIntoView on a target and never writes location.hash; TOC-17 uses scrollTo on the list's own scroll container only. TOC-28: the element blurs nothing and focuses nothing; it closes the list after the browser has taken the fragment navigation, which sets the sequential focus starting point at the target. select is dispatched from the anchor's click and is cancelable, cancelling the click with it. toggle carries detail.open; currentchange carries detail.href. A list that the product builds from a container's headings is the product's (or its site generator's) to build; the package may export a function that returns the nested items of a container's h2 to h4, and the element does not read headings itself. React: TableOfContents takes items ({ href, label, items? }[]) and renders the same element and list, or children. | TanreiTableOfContents(label:, items:, current: Binding<String>, presentation:, isOpen: Binding<Bool>, tracking:, onSelect:). Targets are registered by a modifier on the product's heading views, .tanreiTableOfContentsTarget(id), inside a scroll view marked .tanreiTableOfContentsView(line:), which reports each target's place in the scroll view's coordinate space through a preference; the table of contents applies TOC-9 to TOC-16 to those places and writes current. onSelect is given the id and the product scrolls (a ScrollViewReader proxy or scrollPosition(id:)); TOC-12's hold ends at the next drag of the scroll view. An accessibility container with the navigation role where the platform has one, the items as links (isLink) with isSelected for current; the row is a button whose value is expanded or collapsed. | TanreiTableOfContents(label, items, current, onCurrentChange, presentation, open, onOpenChange, tracking, onSelect, state). rememberTanreiTableOfContentsState() holds the targets' places: headings register with Modifier.tanreiTableOfContentsTarget(state, id) (onGloballyPositioned), a lazy list registers the indices of its headings, and the state applies TOC-9 to TOC-16 from the scroll state it is given. onSelect is given the id and the product scrolls (animateScrollToItem, bringIntoView). Items have the link semantics a link annotation has (Compose has no link role for a clickable node) and selected for current; the row has the expanded state with the expand and collapse actions. | TanreiTableOfContents(label: …, items: …, current:, onCurrentChanged:, presentation:, open:, onOpenChanged:, tracking:, onSelected:, controller:). A TanreiTableOfContentsController is given the page's ScrollController; headings are wrapped in TanreiTableOfContentsTarget(id: …), whose render object's offset in the scrollable is read after layout, and the controller applies TOC-9 to TOC-16. onSelected is given the id and the product scrolls (Scrollable.ensureVisible). Semantics(link: true, selected: …) for items, expanded for the row; on the web target of Flutter the address is the product's router's. | <TableOfContents label="…" items={…} current={…} onCurrentChange={…} />. useTableOfContents() returns what the page's ScrollView and its headings need — an onScroll handler, an onLayout per heading id, and the line — and applies TOC-9 to TOC-16 to them; onSelect is given the id and the product scrolls (scrollTo). accessibilityRole="link" with accessibilityState.selected for items, accessibilityState.expanded for the row. Follows the app's direction where an ancestor's is not known. |
Tokens
| Token | Alias de | Valor resuelto (claro) |
|---|---|---|
--tanrei-comp-table-of-contents-compact-container-color | sys.color.surface-container | |
--tanrei-comp-table-of-contents-compact-container-shape | sys.shape.corner.small | 6px |
--tanrei-comp-table-of-contents-compact-icon-color | sys.color.on-surface-variant | |
--tanrei-comp-table-of-contents-compact-icon-size | sys.icon.small | 20px |
--tanrei-comp-table-of-contents-compact-list-padding-block | sys.space.space100 | 8px |
--tanrei-comp-table-of-contents-compact-list-padding-inline | sys.space.space200 | 16px |
--tanrei-comp-table-of-contents-compact-row-gap | sys.space.space100 | 8px |
--tanrei-comp-table-of-contents-compact-row-height | — | 48px |
--tanrei-comp-table-of-contents-compact-row-padding-inline | sys.space.space200 | 16px |
--tanrei-comp-table-of-contents-compact-supporting-text-color | sys.color.on-surface-variant | |
--tanrei-comp-table-of-contents-container-gap | sys.space.space100 | 8px |
--tanrei-comp-table-of-contents-current-container-color | — | |
--tanrei-comp-table-of-contents-current-focused-container-color | — | |
--tanrei-comp-table-of-contents-current-focused-label-color | — | |
--tanrei-comp-table-of-contents-current-focused-state-layer-color | — | |
--tanrei-comp-table-of-contents-current-hovered-container-color | — | |
--tanrei-comp-table-of-contents-current-hovered-label-color | — | |
--tanrei-comp-table-of-contents-current-hovered-state-layer-color | — | |
--tanrei-comp-table-of-contents-current-label-color | sys.color.on-surface | |
--tanrei-comp-table-of-contents-current-pressed-container-color | — | |
--tanrei-comp-table-of-contents-current-pressed-label-color | — | |
--tanrei-comp-table-of-contents-current-pressed-state-layer-color | — | |
--tanrei-comp-table-of-contents-current-state-layer-color | comp.table-of-contents.current.label.color | |
--tanrei-comp-table-of-contents-disclosure-container-color | — | |
--tanrei-comp-table-of-contents-disclosure-focused-container-color | — | |
--tanrei-comp-table-of-contents-disclosure-focused-label-color | — | |
--tanrei-comp-table-of-contents-disclosure-focused-state-layer-color | — | |
--tanrei-comp-table-of-contents-disclosure-hovered-container-color | — | |
--tanrei-comp-table-of-contents-disclosure-hovered-label-color | — | |
--tanrei-comp-table-of-contents-disclosure-hovered-state-layer-color | — | |
--tanrei-comp-table-of-contents-disclosure-label-color | sys.color.on-surface | |
--tanrei-comp-table-of-contents-disclosure-pressed-container-color | — | |
--tanrei-comp-table-of-contents-disclosure-pressed-label-color | — | |
--tanrei-comp-table-of-contents-disclosure-pressed-state-layer-color | — | |
--tanrei-comp-table-of-contents-disclosure-state-layer-color | comp.table-of-contents.disclosure.label.color | |
--tanrei-comp-table-of-contents-focused-opacity | — | 1 |
--tanrei-comp-table-of-contents-hovered-opacity | — | 1 |
--tanrei-comp-table-of-contents-item-container-color | — | |
--tanrei-comp-table-of-contents-item-focused-container-color | — | |
--tanrei-comp-table-of-contents-item-focused-label-color | — | |
--tanrei-comp-table-of-contents-item-focused-state-layer-color | — | |
--tanrei-comp-table-of-contents-item-hovered-container-color | — | |
--tanrei-comp-table-of-contents-item-hovered-label-color | — | |
--tanrei-comp-table-of-contents-item-hovered-state-layer-color | — | |
--tanrei-comp-table-of-contents-item-label-color | sys.color.on-surface-variant | |
--tanrei-comp-table-of-contents-item-pressed-container-color | — | |
--tanrei-comp-table-of-contents-item-pressed-label-color | — | |
--tanrei-comp-table-of-contents-item-pressed-state-layer-color | — | |
--tanrei-comp-table-of-contents-item-state-layer-color | comp.table-of-contents.item.label.color | |
--tanrei-comp-table-of-contents-marker-color | sys.color.primary | |
--tanrei-comp-table-of-contents-marker-width | sys.border.thick | 2px |
--tanrei-comp-table-of-contents-motion-disclosure-duration | sys.motion.role.disclosure | 400ms |
--tanrei-comp-table-of-contents-motion-disclosure-easing | sys.motion.easing.spatial | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-table-of-contents-motion-feedback-duration | sys.motion.role.feedback | 450ms |
--tanrei-comp-table-of-contents-motion-state-duration | sys.motion.role.state.large | 250ms |
--tanrei-comp-table-of-contents-motion-state-easing | sys.motion.easing.state | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-table-of-contents-pressed-opacity | — | 1 |
--tanrei-comp-table-of-contents-rail-color | sys.color.outline-variant | |
--tanrei-comp-table-of-contents-rail-width | sys.border.hairline | 1px |
--tanrei-comp-table-of-contents-row-height-compact | — | 32px |
--tanrei-comp-table-of-contents-row-height-regular | — | 44px |
--tanrei-comp-table-of-contents-row-indent | sys.space.space150 | 12px |
--tanrei-comp-table-of-contents-row-padding-block-compact | — | 6px |
--tanrei-comp-table-of-contents-row-padding-block-regular | — | 12px |
--tanrei-comp-table-of-contents-row-padding-inline | sys.space.space150 | 12px |
--tanrei-comp-table-of-contents-row-shape | sys.shape.corner.extra-small | 3px |
--tanrei-comp-table-of-contents-title-color | sys.color.on-surface | |
--tanrei-comp-table-of-contents-compact-supporting-text-typescale | sys.typescale.body-small | 400 13px/1.5385 |
--tanrei-comp-table-of-contents-label-typescale | sys.typescale.body-small | 400 13px/1.5385 |
--tanrei-comp-table-of-contents-title-typescale | sys.typescale.label | 500 14px/1.4286 |
Fixtures
Representaciones canónicas. Todas las plataformas capturan cada fixture con el mismo identificador para poder comparar los resultados.
density: regular (22)
flat
label: On this page items: 4 single
label: On this page items: 1 nested
label: On this page items: 4 current-top-level
label: On this page current: #anatomy tracking: manual items: 3 current-nested
label: On this page current: #label tracking: manual items: 3 three-levels
label: On this page items: 2 current-third-level
label: On this page current: #schemes tracking: manual items: 2 top-item
label: On this page current: #top tracking: manual items: 3 current-last
label: On this page current: #check tracking: manual items: 4 long-labels
label: On this page current: #derived tracking: manual items: 3 label-hidden
label: On this page labelHidden: true current: #configure tracking: manual items: 3 compact-closed
label: On this page presentation: compact current: #label tracking: manual items: 3 compact-closed-no-current
label: On this page presentation: compact tracking: manual items: 2 compact-long-current
label: On this page presentation: compact current: #derived tracking: manual items: 2 compact-open
label: On this page presentation: compact open: true current: #label tracking: manual items: 3 Dibujado por separado en una ventana de 272 × 308compact-open-long-labels
label: On this page presentation: compact open: true current: #generated tracking: manual items: 2 Dibujado por separado en una ventana de 272 × 320rtl
label: في هذه الصفحة current: #label tracking: manual direction: rtl items: 3 rtl-ltr-labels
label: في هذه الصفحة current: #config tracking: manual direction: rtl items: 2 rtl-compact-closed
label: في هذه الصفحة presentation: compact current: #anatomy tracking: manual direction: rtl items: 2 rtl-compact-open
label: في هذه الصفحة presentation: compact open: true current: #container tracking: manual direction: rtl items: 2 Dibujado por separado en una ventana de 272 × 220japanese
label: このページの内容 current: #states tracking: manual items: 3 japanese-compact-closed
label: このページの内容 presentation: compact current: #states tracking: manual items: 2 density: compact (6)
density-compact-nested
label: On this page density: compact items: 4 density-compact-three-levels
label: On this page density: compact items: 2 density-compact-current
label: On this page density: compact current: #label tracking: manual items: 3 density-compact-long-labels
label: On this page density: compact current: #derived tracking: manual items: 3 density-compact-open
label: On this page presentation: compact density: compact open: true current: #label tracking: manual items: 3 Dibujado por separado en una ventana de 272 × 248density-compact-rtl
label: في هذه الصفحة density: compact current: #label tracking: manual direction: rtl items: 3 Generado a partir de specs/table-of-contents.spec.json, tokens/comp/table-of-contents.tokens.json, design/tokens/
Úsala en una página más larga que una pantalla y dividida por encabezados. Una página sin encabezados no lleva ninguna: sin elementos, el componente no dibuja nada y no deja una región de referencia vacía. Para moverse entre páginas, usa un panel de navegación; para los pasos de una misma tarea, usa unos pasos.
El componente ocupa la anchura que recibe y no decide nada sobre su lugar. Lo decide el diseño de página que lo contiene:
- dónde se sitúa, y que se mantenga a la vista mientras la página se desplaza (una columna adhesiva, o sticky, por ejemplo);
- qué presentación recibe una ventana: pon
presentation="compact"donde no haya sitio junto al texto; - una columna con desplazamiento alrededor de una lista larga. El componente mantiene entonces a la vista su fila actual dentro de esa columna.
density |
Una fila de una línea | Úsalo para |
|---|---|---|
regular (predeterminado) |
44, el objetivo del puntero | La mayoría de las páginas. |
compact |
32 | Una lista larga de encabezados junto al texto, en un producto que se usa con un puntero. |
Una fila compact es más baja que el objetivo del puntero. Es aceptable 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. El estilo de texto y la sangría son los mismos en las dos.
El elemento actual es el último, en el orden de la página, cuyo encabezado ha llegado al lugar donde el navegador deja un encabezado al que se le envía. El componente lee ese lugar de tu CSS:
html { scroll-padding-top: 4rem; } /* lo que mantienes fijo en la parte superior */
h2, h3 { scroll-margin-top: 1.5rem; } /* el espacio que un encabezado mantiene por encima */| Caso | El actual es |
|---|---|
| Antes del primer encabezado | Ninguno, o el elemento del principio de la página donde hayas dado uno. |
| Al final de la página | El último elemento. Una última sección más corta que la ventana nunca podría llegar a la línea. |
| Se eligió un elemento | Ese elemento, de inmediato, hasta que quien lee vuelva a desplazarse a mano. |
| La dirección indica un encabezado | Ese elemento, que se mantiene del mismo modo. |
| Un contenido situado encima de un encabezado se carga o se pliega | Se decide de nuevo. |
El componente nunca desplaza la página y nunca escribe la dirección. Que la página se deslice o salte hasta un encabezado depende de tu scroll-behavior.
Pon tracking="manual" donde las secciones no sean lugares de una misma vista con desplazamiento, como unos pasos que se muestran de uno en uno, y define current tú.
presentation="compact" es un solo bloque con relleno que tiene una fila: el título, el nombre de la sección actual y un chevron. La fila es un botón que muestra la misma lista debajo de ella.
- Elegir un elemento cierra la lista y sigue el enlace.
- Escape la cierra y devuelve el foco a la fila.
- Da al elemento personalizado un
max-block-size: la lista se desplaza entonces por dentro y la fila se queda en su lugar. - No es una superposición. No dibuja ningún velo y no se cierra con una pulsación fuera. Un diseño de página que la mantiene sobre el texto y quiere ese comportamiento pone
openenfalsepor su cuenta.
Hasta que el script se ha cargado, la forma compacta muestra su lista entera. Un diseño de página que no deba mostrar eso ni un momento oculta tanrei-table-of-contents[presentation="compact"]:not(:defined).
- Escribe
labelen el idioma de tu producto. Una página con dos tablas de contenido da a cada una su propio nombre. - Da los encabezados que quieres que se muestren: normalmente, los de segundo y tercer nivel.
- Da un elemento para el principio de la página donde el texto que precede al primer encabezado sea largo.
- No pongas un control, un tag ni un icono en un elemento. Una etiqueta es el texto del encabezado.
- No anides más de tres niveles: las etiquetas de una columna estrecha se quedan sin sitio.
- No la uses como navegación del producto. Su estado actual dice «esta parte de esta página», no «esta página».
- Rol
navigation- Etiquetado
- A navigation landmark named by label ("On this page"), in the product's language; a page with a second table of contents gives each another name. Inside it a list of links, each named by its item's label, sub-headings as a list inside their heading's item. The current item carries the current-location state and nothing is added to its name. In the compact presentation the disclosure row is a button named by label, described by the current item's label, with its expanded state. The title is drawn text and the landmark's name; it is a heading only where the product gave one.
- 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 through the items in order, each one a stop, as through any list of links; in the compact presentation to the disclosure row, and through the items only while the list is shown. |
| Enter | On an item: follows the link to its heading. On the disclosure row: shows or hides the list. |
| Space | On the disclosure row: shows or hides the list. On an item it does what it does on any link (on the web it scrolls the page). |
| Escape | In the compact presentation, while the list is shown and focus is on the row or in the list: hides the list and returns focus to the row. |
Notas
- The current item is exposed as a location, not as a page. Every item of a table of contents leads to the page the person is already on, so the state that says "the current page" would be true of all of them and is the one the product's navigation uses for the page itself; the state for the current location within a context says what is meant: this part, of this page. The bare true value says less than either. A screen reader that does not know the value announces the item as current, which is still right.
- A change of the current item is not announced (TOC-8). It follows from the person's own scrolling or from the link they chose, and a live region would narrate every heading a reader scrolls past. The state is there when they move to the list.
- The items are plain links in the focus order, one stop each, with no arrow-key movement of their own: a table of contents is a list of links in a landmark, which assistive technology already lets people list, skip and move through, and a composite widget would take those keys away. A product places a skip link before a long one, or places the table of contents after the content in the reading order.
- Current is never told by color alone (TOC-7): the marker is a stroke heavier than the rail in primary, which the token invariants hold to 4.5:1 on every surface role of the default system (13.3:1 at the least today; 3.1:1 at the least in the shipped presets), and the label is heavier by the system's emphasis. The rail is decorative and is not held to 3:1, as a divider's line is not. Item labels are secondary text on a surface and the current label primary text, both held to 4.5:1 by the token invariants.
- The target (TOC-24), WCAG 2.5.8. A row's hit area is the list's whole width and the row's height, with no space between rows. For touch a row is drawn at least the touch target high in both densities. For a fine pointer a regular row, the default, is the pointer target high (44 in the default system). The compact density is lower than the pointer target (32), by design: it is the density a product asks for by name where a long list of headings must fit beside the text, it stays above the 24 by 24 the criterion asks, and its rows reach across the list's whole width. A product that cannot accept that uses regular.
- The items are not underlined (TOC-6). An underline is what tells a link from the text beside it in a sentence (WCAG 1.4.1); a row of a list inside a navigation landmark has no text beside it to be told from, as a navigation drawer's destination has not.
- Keyboard focus after choosing an item goes with the page (TOC-28): the next Tab starts from the chosen section. The table of contents never pulls focus back to itself and never moves it into the content.
- Text must remain readable at 200% text size: labels wrap and rows grow (TOC-33); only the current section's name in the compact row is ever cut, and it is whole in the list below it.
- Motion: the table of contents moves nothing but its own compact list and its state changes, each at once where motion is reduced (TOC-7, TOC-23, TOC-26). Whether the page glides to a heading is the product's setting, not this component's (TOC-14).
- A page with no headings has no table of contents: no empty landmark is left for assistive technology to find (TOC-32).
- How a state looks is a value decision of the active design system (a state-layer mix in Tanrei, a dim or no hover at all elsewhere). The table of contents reads the state's tokens and never computes the effect itself.
Generado a partir de specs/table-of-contents.spec.json, tokens/sys/measure.tokens.json
- Es una región de referencia (landmark) de navegación que recibe su nombre de
labely contiene listas anidadas de enlaces. - El elemento actual lleva
aria-current="location". Su cambio no se anuncia, de modo que el desplazamiento no se narra. - Cada elemento es un enlace en el orden del foco, con una parada cada uno. Enter lo sigue. No hay ningún movimiento con las teclas de flecha que aprender.
- La línea guía, el marcador y el chevron están ocultos para la tecnología de apoyo.
- El título se expone una sola vez, como nombre de la región de referencia. Es un encabezado solo donde hayas dado uno en el slot
title. - La fila compacta es un botón que recibe su nombre de
labely su descripción del nombre de la sección actual, con su estado expandido. - Después de elegir un elemento, el foco se queda con la página: el siguiente Tab continúa desde el encabezado elegido.
- El anillo de foco se dibuja dentro de la fila, así que una columna con desplazamiento no lo recorta.
- Cuál es el actual no se comunica solo con el color: el marcador es un trazo y la etiqueta tiene más peso.
- La lista no se mueve cuando cambia el elemento actual.
- Con el texto al 200%, las etiquetas saltan de línea y las filas crecen. Lo único que llega a cortarse es el nombre de la sección actual en la fila compacta.
- Con colores forzados, los elementos tienen el color de los enlaces, y la etiqueta actual, la línea guía y el marcador tienen el color del texto.
- Las compilaciones de depuración notifican un
labelvacío, un elemento sin etiqueta, dos elementos con un mismohref, unhrefque no lleva a ningún sitio, un valor desconocido y más de tres niveles.
- Da un
ida cada encabezado que enumeres, y escribe el mismo fragmento en elhrefdel elemento. - Declara con
scroll-padding-toplo que mantienes fijo en la parte superior, para que un encabezado no quede oculto debajo cuando un enlace lleve la página hasta él. - Desactiva el desplazamiento suave donde quien lee pida movimiento reducido.
- Pon una tabla de contenido larga después del contenido en el orden de lectura, o da un enlace de salto antes de ella.