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
InicioComponentesTooltip

Tooltip

Describe un elemento en pocas palabras cuando una persona lo señala con el puntero, le da el foco con el teclado o lo mantiene pulsado, sin tomar el foco ni bloquear nada.

content_copyVer en Markdown
Categoría
Comunicación
Tokens
comp.tooltip
Nivel
Base

Descripción general

Web
tanrei-tooltip
schedule
SwiftUI
tanreiTooltip
schedule
Jetpack Compose
TanreiTooltip
schedule
Flutter
TanreiTooltip
schedule
React Native
Tooltip
schedule

Generado a partir de docs/status/status.json, specs/tooltip.spec.json

Apunta a un botón o dale el foco: un tooltip y uno rich

deleteinfo

Uso

El ancla es un elemento tuyo: un botón de icono, una etiqueta truncada, una marca de un gráfico. El tooltip le añade una descripción y no cambia nada más de ella. Envuelve el ancla en la web, Compose, Flutter y React Native, y es un modificador del ancla en SwiftUI.

El tooltip se abre y se cierra solo, al pasar el cursor, con el foco del teclado y con la pulsación larga, y lo notifica mediante toggle. Tú defines open únicamente para mostrarlo por tu cuenta, como una pista de primer uso. Definirlo no emite nada, y el tooltip sigue abriéndose y cerrándose solo después.

describes (true de forma predeterminada) convierte el texto en la descripción accesible del ancla. Ponlo en false cuando el texto repita el propio nombre del ancla, como ocurre con un botón de icono cuyo tooltip muestra su etiqueta, para que los lectores de pantalla no lean las palabras dos veces.

Los ejemplos de Web y React muestran la especificación actual. SwiftUI, Compose, Flutter y React Native van rezagados: todavía ofrecen la revisión anterior del tooltip, que tiene cuatro colocaciones centradas y no tiene retardos por tooltip, desplazamientos, flecha, segundo aspecto ni atajo, y que aparece con un fundido sin crecer. Sus ejemplos muestran esa revisión hasta que se pongan al día.

<!-- El tooltip envuelve su ancla. no-describe es describes en false: el texto repite la etiqueta. -->
<tanrei-tooltip text="Mover a la papelera" no-describe>
  <tanrei-button variant="text" label="Mover a la papelera"><span slot="icon">delete</span></tanrei-button>
</tanrei-tooltip>

<!-- Una barra de herramientas densa que quiere sus nombres antes. Los retardos van en milisegundos. -->
<tanrei-tooltip text="Negrita" show-delay="150" no-describe>
  <tanrei-button variant="text" label="Negrita"><span slot="icon">format_bold</span></tanrei-button>
</tanrei-tooltip>

<!-- Las teclas del comando después de su nombre. El ancla las lleva para la tecnología de apoyo. -->
<tanrei-tooltip text="Negrita" shortcut="mod+b" no-describe>
  <tanrei-button variant="text" label="Negrita"><span slot="icon">format_bold</span></tanrei-button>
</tanrei-tooltip>

<!-- Debajo del control, alineado con su borde de inicio, con una flecha, sobre una superficie en lugar de inverso. -->
<tanrei-tooltip text="Filtrar por fecha o por propietario" placement="bottom-start" arrow inverse="false">
  <tanrei-button variant="text" label="Filtrar"><span slot="icon">filter_list</span></tanrei-button>
</tanrei-tooltip>

<tanrei-tooltip id="storage" variant="rich" headline="Almacenamiento" placement="bottom"
                text="Los archivos de la papelera siguen contando para tu almacenamiento hasta que se eliminan.">
  <tanrei-button variant="text" label="Acerca del almacenamiento"><span slot="icon">info</span></tanrei-button>
</tanrei-tooltip>

<script type="module">
  import '@tanrei/web/components/tooltip';
  const storage = document.querySelector('#storage');
  // Una pista de primer uso. Definir open no emite nada.
  storage.open = true;
  // toggle notifica lo que el tooltip hizo por sí solo: cursor, foco, pulsación larga, Escape, el tiempo de espera, otro tooltip.
  storage.addEventListener('toggle', (e) => console.log(e.detail.open));
</script>
import { Button, Tooltip } from '@tanrei/react';

<Tooltip text="Mover a la papelera" describes={false}>
  <Button variant="text" label="Mover a la papelera" onClick={trash}><span slot="icon">delete</span></Button>
</Tooltip>
{/* Las teclas del comando después de su nombre: una combinación por cadena. */}
<Tooltip text="Negrita" shortcut={['mod+b']} describes={false}>
  <Button variant="text" label="Negrita" onClick={bold}><span slot="icon">format_bold</span></Button>
</Tooltip>
{/* Debajo del control, alineado con su borde de inicio, con una flecha, sobre una superficie en lugar de inverso. */}
<Tooltip text="Filtrar por fecha o por propietario" placement="bottom-start" arrow inverse={false}>
  <Button variant="text" label="Filtrar" onClick={filter}><span slot="icon">filter_list</span></Button>
</Tooltip>
<Tooltip
  variant="rich"
  headline="Almacenamiento"
  text="Los archivos de la papelera siguen contando para tu almacenamiento hasta que se eliminan."
  placement="bottom"
  touchTimeout={4000} // unas pocas frases necesitan más tiempo de lectura tras una pulsación larga
  onToggle={(e) => log(e.detail.open)}
>
  <Button variant="text" label="Acerca del almacenamiento"><span slot="icon">info</span></Button>
</Tooltip>
import Tanrei

// Un modificador del ancla. .tanreiTheme(_:) por encima de ella aloja la capa en la que se dibuja el tooltip.
// La descripción pasa a ser el accessibilityHint del ancla.
TanreiIconButton("Mover a la papelera", action: trash) { Image(systemName: "trash") }
    .tanreiTooltip("Mover a la papelera", describes: false)

// isPresented es open; el tooltip lo escribe cuando se abre o se cierra solo.
TanreiIconButton("Acerca del almacenamiento", action: {}) { Image(systemName: "info.circle") }
    .tanreiTooltip("Los archivos de la papelera siguen contando para tu almacenamiento hasta que se eliminan.",
                   title: "Almacenamiento", variant: .rich, placement: .bottom, isPresented: $showHint)
import io.github.chnotchy.tanrei.components.TanreiIconButton
import io.github.chnotchy.tanrei.components.TanreiTooltip
import io.github.chnotchy.tanrei.components.TanreiTooltipPlacement
import io.github.chnotchy.tanrei.components.TanreiTooltipVariant
import io.github.chnotchy.tanrei.components.rememberTanreiTooltipState
import io.github.chnotchy.tanrei.primitives.TanreiText

// Como el TooltipBox de Material: el tooltip envuelve su ancla.
TanreiTooltip(text = "Mover a la papelera", describes = false) {
    TanreiIconButton(onClick = ::trash, contentDescription = "Mover a la papelera") { TanreiText("delete") }
}

// El estado es open. onToggle oye lo que el tooltip hace por sí solo; show() y dismiss() no emiten nada.
val hint = rememberTanreiTooltipState(onToggle = { open -> log(open) })
TanreiTooltip(
    text = "Los archivos de la papelera siguen contando para tu almacenamiento hasta que se eliminan.",
    variant = TanreiTooltipVariant.Rich,
    title = "Almacenamiento",
    placement = TanreiTooltipPlacement.Bottom,
    state = hint,
) {
    TanreiIconButton(onClick = {}, contentDescription = "Acerca del almacenamiento") { TanreiText("info") }
}
LaunchedEffect(Unit) { hint.show() } // una pista de primer uso
import 'package:tanrei/tanrei.dart';

// show() y hide() definen open y no avisan a nadie. Los listeners oyen lo que el tooltip hace por sí solo.
final TanreiTooltipController hint = TanreiTooltipController();
hint.addListener(() => log(hint.isOpen));

// Como el Tooltip de Flutter: message es el texto, y excludeFromSemantics es describes, invertido.
TanreiTooltip(
  message: 'Mover a la papelera',
  excludeFromSemantics: true, // el texto repite el propio nombre del botón
  child: TanreiIconButton(onPressed: trash, icon: const Icon(AppSymbols.delete), semanticLabel: 'Mover a la papelera'),
);
TanreiTooltip(
  variant: TanreiTooltipVariant.rich,
  title: 'Almacenamiento',
  message: 'Los archivos de la papelera siguen contando para tu almacenamiento hasta que se eliminan.',
  placement: TanreiTooltipPlacement.bottom,
  controller: hint, // hint.show() para una pista de primer uso
  child: TanreiIconButton(onPressed: info, icon: const Icon(AppSymbols.info), semanticLabel: 'Acerca del almacenamiento'),
);
import { IconButton, Tooltip } from '@tanrei/react-native';

