Componentes · Ola 2 · Superposiciones
Tooltip
Texto breve que describe a un control al pasar el puntero o al enfocarlo. Es solo texto: la luz sobre el vacío, con una flecha hacia el control. Se abre con un retardo al pasar el puntero y al instante con el foco del teclado.
import { Tooltip, TooltipProvider } from '@archeblack/ui';
Ejemplos
Básico
Un botón de solo ícono con su aria-label y un tooltip que lo describe, como en el demo.
<script lang="ts">
import { Button, Tooltip } from '@archeblack/ui';
import { IconCopy } from '@archeblack/ui/icons';
</script>
<!--
El tooltip describe al botón (aria-describedby); el nombre sigue siendo el aria-label. Se abre
con el puntero después del retardo, y al instante con el foco del teclado.
-->
<Tooltip content="Copiar ID">
{#snippet trigger(props)}
<Button {...props} icon={IconCopy} aria-label="Copiar ID del proyecto" />
{/snippet}
</Tooltip> Lados
side elige el lado: top (por defecto), right, bottom o left.
<script lang="ts">
import { Button, Tooltip, type TooltipSide } from '@archeblack/ui';
const sides: { side: TooltipSide; label: string }[] = [
{ side: 'top', label: 'Arriba' },
{ side: 'right', label: 'Derecha' },
{ side: 'bottom', label: 'Abajo' },
{ side: 'left', label: 'Izquierda' }
];
</script>
<!-- Si no entra del lado pedido, el tooltip pasa al opuesto. -->
<div style:display="flex" style:flex-wrap="wrap" style:gap="var(--arche-spacing-2)">
{#each sides as { side, label } (side)}
<Tooltip content="side="{side}"" {side}>
{#snippet trigger(props)}
<Button {...props}>{label}</Button>
{/snippet}
</Tooltip>
{/each}
</div> Con proveedor
TooltipProvider comparte el retardo: después del primer tooltip, los vecinos se abren sin esperar. Va una sola vez, envolviendo el contenido del +layout.svelte raíz de la aplicación (esta documentación lo tiene ahí); sin él, cada tooltip usa los valores por defecto.
<script lang="ts">
import { Button, Tooltip } from '@archeblack/ui';
import { IconBold, IconItalic, IconLink } from '@archeblack/ui/icons';
</script>
<!--
El TooltipProvider va una sola vez, en el +layout.svelte de la aplicación (esta documentación lo
tiene ahí). Por él, después del primer tooltip los vecinos se abren sin esperar.
-->
<div role="group" aria-label="Formato" style:display="flex" style:gap="var(--arche-spacing-1)">
<Tooltip content="Negrita · ⌘B">
{#snippet trigger(props)}
<Button {...props} variant="ghost" icon={IconBold} aria-label="Negrita" />
{/snippet}
</Tooltip>
<Tooltip content="Cursiva · ⌘I">
{#snippet trigger(props)}
<Button {...props} variant="ghost" icon={IconItalic} aria-label="Cursiva" />
{/snippet}
</Tooltip>
<Tooltip content="Insertar link · ⌘K">
{#snippet trigger(props)}
<Button {...props} variant="ghost" icon={IconLink} aria-label="Insertar link" />
{/snippet}
</Tooltip>
</div> Props
Tooltip
| Prop | Descripción |
|---|---|
content string | El texto del tooltip. Es solo texto: describe al disparador y nunca lleva links ni botones. |
trigger Snippet<[TriggerAttributes]> | El disparador, obligatorio: el tooltip lo describe y se ancla a él. Recibe los atributos del disparador (id, aria-describedby mientras está abierto, los eventos de puntero y de foco y la referencia), que se esparcen en un elemento que tome el foco, casi siempre un Button: {#snippet trigger(props)}<Button {...props}>…</. |
side? 'top' | 'right' | 'bottom' | 'left' Por defecto 'top' | Lado del disparador en el que aparece. Si no entra, pasa al opuesto. |
align? 'start' | 'center' | 'end' Por defecto 'center' | Alineación sobre el lado elegido. |
delay? number | Retardo de apertura con el puntero, en ms. Por defecto, el del TooltipProvider (500). El foco lo abre sin esperar. |
disabled? boolean Por defecto false | El tooltip no se abre. |
bind:open? boolean Por defecto false | Si el tooltip está abierto. |
onOpenChange? (open: boolean) => void | Se llama cada vez que se abre o se cierra por sí mismo (puntero, foco o Escape), con el estado nuevo. Llega después de actualizar open y solo si el cambio se aceptó: si un bind:open de función lo rechaza, no se llama. |
class? ClassValue | Clases del producto; se suman a arche-tooltip. |
...rest HTMLAttributes<HTMLDivElement> | Cualquier otro atributo va al <div role="tooltip">. El rol y el contenido los decide el componente. |
TooltipProvider
| Prop | Descripción |
|---|---|
delay? number Por defecto 500 | Retardo de apertura con el puntero, en ms, de todos los tooltips que envuelve. |
skipDelay? number Por defecto 300 | Ventana en ms en la que, después de cerrar un tooltip, el siguiente se abre sin retardo. |
children Snippet | La aplicación. Va una sola vez, en el +layout.svelte de la raíz. |
Accesibilidad
- El contenido es un
<div role="tooltip">y, mientras está abierto, el disparador apunta a él conaria-describedby: el lector de pantalla lee primero el nombre del control y después el tooltip. - El tooltip describe, no nombra. Un botón de solo ícono sigue necesitando su
aria-label; el tooltip puede repetirlo o sumar algo, como el atajo de teclado. - Se abre al pasar el puntero, después del retardo, y al instante cuando el disparador recibe el foco del teclado. Se cierra con Escape, al salir con el puntero o al perder el foco.
- Se puede pasar el puntero del disparador al tooltip sin que se cierre, y no desaparece solo mientras el puntero o el foco siguen ahí (WCAG 1.4.13).
- El disparador tiene que poder recibir el foco. Un
<button disabled>no lo recibe ni dispara los eventos del puntero, así que su tooltip nunca aparece. - Texto
on-primarysobreprimary: el vacío sobre la luz, muy por encima de AA. En colores forzados, el tooltip lleva un borde del sistema. - Con movimiento reducido, aparece y desaparece sin escala ni fundido.
Qué evitar
- Links, botones o texto largo dentro del tooltip. Un
Popover: se abre con un clic, recibe el foco y admite contenido interactivo. - Un tooltip en lugar del nombre accesible de un botón de solo ícono. El
aria-labelen el botón y, si suma, un tooltip que lo describa. - Información imprescindible que solo está en el tooltip. Texto visible en la página o una ayuda del
Field: en pantallas táctiles no hay hover. - Un
TooltipProviderpor componente o por página. Uno solo, en el+layout.sveltede la raíz. - Un tooltip sobre texto estático o sobre un botón deshabilitado. El texto a la vista, o explicar por qué el botón está deshabilitado junto a él.