// El ancla es UN hijo que acepta las propiedades de un Pressable. El tooltip añade sus controladores y llama primero a los del ancla.
<Tooltip text="Mover a la papelera" describes={false}>
  <IconButton accessibilityLabel="Mover a la papelera" onPress={trash}>delete</IconButton>
</Tooltip>

// open lo muestra desde tu código y no emite nada; onOpenChange oye lo que hace por sí solo.
<Tooltip
  variant="rich"
  headline="Almacenamiento"
  text="Los archivos de la papelera siguen contando para tu almacenamiento hasta que se eliminan."
  placement="bottom"
  open={showHint}
  onOpenChange={setShowHint}
>
  <IconButton accessibilityLabel="Acerca del almacenamiento">info</IconButton>
</Tooltip>

Especificaciones

Un tooltip debajo de su ancla y uno rich sin título

deleteinfo

Anatomía

Parte Descripción
1 anchor The element the tooltip describes: the product's own (an icon-only Button, a truncated label, a chart mark). The tooltip adds a description to it and changes nothing else about it.
2 container The surface that holds the text, placed on one side of the anchor and aligned along it.
3 arrow · opcional A triangle on the container's edge that faces the anchor, pointing at it; one shape with the container.
4 title · opcional A short heading above the supporting text. Rich tooltips only.
5 supporting-text The description. A plain tooltip holds nothing else.
6 shortcut · opcional The keys that perform the anchor's command, after the text. Plain tooltips only.

Propiedades

Propiedad Tipo Valor predeterminado Descripción
variant plain | rich "plain" Plain is one short phrase, by default on the inverse surface, for naming what an icon does. Rich is an optional title and a few sentences, by default on a raised surface, for explaining a term or a setting. A structural choice drawn by code, not a token axis: a design system cannot add a form by values.
text string "" The description. Required.
title string "" A heading for a rich tooltip. Ignored by a plain one.
shortcut strings The keyboard shortcut of the anchor's command, in the keyboard shortcut component's key names: one chord per string, pressed in order (["mod+b"]). A plain tooltip draws it after the text for the keyboard the person uses and exposes it as the anchor's keyboard shortcut (TIP-27); a rich one ignores it. It does not make the keys work; the product binds them.
placement top | top-start | top-end | bottom | bottom-start | bottom-end | start | start-top | start-bottom | end | end-top | end-bottom | auto "top" Where the tooltip prefers to stand: a side of the anchor, and how it lines up along that side (TIP-22). top and bottom centre it above or below the anchor; with -start or -end its start or end edge meets the anchor's. start and end centre it beside the anchor; with -top or -bottom its top or bottom edge meets the anchor's. auto takes the first side with room (TIP-23). Start and end follow the layout direction. The tooltip flips to the opposite side when the preferred one has no room, keeping the alignment (TIP-9).
offset number null The distance between the anchor's edge and the tooltip, in the platform's layout units; 0 lets them touch. Null takes comp.tooltip.offset, the system's answer for every tooltip. Set it only where one anchor's box is not what the eye takes for its edge (a control with a large invisible hit area, a mark of a chart).
crossOffset number 0 How far the tooltip moves along the side it stands on, in the platform's layout units, from where placement puts it: positive towards the end for a tooltip above or below, towards the bottom for one beside. For lining an aligned tooltip up with what is drawn inside the anchor rather than with the anchor's box. It never moves the tooltip off the anchor's side (TIP-24).
arrow boolean null Whether the tooltip draws an arrow that points at the anchor. Null, the default, takes comp.tooltip.arrow.visible, the system's choice, which is off in the default system (TIP-25).
inverse boolean null Whether this tooltip is drawn inverse: in the opposite scheme's colors, so that it stands apart from whatever it lands on. False draws it on a surface of the scheme. Null, the default, takes its form's choice: comp.tooltip.plain.container.inverse (on in the default system) or comp.tooltip.rich.container.inverse (off). It changes colors and elevation only (TIP-26).
describes boolean true Whether assistive technology reads the text as the anchor's description. Set it to false when the text repeats the anchor's own accessible name (an icon-only Button whose tooltip shows its label), so that it is not read twice.
open boolean false Whether the tooltip is showing. The tooltip opens and closes itself on hover, focus and long-press and reports it (toggle). A product sets it to show a tooltip on its own (a first-run hint); a snapshot harness sets it to draw a fixture.
showDelay number null How long, in milliseconds, a fine pointer rests on the anchor before this tooltip opens; 0 opens it at once. Null takes comp.tooltip.motion.show-delay, the system's answer for every tooltip. Set it only where one tooltip needs another pace than the rest (a dense toolbar that wants its names sooner, a chart whose marks the pointer sweeps across and should not flash). It applies to hover alone: keyboard focus still opens at once.
hideDelay number null How long, in milliseconds, this tooltip waits after the pointer has left the anchor, the gap and the tooltip before it closes; 0 closes it at once. Null takes comp.tooltip.motion.hide-delay. The tooltip stays hoverable at any value, 0 included, because the gap between the anchor and the tooltip counts as hover (TIP-1).
touchTimeout number null How long, in milliseconds, a tooltip opened by a long-press stays after the finger lifts; 0 closes it as the finger lifts, so it shows for as long as the press lasts. Null takes comp.tooltip.timeout.touch. Set it only where one tooltip needs more or less reading time on touch than the rest (a rich tooltip of a few sentences, a one-word name).

Slots

Slot Descripción
default The anchor.

Eventos

Evento Descripción
toggle The tooltip opened or closed by itself (hover, focus, long-press, Escape, the touch timeout, another tooltip opening); carries the new open value.

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
TIP-1 WHEN a fine pointer enters the anchor and stays on it for the show delay (TIP-17) THE tooltip SHALL open; WHEN the pointer leaves the anchor THE tooltip SHALL stay open while the pointer crosses the gap to the tooltip or moves onto the tooltip itself, and SHALL close once the pointer has been off the anchor, the gap and the tooltip for the hide delay (TIP-17). The gap is the strip between the anchor's edge and the container — the offset deep (TIP-24), and comp.tooltip.arrow.height deeper while an arrow is drawn (TIP-25) — as wide as the container along that side; it counts for hover alone, is not drawn and takes no press.
TIP-2 WHEN the anchor receives keyboard focus THE tooltip SHALL open without delay, and WHEN the anchor loses focus THE tooltip SHALL close; focus gained by pointer or touch SHALL NOT open it.
TIP-3 WHEN the user long-presses the anchor by touch THE tooltip SHALL open without activating the anchor, and WHEN the finger lifts SHALL stay open for the touch timeout (TIP-17) and then close; a touch anywhere else SHALL close it sooner.
TIP-4 WHILE the tooltip is open, WHEN the user presses Escape THE tooltip SHALL close without moving focus and SHALL consume the key, so that it does not also close an enclosing dialog; it SHALL stay closed until the anchor is entered by the pointer or focused again.
TIP-5 WHILE the pointer is over the anchor or the tooltip, or the anchor has keyboard focus, THE tooltip SHALL stay open with no time limit, until Escape (TIP-4), an activation of the anchor (TIP-6) or another tooltip opening (TIP-8) closes it.
TIP-6 WHEN the anchor is activated (a click, a tap, Enter or Space) THE tooltip SHALL close, and SHALL NOT open again from the same hover until the pointer has left the anchor and entered it again.
TIP-7 WHEN the tooltip opens or closes by itself (TIP-1 to TIP-6, TIP-8) THE tooltip SHALL emit toggle with the new value; WHEN the product sets open THE tooltip SHALL show or hide accordingly without emitting toggle, and SHALL then keep following TIP-1 to TIP-6.
TIP-8 WHEN a tooltip opens while another tooltip is open THE other tooltip SHALL close at once, and the new one SHALL open without waiting for its show delay (TIP-17), because the person is already reading tooltips; at most one tooltip SHALL be open in a window.
TIP-9 THE tooltip SHALL place its container on the side of the anchor and with the alignment that placement names (TIP-22, TIP-23), the offset away from the anchor's edge and moved along the side by crossOffset (TIP-24), and SHALL keep it at least comp.tooltip.window-margin inside the window's safe area by these steps, in this order: WHEN the preferred side has no room for the container and the opposite side has, it SHALL flip to the opposite side, keeping the alignment; WHEN neither has room it SHALL use the one of the two with more room; it SHALL then shift along the side as far as the margin asks and no farther; and WHERE the container is still larger than the room on its side (a window smaller than the tooltip) it SHALL move the container back into the margin over the anchor, its top and start edges first, rather than leave the window. It SHALL follow the anchor when the anchor moves (scrolling, resizing, layout), taking these steps again from the side it is on, which it SHALL keep for as long as that side has room, so that a page that scrolls does not throw the tooltip from side to side; and it SHALL close WHEN the anchor is removed, hidden, scrolled out of the window, or scrolled out of sight inside a scrolling ancestor so that no part of it can be seen.
TIP-10 WHILE variant is plain THE tooltip SHALL draw text in comp.tooltip.plain.supporting-text.typescale and comp.tooltip.plain.supporting-text.color on a container of comp.tooltip.plain.container.color with comp.tooltip.plain.container.shape corners and comp.tooltip.plain.container.elevation — or, WHILE it is drawn on a surface, in the colors and the elevation TIP-26 names in their place — padded by comp.tooltip.plain.container.padding-inline and comp.tooltip.plain.container.padding-block, at least comp.tooltip.plain.container.min-height tall and at most comp.tooltip.plain.container.max-width wide, wrapping longer text onto further lines; it SHALL draw its shortcut as TIP-27 says and SHALL ignore title.
TIP-11 WHILE variant is rich THE tooltip SHALL draw title in comp.tooltip.rich.title.typescale and comp.tooltip.rich.title.color above text in comp.tooltip.rich.supporting-text.typescale and comp.tooltip.rich.supporting-text.color, comp.tooltip.rich.container.gap apart, on a container of comp.tooltip.rich.container.color with comp.tooltip.rich.container.shape corners and comp.tooltip.rich.container.elevation — or, WHILE it is drawn inverse, in the colors and the elevation TIP-26 names in their place — padded by comp.tooltip.rich.container.padding-inline and comp.tooltip.rich.container.padding-block and at most comp.tooltip.rich.container.max-width wide; WHILE title is empty it SHALL draw the supporting text alone. THE tooltip SHALL set the title's letter-spacing by the script of its text, as every title is set (PRS-20): no negative letter-spacing WHERE its language is Chinese, Japanese or Korean, and none WHERE its script joins its letters or stacks marks on them.
TIP-12 THE tooltip SHALL ease its 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), SHALL grow with enlarged text without clipping it, and SHALL start-align its text by the layout direction.
TIP-13 THE tooltip SHALL NOT take focus, SHALL hold nothing focusable or pressable, SHALL NOT make anything inert or dimmed, and SHALL be drawn above every other layer of its window, including an open dialog and its scrim; a press on the tooltip SHALL close it and SHALL NOT reach what lies under it.
TIP-14 WHILE describes is true THE tooltip SHALL expose text — preceded by title for a rich tooltip — as the anchor's accessible description, whether or not the tooltip is open, and SHALL keep the drawn tooltip from being read a second time; WHILE describes is false it SHALL add nothing to the anchor's semantics. In both cases it SHALL NOT change the anchor's accessible name or role.
TIP-15 WHEN the tooltip opens THE tooltip SHALL appear as every surface appears: from sys.motion.appear.opacity, sys.motion.appear.scale, sys.motion.appear.distance toward its anchor and sys.motion.appear.blur to whole, grown from the middle of its edge that faces the anchor — from its own centre WHERE sys.motion.appear.origin is center, and WHILE it covers its anchor (TIP-9) — over comp.tooltip.motion.enter-duration with comp.tooltip.motion.enter-easing, so that it comes out of the anchor's side whichever side it is on; WHEN it closes THE tooltip SHALL take it back the same way to where it started, over comp.tooltip.motion.exit-duration with comp.tooltip.motion.exit-easing. WHERE sys.behavior.appearance is unfold the scale SHALL apply along the axis that leaves the anchor only. The motion SHALL be drawn only: the place TIP-9 gives, the gap of TIP-1 and the room the tooltip is measured for are those of the tooltip at rest. WHERE motion is reduced THE tooltip SHALL only fade in and out, over sys.motion.role.reduced, with no scale, distance or blur, or appear and disappear at once on a platform whose reduced-motion setting removes every animation (Android's). WHEN it is mounted with open true THE tooltip SHALL appear without its motion while the document has not yet been first painted, and with it when it is mounted after that. A tooltip that takes over from another SHALL NOT move at all (TIP-28).
TIP-16 WHILE text is empty THE tooltip SHALL NOT open and SHALL add nothing to the anchor's semantics, and in debug builds SHALL report the empty text; WHILE variant is plain and title is set it SHALL report the ignored title in debug builds.
TIP-17 THE tooltip SHALL take its show delay from showDelay, its hide delay from hideDelay and its touch timeout from touchTimeout, each a number of milliseconds used as given (the motion dial does not scale it), so that 0 opens or closes at once: a show delay of 0 opens as the pointer enters, a hide delay of 0 closes as the pointer leaves the anchor, the gap and the tooltip, and a touch timeout of 0 closes as the finger lifts, after the tooltip has shown for the whole long-press. WHILE one of them is null THE tooltip SHALL use comp.tooltip.motion.show-delay, comp.tooltip.motion.hide-delay or comp.tooltip.timeout.touch in its place, and IF one is negative or not a finite number THE tooltip SHALL use that token likewise and in debug builds report the value it ignored.
TIP-18 THE tooltip SHALL treat its show delay, hide delay and touch timeout as waiting times, not motion: WHERE motion is reduced it SHALL keep them, on every platform, including one whose reduced-motion setting removes every animation. The show and hide delays SHALL govern hover alone (TIP-1), and the touch timeout the time after a long-press alone (TIP-3): keyboard focus (TIP-2), another tooltip being open (TIP-8) and the product setting open (TIP-7) SHALL NOT wait for any of them, and the long-press itself SHALL take the platform's own duration. WHEN showDelay, hideDelay or touchTimeout changes while that wait is running THE tooltip SHALL finish the running wait and use the new value from the next time that wait starts.
TIP-19 THE tooltip 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 tooltip is shown THE tooltip SHALL draw itself for the new direction at once, without a motion of its own, keeping its open state, the container placed again by the new direction (TIP-20).
TIP-20 WHEN the layout direction is right-to-left THE tooltip SHALL take the side start as the anchor's right side and the side end as its left, SHALL take the alignments -start and -end of a tooltip above or below as the right and the left edges, and a positive crossOffset of such a tooltip as a move towards the left, flipping and shifting from there as TIP-9 says; it SHALL leave the sides top and bottom, the alignments -top and -bottom, a crossOffset beside the anchor and the centring on the anchor as they are, SHALL keep auto's order of sides by their names (TIP-23), SHALL start-align a rich tooltip's title and text at the right (TIP-12) and SHALL draw a plain tooltip's shortcut at the left of its text (TIP-27).
TIP-21 THE tooltip SHALL lay out its title and its text 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 word, a number with its sign or unit, a telephone number and an address keep their own order in a right-to-left layout and reorder nothing beside them; THE tooltip SHALL still place each and align its lines by the layout direction, not by the text's own.
TIP-22 THE tooltip SHALL read placement as a side and an alignment along that side: top and bottom SHALL put the container above or below the anchor with its centre on the anchor's, top-start and bottom-start with its start edge on the anchor's start edge, and top-end and bottom-end with its end edge on the anchor's end edge; start and end SHALL put it beside the anchor, on the side the layout direction gives that name, with its centre on the anchor's, start-top and end-top with its top edge on the anchor's top edge, and start-bottom and end-bottom with its bottom edge on the anchor's bottom edge. WHEN placement names a value the tooltip does not define THE tooltip SHALL place itself as the default value says and in debug builds report the unknown value; WHEN placement changes while the tooltip is shown THE tooltip SHALL take its new place at once, without a motion.
TIP-23 WHILE placement is auto THE tooltip SHALL try the sides in the order top, bottom, end, start and SHALL take the first that has room for the container within comp.tooltip.window-margin, or the one with the most room WHEN none has, with its centre on the anchor's, and SHALL then shift, hold and follow as TIP-9 says, keeping the side it took for as long as that side has room.
TIP-24 THE tooltip SHALL take the distance between the anchor's edge and the nearest part of itself — the container's edge, or the arrow's tip while an arrow is drawn — from offset, a number of the platform's layout units used as given, so that 0 lets the two touch, and from comp.tooltip.offset WHILE offset is null; it SHALL then move the container along its side by crossOffset, before the shift of TIP-9, and by no more than leaves comp.tooltip.arrow.width of the container beside the anchor, so that the tooltip still stands on the anchor's side and an arrow can still reach the anchor. IF offset is negative or not a finite number THE tooltip SHALL use comp.tooltip.offset in its place, IF crossOffset is not a finite number THE tooltip SHALL use 0, and in debug builds it SHALL report the value it ignored.
TIP-25 THE tooltip SHALL draw an arrow WHILE arrow is true, and WHILE arrow is null and comp.tooltip.arrow.visible is on, and none otherwise. WHILE it draws one THE tooltip SHALL draw a triangle comp.tooltip.arrow.width wide at its base and comp.tooltip.arrow.height tall on the container's edge that faces the anchor, as one shape with the container — the container's color and elevation, with no seam and no shadow between the two — its tip pointing at the middle of the part of the anchor's edge that the container stands beside, and SHALL keep its base at least comp.tooltip.arrow.inset, and at least the corner's radius, from each end of that edge, standing at the edge's middle where the edge is too short for both; the container SHALL stand comp.tooltip.arrow.height farther from the anchor, so that the tip keeps the offset (TIP-24). WHEN the container flips, shifts or follows the anchor (TIP-9) the arrow SHALL move with it to the edge that now faces the anchor and point at the anchor again, and WHILE the container covers the anchor (TIP-9) THE tooltip SHALL draw no arrow.
TIP-26 THE tooltip SHALL draw itself inverse — in the opposite scheme's colors — WHILE inverse is true, on a surface of the scheme WHILE inverse is false, and WHILE inverse is null as its form's choice says: comp.tooltip.plain.container.inverse for a plain tooltip and comp.tooltip.rich.container.inverse for a rich one. The tokens TIP-10 and TIP-27 name are a plain tooltip's inverse look: WHILE drawn on a surface a plain tooltip SHALL take comp.tooltip.plain.surface.container.color, comp.tooltip.plain.surface.container.elevation, comp.tooltip.plain.surface.supporting-text.color and comp.tooltip.plain.surface.shortcut.color in their place. The tokens TIP-11 names are a rich tooltip's surface look: WHILE drawn inverse a rich one SHALL take comp.tooltip.rich.inverse.container.color, comp.tooltip.rich.inverse.container.elevation, comp.tooltip.rich.inverse.title.color and comp.tooltip.rich.inverse.supporting-text.color in place of those TIP-11 names; its shape, padding, sizes, typescales, arrow, placement, motion and timing SHALL be the same either way, and WHEN inverse changes while the tooltip is shown THE tooltip SHALL draw the other look at once, keeping its open state.
TIP-27 WHILE variant is plain and shortcut is not empty THE tooltip SHALL draw the shortcut after the text, comp.tooltip.plain.container.gap from it and on the text's first line, with the keyboard shortcut component hosted as KBS-13 says: in its plain form, at size small, with convention auto, its legends and separators in comp.tooltip.plain.supporting-text.typescale and comp.tooltip.plain.shortcut.color; the shortcut SHALL stay whole on one line while the text wraps beside it, and the two with the gap SHALL fit within comp.tooltip.plain.container.max-width. THE tooltip SHALL expose the shortcut as the anchor's keyboard shortcut in the form KBS-12 gives (aria-keyshortcuts on the web) where the platform has that property and the anchor does not state one itself, and otherwise, WHILE describes is true, SHALL add the text KBS-10 gives to the end of the anchor's description; it SHALL NOT make the keys work. WHILE variant is rich THE tooltip SHALL ignore shortcut and in debug builds report it.
TIP-28 WHEN a tooltip opens while another tooltip of its window is open or still fading out, or within comp.tooltip.motion.warm-duration after one closed because the pointer or the keyboard focus left its anchor THE tooltip SHALL appear whole in its place at once, without the motion of TIP-15, and the other SHALL disappear at once, without its own; WHEN it is a pointer that opens it within that time THE tooltip SHALL NOT wait for its show delay either, as TIP-8 says of a tooltip that opens while another is open. A tooltip closed by Escape (TIP-4), by an activation of its anchor (TIP-6) or by a press on it (TIP-13) SHALL start no such time, so that the next tooltip waits and moves as a first one does. The time is a waiting time: WHERE motion is reduced it SHALL still apply (TIP-18).
TIP-29 WHEN the tooltip is told to close while it is still entering, or to open while it is still leaving THE tooltip SHALL turn round from the opacity, the size and the position it has reached, without first jumping to the start or the end of either motion, and SHALL take no longer over the rest than the whole duration of the motion it turns to. WHILE the tooltip is closed or leaving THE tooltip SHALL take no pointer input — a press reaches what lies under it, and the pointer on it is not hover (TIP-1) — and WHILE it is closed it SHALL take no room in the layout and draw nothing, so that a tooltip nobody can see never stands in the way of what is under it.

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-tooltip tanreiTooltip TanreiTooltip TanreiTooltip Tooltip
variant · Propiedad variant variant variant variant variant
text · Propiedad text text text message text
title · Propiedad headline title title title title
shortcut · Propiedad shortcut shortcut shortcut shortcut shortcut
placement · Propiedad placement placement placement placement placement
offset · Propiedad offset offset offset offset offset
crossOffset · Propiedad crossOffset crossOffset crossOffset crossOffset crossOffset
arrow · Propiedad arrow arrow arrow arrow arrow
inverse · Propiedad inverse inverse inverse inverse inverse
describes · Propiedad describes describes describes excludeFromSemantics describes
open · Propiedad open isPresented state controller open
showDelay · Propiedad showDelay showDelay showDelayMillis waitDuration showDelay
hideDelay · Propiedad hideDelay hideDelay hideDelayMillis exitDuration hideDelay
touchTimeout · Propiedad touchTimeout touchTimeout touchTimeoutMillis showDuration touchTimeout
toggle · Evento toggle isPresented state controller onOpenChange
Notas Wraps its anchor (the default slot). showDelay, hideDelay and touchTimeout are number properties in milliseconds, null by default, set by the show-delay, hide-delay and touch-timeout attributes; an attribute that is empty or does not parse as a finite number is not a number (TIP-17), so show-delay="" takes the token and does not open at once. The gap of TIP-1 is measured, not drawn: the document's pointer-move listener counts a point inside it as over the tooltip, so nothing in the top layer covers what lies under the gap. The drawn tooltip is a popover="manual" element in the shadow root, so it is in the top layer (above an open modal <dialog>); it is placed with CSS anchor positioning and position-try flips where supported, and by measuring otherwise. describes is a boolean property that defaults to true; its attribute is the inverse no-describe, because an HTML boolean attribute cannot default to true. toggle is a CustomEvent whose detail.open is the new value. Snapshot harness: each fixture is a stage of 320 × 200 with a medium icon-only text tanrei-button labelled after the fixture's glyph at its centre, and the tooltip open beside it. placement takes the thirteen values as written (top-start, end-bottom, auto); offset and crossOffset are number properties in CSS pixels (attributes offset, cross-offset), parsed as the delays are, so an empty attribute is not a number. arrow and inverse are properties that are true, false or null: the attribute is absent for null, present for true and ="false" for false, as the snackbar's inverse is; null reads the choice from the cascade. shortcut is an array property; its attribute holds the chords separated by spaces, as the keyboard shortcut's keys does, and the shortcut reaches the anchor's focusable element as aria-keyshortcuts unless that element already has one. The container and the arrow are one painted shape, so the elevation's ring and shadows run round both. The enter and exit motion runs on a wrapper inside the popover whose transform origin is set from the placement that was taken; the popover element itself keeps its placed box, so the measured gap and the following do not see the motion. The time tooltips stay warm is kept per window, beside the one showing tooltip. Snapshot harness: the stage sets data-tanrei-keyboard-convention="standard", so plain-shortcut reads the same on every machine. Lagging: has no delay or timeout parameters and no hover gap; owes TIP-1 (the gap), TIP-3 and TIP-8's wording, TIP-17 and TIP-18. The target: a view modifier .tanreiTooltip(_ text:, title:, variant:, placement:, describes:, showDelay: Duration? = nil, hideDelay: Duration? = nil, touchTimeout: Duration? = nil, isPresented: Binding<Bool>?); a Duration carries its own unit (.milliseconds(300)), nil takes the token, and a negative one takes the token and is reported in debug builds. The description is the anchor's accessibilityHint. The tooltip is drawn in an overlay above the window's content (anchored with anchor preferences), not with .popover, which is modal at compact widths and moves VoiceOver focus: a non-modal overlay must do neither. Hover is onContinuousHover (iPadOS and macOS pointers), keyboard focus is focused with full keyboard access, long-press is a LongPressGesture that does not fire the anchor's action. Snapshot harness: renders the anchor and the open tooltip in a fixed 320 × 200 frame. Also owed: the thirteen placement values, offset, crossOffset, arrow, inverse and shortcut; TIP-9 and TIP-15 as they read now and TIP-22 to TIP-29. offset and crossOffset are CGFloat? and CGFloat in points; arrow and inverse are Bool?, nil taking the system's choice; shortcut is [String], exposed with the anchor's keyboardShortcut semantics where it has one and in the hint otherwise. The container and the arrow are one Shape. Snapshot harness: the stage sets the standard keyboard convention for plain-shortcut. Not yet: the title's letter-spacing by the script of its text (TIP-11, PRS-20). Lagging: has no delay or timeout parameters and no hover gap; owes TIP-1 (the gap), TIP-3 and TIP-8's wording, TIP-17 and TIP-18. The target: TanreiTooltip(text, modifier, variant, title, placement, describes, showDelayMillis: Long? = null, hideDelayMillis: Long? = null, touchTimeoutMillis: Long? = null, state = rememberTanreiTooltipState()) { anchor }, shaped like Material's TooltipBox, the times named in milliseconds as ViewConfiguration.longPressTimeoutMillis is; null takes the token, a negative value takes the token and is reported in debug builds. The waits are coroutine delays, not animations, so the animator duration scale of 0 (Android's reduced motion) does not remove them (TIP-18); state.isVisible is open, and state.show() / state.dismiss() set it. The tooltip is a Popup with PopupProperties(focusable = false). Compose has no separate description semantics: the text is appended to the anchor's merged semantics after its own name, as Android reads a View's tooltip text, and a test asserts the order. Snapshot harness: renders the anchor and the open tooltip in a fixed 320 × 200 frame. Also owed: the thirteen placement values, offset, crossOffset, arrow, inverse and shortcut; TIP-9 and TIP-15 as they read now and TIP-22 to TIP-29. offset and crossOffset are Dp? and Dp; arrow and inverse are Boolean?, null taking the system's choice; shortcut is List<String>. The container and the arrow are one Shape, so the shadow follows both. The warm time is a coroutine delay, kept at an animator duration scale of 0 (TIP-28). Snapshot harness: the stage sets the standard keyboard convention for plain-shortcut. Not yet: the title's letter-spacing by the script of its text (TIP-11, PRS-20). Lagging: has no delay or timeout parameters and no hover gap; owes TIP-1 (the gap), TIP-3 and TIP-8's wording, TIP-17 and TIP-18. Named as Flutter's Tooltip: message is the text, excludeFromSemantics is the inverse of describes, the delays are waitDuration and exitDuration, and the touch timeout is showDuration, which Flutter's Tooltip uses for the time after a long-press is released (each a Duration?: null takes the token, a negative one takes the token and is reported in debug builds). The description is the anchor's Semantics(tooltip:). The tooltip is drawn through an OverlayPortal (the overlay of the nearest Overlay, so above a dialog route opened earlier). controller is a TanreiTooltipController (a ChangeNotifier with show(), hide() and isOpen). Snapshot harness: a golden of the anchor and the open tooltip in a 320 × 200 surface. Also owed: the thirteen placement values, offset, crossOffset, arrow, inverse and shortcut; TIP-9 and TIP-15 as they read now and TIP-22 to TIP-29. offset and crossOffset are double? and double in logical pixels (Flutter's own Tooltip calls the first verticalOffset; this one is not vertical only); arrow and inverse are bool?, null taking the system's choice; shortcut is List<String>. The container and the arrow are one ShapeBorder. Snapshot harness: the stage sets the standard keyboard convention for plain-shortcut. Not yet: the title's letter-spacing by the script of its text (TIP-11, PRS-20). Lagging: has no delay or timeout props and no hover gap; owes TIP-1 (the gap), TIP-3 and TIP-8's wording, TIP-17 and TIP-18. The target: showDelay, hideDelay and touchTimeout are numbers of milliseconds, as Pressable's delayLongPress is; undefined or null takes the token, and a negative or non-finite number takes the token and is reported in development builds. Wraps its anchor (children). The description is the anchor's accessibilityHint. The tooltip is drawn in the overlay layer that TanreiProvider renders at the root of the app, not in a Modal: a Modal is modal (it takes every touch and moves accessibility focus), which a non-modal overlay must not be. Hover comes from onHoverIn/onHoverOut on platforms with a pointer. Snapshot harness: renders the anchor and the open tooltip in a fixed 320 × 200 view. Also owed: the thirteen placement values, offset, crossOffset, arrow, inverse and shortcut; TIP-9 and TIP-15 as they read now and TIP-22 to TIP-29. offset and crossOffset are numbers of density-independent pixels; arrow and inverse are booleans, undefined or null taking the system's choice; shortcut is a string array. The container and the arrow are one drawn shape. Snapshot harness: the stage sets the standard keyboard convention for plain-shortcut. Not yet: the title's letter-spacing by the script of its text (TIP-11, PRS-20).

Tokens

Token Alias de Valor resuelto (claro)
--tanrei-comp-tooltip-arrow-height sys.space.space75 6px
--tanrei-comp-tooltip-arrow-inset sys.space.space100 8px
--tanrei-comp-tooltip-arrow-visible — 0
--tanrei-comp-tooltip-arrow-width sys.space.space150 12px
--tanrei-comp-tooltip-motion-enter-duration sys.motion.role.appear.hint.enter 250ms
--tanrei-comp-tooltip-motion-enter-easing sys.motion.easing.enter cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-tooltip-motion-exit-duration sys.motion.role.appear.hint.exit 200ms
--tanrei-comp-tooltip-motion-exit-easing sys.motion.easing.exit cubic-bezier(0.3, 0, 1, 1)
--tanrei-comp-tooltip-motion-hide-delay sys.motion.duration.short2 100ms
--tanrei-comp-tooltip-motion-show-delay sys.motion.duration.long2 500ms
--tanrei-comp-tooltip-motion-warm-duration sys.motion.duration.medium2 300ms
--tanrei-comp-tooltip-offset sys.space.space50 4px
--tanrei-comp-tooltip-plain-container-color sys.color.inverse-surface #1f1f1f
--tanrei-comp-tooltip-plain-container-elevation sys.elevation.level0
--tanrei-comp-tooltip-plain-container-gap sys.space.space100 8px
--tanrei-comp-tooltip-plain-container-inverse — 1
--tanrei-comp-tooltip-plain-container-max-width — 200px
--tanrei-comp-tooltip-plain-container-min-height — 24px
--tanrei-comp-tooltip-plain-container-padding-block sys.space.space50 4px
--tanrei-comp-tooltip-plain-container-padding-inline sys.space.space100 8px
--tanrei-comp-tooltip-plain-container-shape sys.shape.corner.small 6px
--tanrei-comp-tooltip-plain-shortcut-color sys.color.inverse-on-surface #f1f1f1
--tanrei-comp-tooltip-plain-supporting-text-color sys.color.inverse-on-surface #f1f1f1
--tanrei-comp-tooltip-plain-surface-container-color sys.color.surface-bright #ffffff
--tanrei-comp-tooltip-plain-surface-container-elevation sys.elevation.level2 0px 0px 0px 1px rgb(0 0 0 / 0.08), 0px 1px 2px 0px rgb(0 0 0 / 0.04)
--tanrei-comp-tooltip-plain-surface-shortcut-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-tooltip-plain-surface-supporting-text-color sys.color.on-surface #1b1b1b
--tanrei-comp-tooltip-rich-container-color sys.color.surface-bright #ffffff
--tanrei-comp-tooltip-rich-container-elevation sys.elevation.level2 0px 0px 0px 1px rgb(0 0 0 / 0.08), 0px 1px 2px 0px rgb(0 0 0 / 0.04)
--tanrei-comp-tooltip-rich-container-gap sys.space.space50 4px
--tanrei-comp-tooltip-rich-container-inverse — 0
--tanrei-comp-tooltip-rich-container-max-width — 320px
--tanrei-comp-tooltip-rich-container-padding-block sys.space.space150 12px
--tanrei-comp-tooltip-rich-container-padding-inline sys.space.space200 16px
--tanrei-comp-tooltip-rich-container-shape sys.shape.corner.medium 8px
--tanrei-comp-tooltip-rich-inverse-container-color sys.color.inverse-surface #1f1f1f
--tanrei-comp-tooltip-rich-inverse-container-elevation sys.elevation.level0
--tanrei-comp-tooltip-rich-inverse-supporting-text-color sys.color.inverse-on-surface #f1f1f1
--tanrei-comp-tooltip-rich-inverse-title-color sys.color.inverse-on-surface #f1f1f1
--tanrei-comp-tooltip-rich-supporting-text-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-tooltip-rich-title-color sys.color.on-surface #1b1b1b
--tanrei-comp-tooltip-timeout-touch — 1500ms
--tanrei-comp-tooltip-window-margin sys.space.space100 8px
--tanrei-comp-tooltip-plain-supporting-text-typescale sys.typescale.body-small 400 13px/1.5385
--tanrei-comp-tooltip-rich-supporting-text-typescale sys.typescale.body 400 14px/1.5714
--tanrei-comp-tooltip-rich-title-typescale sys.typescale.heading-6 500 14px/1.4286

Fixtures

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

Generado a partir de specs/tooltip.spec.json, tokens/comp/tooltip.tokens.json, design/tokens/

Pautas

Cuándo usarlo

Usa un tooltip para dar nombre a una acción de icono ante una persona que no reconoce el glifo, o para explicar en el momento un término, un límite o un ajuste. Es una descripción, que se lee de pasada.

Un tooltip es invisible para quienes usan el tacto hasta que hacen una pulsación larga, y un lector de pantalla lo oye solo como una descripción. Nunca pongas únicamente en un tooltip algo que una persona necesita para terminar una tarea: muéstralo como texto en la pantalla. Una nota que necesita un enlace o un botón no es un tooltip. Usa un diálogo, o texto junto a lo que explica.

Cómo elegir una variante

Variante Qué es Úsala para
Plain Una frase corta, de forma predeterminada sobre la superficie inversa. Ignora headline y puede mostrar un atajo de teclado después de su texto. Nombrar lo que hace un icono: «Mover a la papelera», «Compartir».
Rich Un título opcional encima de unas pocas frases, de forma predeterminada sobre una superficie elevada. Ignora shortcut. Explicar un término o un ajuste: «Almacenamiento» y qué cuenta para él.

La variante es una elección estructural, no un eje de tokens. Un sistema de diseño cambia el estilo de ambas formas, pero no puede añadir una tercera mediante valores.

Colocación

placement nombra el lado del ancla que el tooltip prefiere y cómo se alinea a lo largo de ese lado. El valor predeterminado es top.

Apunta a un botón o dale el foco: las trece colocaciones

toptop-starttop-endbottombottom-startbottom-endstartstart-topstart-bottomendend-topend-bottomauto
Lado Centrado en el ancla Primeros bordes juntos Segundos bordes juntos
Encima top top-start top-end
Debajo bottom bottom-start bottom-end
Antes del ancla start start-top start-bottom
Después del ancla end end-top end-bottom
  • Alineado significa borde con borde. top-start pone el borde de inicio del tooltip sobre el borde de inicio del ancla, y end-bottom pone su borde inferior sobre el borde inferior del ancla. Usa una colocación alineada para un tooltip ancho sobre un ancla pequeña cerca del borde de un panel, o para alinear un tooltip con una fila de texto.
  • Inicio y fin siguen la dirección del diseño. En un diseño de derecha a izquierda, start es el lado derecho y top-start alinea los bordes derechos. Arriba y abajo no se reflejan.
  • auto prueba arriba, abajo, fin e inicio, en ese orden, y toma el primer lado con sitio, centrado. Úsalo para un ancla cuyo entorno no puedes conocer, como un control en un panel que puede acoplarse a cualquier borde.
  • Cuando no hay sitio. El tooltip pasa al lado opuesto y conserva su alineación, y después se desliza a lo largo del lado para quedar dentro del área segura de la ventana. En una ventana más pequeña que el tooltip se queda dentro de la ventana, sobre el ancla si no hay más remedio. Una vez que ha cambiado de lado, lo conserva mientras ese lado tenga sitio, de modo que una página que se desplaza no lo lleva de un lado a otro.
  • offset y crossOffset. offset es la distancia desde el borde del ancla, y 0 deja que los dos se toquen; si no se define, es la distancia del sistema. crossOffset mueve el tooltip a lo largo de su lado, hacia el fin cuando está encima o debajo del ancla y hacia abajo cuando está a su lado, y nunca lo saca del lado del ancla. Ambos van en las unidades de diseño de la plataforma. Defínelos solo donde la caja del ancla no sea lo que el ojo toma por su borde, como un control con un área de pulsación grande e invisible o una marca de un gráfico.
  • Un cambio mientras se muestra. Un nuevo placement o un nuevo desplazamiento mueven el tooltip de inmediato, sin movimiento.

Una flecha

Apunta a un botón o dale el foco: con una flecha

deletefilter_listinfo

arrow dibuja en el borde del tooltip un pequeño triángulo que apunta al ancla. Está desactivado en el sistema predeterminado. Si no se define, toma la elección del sistema de diseño; true y false lo deciden para un solo tooltip. En la web, el atributo es arrow para true y arrow="false" para false.

La flecha forma una sola figura con el tooltip, del mismo color. Apunta al ancla, no al centro del tooltip, también después de que el tooltip haya cambiado de lado o se haya deslizado, y se mantiene apartada de las esquinas. El tooltip se aleja lo que mide la altura de la flecha, de modo que la separación que ves es la misma con ella o sin ella.

Usa una flecha donde el lado por sí solo no diga a qué control se refiere: una pista que abres tú sobre una barra de herramientas abarrotada, por ejemplo. Los nombres que se muestran al pasar el cursor rara vez la necesitan.

Dos aspectos

Apunta a un botón o dale el foco: cada forma, inversa y sobre una superficie

Plain, inversoPlain, superficieRich, superficieRich, inverso

Cualquiera de las dos formas se puede dibujar inversa, con los colores del esquema opuesto, o sobre una superficie elevada del esquema.

inverse Plain Rich
Sin definir (el valor predeterminado) Lo que el sistema de diseño elija para los tooltips plain: inverso en el sistema predeterminado. Lo que el sistema de diseño elija para los tooltips rich: una superficie en el sistema predeterminado.
true Inverso. Inverso.
false Sobre una superficie. Sobre una superficie.

En la web, el atributo es inverse para true e inverse="false" para false, como el del snackbar.

Solo cambian los colores y la elevación. La forma, los tamaños, los estilos de texto, la flecha, la colocación y el movimiento son los mismos en ambos aspectos, y ninguno de los dos dice que un tooltip sea importante. Defínelo para el tooltip que, de otro modo, no tendría de qué distinguirse: una etiqueta oscura sobre un visor de imágenes oscuro o sobre una barra inversa, o una nota más larga sobre una superficie elevada y recargada.

Un atajo de teclado

Apunta a un botón o dale el foco: las teclas de un comando después de su nombre

format_boldformat_italic

shortcut muestra las teclas del comando del ancla después del texto de un tooltip plain, escritas para el teclado que usa la persona. Recibe los nombres de tecla del componente atajo de teclado, una combinación por cadena; en la web, el atributo contiene las combinaciones separadas por espacios.

El tooltip solo muestra las teclas. No hace que funcionen: las vincula tu producto. Las teclas se mantienen enteras en una línea mientras un texto largo salta de línea a su lado. Un tooltip rich ignora shortcut, y las compilaciones de depuración lo notifican.

Apertura, foco y cierre

Un tooltip es una superposición de lectura. Las personas toman información de él y nunca actúan dentro de él, así que nunca toma el foco.

Entrada Se abre Se cierra
Un puntero Después de que repose sobre el ancla durante el retardo de aparición. Después de que haya estado fuera del ancla, de la separación y del tooltip durante el retardo de ocultación. El puntero puede cruzar la separación hasta el tooltip para leerlo.
El foco del teclado De inmediato, cuando el ancla recibe el foco del teclado. El foco que viene de un puntero o del tacto no lo abre. Cuando el foco sale del ancla.
Una pulsación larga táctil De inmediato, sin activar el ancla. Cuando pasa el tiempo de espera táctil después de levantar el dedo, o antes con un toque en cualquier otro lugar.
  • Sin límite de tiempo mientras se usa. Mientras el puntero está sobre el ancla, el tooltip o la separación entre ambos, o el ancla tiene el foco del teclado, se queda abierto. La separación no se dibuja ni recibe pulsaciones: solo cuenta como paso del cursor.
  • Escape. Escape lo cierra sin mover el foco y no va más allá, así que un diálogo que lo contenga se queda abierto. Sigue cerrado hasta que el puntero vuelve a entrar en el ancla o esta vuelve a recibir el foco.
  • Activación. Activar el ancla (un clic, un toque, Enter o Espacio) lo cierra, y el mismo paso del cursor no lo vuelve a abrir.
  • De uno en uno. Cuando se abre un tooltip, cualquier otro de la ventana se cierra, y el nuevo se abre sin el retardo, porque la persona ya está leyendo tooltips.
  • Pasar de un tooltip a otro. Un tooltip que toma el relevo de otro, o que se abre poco después de que otro se cerrara porque el puntero o el foco salieron de su ancla, aparece entero de inmediato: sin retardo y sin movimiento. Así, un puntero que recorre una barra de herramientas lee un nombre tras otro. Un tooltip cerrado con Escape, al activar su ancla o al pulsarlo no inicia ese tiempo.
  • No toma el foco, no bloquea nada. No contiene nada que pueda recibir el foco ni pulsarse, no deja nada inerte y no dibuja ningún velo. Una pulsación sobre el tooltip lo cierra y no llega a lo que hay debajo.
  • Por encima de todo. Se dibuja por encima de cualquier otra capa de su ventana, incluidos un diálogo abierto y su velo, así que un tooltip dentro de un diálogo es visible.
  • Colocación. Se sitúa donde dice placement; consulta Colocación. Sigue al ancla cuando esta se mueve, y se cierra cuando el ancla se quita, se oculta, sale de la ventana por el desplazamiento o queda fuera de la vista dentro de un área con desplazamiento.
  • Movimiento. Sale del lado del ancla, como aparece cada superficie del sistema de diseño: por defecto aparece con un fundido mientras crece un poco desde el centro del borde que da al ancla, y vuelve del mismo modo. Un movimiento que se interrumpe da la vuelta desde donde está. Mientras se cierra, el tooltip no recibe el puntero, así que nunca estorba a lo que tiene debajo. Donde el movimiento está reducido, solo hace el fundido.
  • Anuncio. No se anuncia nada cuando aparece el tooltip. Mientras describes es true, su texto, después del título en un tooltip rich, es la descripción del ancla esté el tooltip abierto o no, y se evita que el tooltip dibujado se lea una segunda vez.

Retardos para un solo tooltip

El sistema de diseño define el retardo de aparición, el retardo de ocultación y el tiempo de espera táctil para todos los tooltips a la vez. Un tooltip puede definir los suyos con showDelay, hideDelay y touchTimeout, en milisegundos. Si no se definen, cada uno toma el valor del sistema.

  • Cuándo definirlos. Define un retardo de aparición más corto en una barra de herramientas densa que quiere sus nombres antes, y uno más largo sobre un gráfico cuyas marcas recorre el puntero, para que ningún tooltip parpadee. Define un tiempo de espera táctil más largo en un tooltip rich de unas pocas frases, y uno más corto en un nombre de una sola palabra.
  • 0 significa de inmediato. Un retardo de aparición de 0 abre el tooltip en cuanto el puntero entra en el ancla, y un retardo de ocultación de 0 lo cierra en cuanto el puntero sale del ancla, de la separación y del tooltip. Aun así, se puede seguir pasando el cursor por el tooltip, porque la separación cuenta como paso del cursor. Un tiempo de espera táctil de 0 lo cierra en cuanto se levanta el dedo, después de haberse mostrado durante toda la pulsación larga.
  • Se usan tal como se escriben. Un valor que defines no se escala con el dial de movimiento, y el movimiento reducido lo conserva: un retardo es una espera, no una animación. Un valor negativo o no numérico toma el valor del sistema, y las compilaciones de depuración lo notifican. En la web, un atributo vacío tampoco es un número.
  • Solo el cursor y el tacto. El foco del teclado sigue abriendo el tooltip de inmediato, un tooltip que se abre mientras otro se muestra sigue saltándose su retardo de aparición, y definir open sigue mostrándolo u ocultándolo de inmediato. La pulsación larga en sí dura lo que establece la plataforma.
  • Un cambio durante la espera. Una espera que ya está en curso termina como empezó. El nuevo valor se aplica la vez siguiente.

Hoy solo la web y React aceptan estas propiedades. Cuando las demás plataformas se pongan al día, la especificación las nombra según el estilo propio de cada plataforma: showDelayMillis, hideDelayMillis y touchTimeoutMillis en Compose, waitDuration, exitDuration y showDuration del Tooltip de Flutter, y los nombres de la propia especificación en SwiftUI y React Native.

Cada plataforma usa una presentación no modal: un elemento popover="manual" en la capa superior en la web, una superposición por encima de la ventana en SwiftUI (no .popover, que es modal en anchos compactos), un Popup que no puede tomar el foco en Compose, un OverlayPortal en Flutter y la capa de superposición de TanreiProvider en React Native (no un Modal, que recibe todos los toques).

Recomendado

  • Limita los tooltips plain a unas pocas palabras, y los tooltips rich a unas pocas frases.
  • Da la misma colocación al mismo tipo de ancla en toda una pantalla, como debajo de todos los iconos de una barra de herramientas.
  • Deja inverse y arrow al sistema de diseño en la mayoría de los tooltips, y defínelos en el que lo necesite.
  • Muestra las teclas de un comando con shortcut, no escribiéndolas en el texto.
  • Da los mismos retardos a los tooltips de un mismo grupo de anclas, para que lleven un mismo ritmo.
  • Pon describes en false cuando el tooltip muestre la propia etiqueta del ancla.

Evita

  • No uses un tooltip como nombre de un botón de icono. El label del botón es su nombre.
  • No pongas un tooltip en un ancla deshabilitada para explicar por qué lo está. Un control deshabilitado no puede recibir el foco y puede no recibir eventos de puntero. Pon el motivo en un texto visible.
  • No pongas enlaces, botones ni nada interactivo en un tooltip.
  • No repitas en un tooltip lo que el ancla ya dice en un texto visible.
  • No uses el aspecto inverso ni una flecha para que un tooltip parezca más importante.

Accesibilidad

Rol
tooltip
Etiquetado
The tooltip names nothing. The anchor keeps its own accessible name and role; while describes is true the text (after the title, for a rich tooltip) is the anchor's description, available whether or not the tooltip is showing. An icon-only Button's label is its name (BTN-16) and is never replaced by a tooltip: a tooltip that shows the same words sets describes to false. A shortcut is the anchor's keyboard shortcut where the platform has that property, and the end of its description otherwise (TIP-27); the drawn keys and the arrow are hidden.
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 Moving focus to the anchor opens its tooltip at once; moving focus away closes it. The tooltip itself is never a tab stop.
Escape Closes an open tooltip without moving focus, and goes no further (an enclosing dialog stays open).

Notas

  • The tooltip takes no input, so it has no target of its own: minimumTarget applies to the anchor, which keeps its own hit area.
  • WCAG 1.4.13 (content on hover or focus): the tooltip can be dismissed without moving the pointer or focus (Escape, TIP-4), can be hovered (TIP-1: the gap between the anchor and the tooltip counts as hover — at any offset, with or without an arrow — so this holds at any hideDelay, 0 included), and stays until hover or focus ends or it is dismissed (TIP-5). Placement, the arrow and the motion change none of the three: a tooltip that flips, shifts or follows its anchor is the same open tooltip, and the gap is measured to wherever it stands.
  • A tooltip is invisible to touch users until they long-press, and to screen-reader users it is only a description. Nothing a person needs to finish a task may live only in a tooltip. A note that needs a link or a button is not a tooltip; that form belongs to a separate non-modal popover component.
  • Do not put a tooltip on a disabled anchor to explain why it is disabled: a disabled control cannot be focused, and on the web it may receive no pointer events. Put the reason in visible text.
  • Web: the description reaches the anchor's focusable element as aria-description, because aria-describedby cannot point across shadow roots. The anchor is the first focusable element slotted into the tooltip; a Tanrei component forwards aria-description from its host to the native element in its shadow root. The drawn tooltip has role tooltip and aria-hidden while describes carries the text.
  • The motion is short, small and never the only sign of anything; where motion is reduced nothing grows or travels (TIP-15). A tooltip that is leaving is already closed for input (TIP-29), so nothing invisible is ever in the pointer's way.
  • The inverse look and the surface look are two looks of one thing, not two meanings: neither says that a tooltip matters more. Choose by what the tooltip lands on.
  • A shortcut in a tooltip is a reminder for people who see it. It must also work for those who do not: the product binds the keys, and the anchor carries the shortcut for assistive technology (TIP-27).

Generado a partir de specs/tooltip.spec.json, tokens/sys/measure.tokens.json

De qué se encarga el componente

  • Mientras describes es true, el texto, después del título en un tooltip rich, es la descripción accesible del ancla, disponible se esté mostrando el tooltip o no. El ancla conserva su propio nombre y su rol. Mientras describes es false, el tooltip no añade nada al ancla.
  • Se evita que el tooltip dibujado se lea dos veces. Nunca toma el foco y no contiene nada que pueda recibirlo.
  • El foco del teclado en el ancla lo abre de inmediato, y llevar el foco a otro lugar lo cierra. El tooltip en sí nunca es una parada de tabulación.
  • Escape lo cierra sin mover el foco, y no cierra además un diálogo que lo contenga.
  • Cumple WCAG 1.4.13 (contenido al pasar el cursor o al recibir el foco): se puede descartar sin mover el puntero ni el foco, se puede pasar el cursor por él con cualquier retardo de ocultación, incluido 0, porque la separación entre el ancla y el tooltip cuenta como paso del cursor, y permanece hasta que termina el paso del cursor o el foco, o hasta que se descarta.
  • Crece con un texto más grande sin recortarlo, y su texto se alinea al inicio de la dirección del diseño.
  • Un atajo se expone como el atajo de teclado del ancla (aria-keyshortcuts en la web, en el elemento que recibe el foco), y las teclas dibujadas quedan ocultas para la tecnología de apoyo. Donde el ancla ya declara un atajo propio, las teclas del tooltip se escriben con todas sus letras al final de la descripción, mientras describes es true.
  • La flecha es decoración y queda oculta para la tecnología de apoyo. Ambos aspectos usan pares de colores de texto y de contenedor cuyo contraste comprueba la compilación en todos los esquemas.
  • Su movimiento es pequeño: por defecto, un fundido y un ligero crecimiento. Donde el movimiento está reducido, hace el fundido sin crecer ni desplazarse, salvo en Android, cuyo ajuste quita todas las animaciones. Los retardos, el tiempo de espera táctil y el tiempo durante el cual el siguiente tooltip se abre de inmediato son esperas, no movimiento, y se conservan en todas partes.
  • Un tooltip cuyo texto está vacío nunca se abre y no añade nada. Las compilaciones de depuración lo notifican, igual que el título ignorado de un tooltip plain.

Carencias conocidas por plataforma:

  • SwiftUI, Compose, Flutter y React Native todavía no aceptan showDelay, hideDelay ni touchTimeout, y no cuentan la separación como paso del cursor: allí todos los tooltips toman los retardos del sistema, y el puntero cruza la separación dentro del retardo de ocultación. Además, solo tienen las cuatro colocaciones centradas (top, bottom, start, end), y no tienen offset, crossOffset, arrow, inverse ni shortcut; sus tooltips hacen el fundido sin crecer ni desplazarse.
  • Web: una pulsación larga táctil abre un tooltip solo donde el navegador la notifica como un menú contextual. Safari en iOS no lo hace, así que allí un tooltip no se abre con el tacto.
  • Web: el título de un tooltip enriquecido es el atributo headline. Un atributo title en <tanrei-tooltip> es del navegador, que dibuja para él su tooltip nativo: no lo pongas.
  • SwiftUI no tiene rol de tooltip. La descripción es la indicación de accesibilidad del ancla.
  • SwiftUI en iOS: Retorno o Espacio sobre un ancla con foco no cierran el tooltip, y Escape lo cierra solo mientras el ancla tiene el foco. Un ancla que recibe el foco con un toque, como un campo de texto, abre su tooltip. Un ancla que se hace transparente o queda tapada no se detecta como oculta.
  • SwiftUI dibuja los tooltips en una capa que proporcionan .tanreiTheme(_:) y un diálogo de Tanrei. El contenido que SwiftUI presenta aparte, como tu propio .sheet o .popover, necesita .tanreiTooltipLayer() para que sus tooltips se muestren.
  • Compose no tiene una propiedad de descripción. El texto pasa a ser la descripción de estado del ancla, que se lee después de su nombre y su rol. Un control de Tanrei la pone en su propio nodo; cualquier otra ancla se describe solo cuando un ancestro que fusiona la recoge. En un ancla conmutadora, como un botón de icono conmutador, sustituye al «On» o al «Off».
  • Compose: un tooltip que muestras desde el código sobre un ancla situada detrás de un diálogo abierto se dibuja debajo de la ventana del diálogo.
  • Compose: mientras el foco está en otro lugar de la ventana y sobre el ancla solo se pasó el cursor, Escape llega al tooltip solo en Android 9 (API 28) y posteriores.
  • Compose: el paso del cursor con un ratón real, un toque fuera, el listener de Escape y la lectura que TalkBack hace de la descripción de estado del ancla se han probado solo en Robolectric, todavía no en un dispositivo.
  • Flutter: el tooltip dibujado siempre se excluye de la semántica, porque el rol de tooltip de Flutter todavía no se puede usar. La descripción del ancla no se ve afectada.
  • Flutter: Escape se consume solo mientras el foco está en el ancla, o lo consume un diálogo de Tanrei. Otro ancestro que gestione Escape, como una ruta de diálogo de Material, lo sigue recibiendo mientras el foco está en otro lugar.
  • React Native: la descripción es el accessibilityHint del ancla, después de la indicación propia del ancla.
  • React Native: un toque en otro lugar no cierra antes un tooltip abierto con una pulsación larga. El tiempo de espera táctil lo cierra igualmente.
  • React Native: el tooltip no sigue a un ancla que se desplaza, y no se cierra cuando el ancla sale de la vista por el desplazamiento. Se mantiene dentro del área segura solo cuando pasas los márgenes interiores de la ventana a TanreiProvider.
  • React Native: el paso del cursor, llevar el puntero hasta el tooltip, la pulsación larga y Escape todavía no se han comprobado en un dispositivo.

Qué debes hacer tú

  • Da al ancla su propio nombre accesible. El tooltip nunca lo sustituye.
  • Pon describes en false cuando el texto repita ese nombre.
  • Vincula tú las teclas que muestras con shortcut, y muestra las mismas teclas en cualquier otro lugar donde aparezca el comando, como en un menú.
  • Haz que el ancla pueda recibir el foco, para que quienes usan el teclado puedan abrir el tooltip.
  • Si acortas el tiempo de espera táctil, asegúrate de que el texto se pueda seguir leyendo en el tiempo que queda. Un tiempo de espera de 0 muestra el tooltip solo mientras el dedo está apoyado.
  • Mantén fuera del tooltip todo lo que una persona necesita. Quienes usan el tacto o un lector de pantalla quizá nunca lo vean.
  • En React Native, pon TanreiProvider en la raíz de tu aplicación, con los insets de la ventana: su capa de superposición dibuja el tooltip dentro del área segura. En SwiftUI, aplica .tanreiTheme(_:) por encima del ancla, y .tanreiTooltipLayer() al contenido de tus propias hojas y popovers. En Flutter, el tooltip necesita un Overlay por encima, que tiene toda WidgetsApp con un Navigator.