You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/eidos/components/tooltip/README.md

107 lines
7.8 KiB

# Eidos Tooltip
Fecha de revision: 2026-05-17.
## Baseline
Air no tenia `tooltip` en `glm-5:src/uix/air/components`; este componente es
una envoltura visual sobre Soma/Morfo, no un port de Air.
docs(theming): los 21 de la mañana recuperan su README y su pestaña Tokens La revisión de hoy (`REVIEW-theming-2026-08-23.md`, punto P4) destapó que NINGUNO de los commits de tokenización de la mañana del 23 hizo los pasos 8 y 9 del protocolo: `git show --stat` de los diecisiete sólo tocaba CSS, base.ts, el ledger y las fichas. Veintidós componentes tokenizados sin la tabla de tokens en su README y veintiuno sin la pestaña que la enseña viva. QUÉ ENTRA - **README «Talla y tema»** en 22 (los 21 con demo + `surface`, que no tiene ruta). La tabla NO está escrita a mano: se DERIVA de `lib/recipes/base.ts` y de `theming-sentinel-exceptions.ts`, así que lo que el lector ve es lo que el contrato dice. Hasta 30 claves va la tabla completa clave → valor por defecto; por encima, agrupada por parte (con la paleta en su propio grupo, que si no se come la tabla: button tiene 70 claves de tono de 106). Debajo, lo que el guard da por silencioso con su razón medida, y la excepción POR PATRÓN cuando la razón es la cascada de paleta. - **Pestaña `Tokens`** en los 21 con demo, con el conteo real de claves. VERIFICADO EN EL NAVEGADOR, LOS 21 Cada pestaña abre y lista exactamente sus claves: menubar 35 · field 68 · onion-menu 19 · button 106 · callout 34 · empty-state 26 · dropdown-menu 28 · context-menu 28 · checkbox 47 · image 23 · anchor-nav 12 · banner 53 · date-range-field 7 · time-range-field 7 · tooltip 23 · section 4 · sticky 1 · button-group 1 · qr-code 10 · toggle-group 1 · split-button 1. ⚠ Y el verificador mintió DOS veces antes de acertar: primero buscaba el rótulo de la cabecera del panel en `innerText` (no lo encontraba aunque la tabla estaba ahí), y después clicaba con `element.click()` tras `waitUntil: 'load'` — la página aún NO ha hidratado, así que el `onclick` de Svelte no está enganchado y el clic no hace nada. Con `networkidle` + el clic de Playwright (que espera a que el nodo sea accionable), los 21 en verde. Es la ley de siempre: el instrumento miente primero. `audio-player` queda fuera: no tiene README propio — hueco aparte, anotado. Verificación: `npm run check` sin errores nuevos en las 21 demos (los 72 globales son ajenos y preexistentes) · `docs:check` 0 · cada README conserva su estructura de encabezados y **ninguno gana un hunk de prettier** (mi sección se formateó dentro de su propio recorte, sin tocar lo ajeno). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
## Talla y tema
**23 clave(s) pública(s)** en `lib/recipes/base.ts` (bloque `tooltip`), con sus pasos por talla y el nombre RESUELTO que consume la receta.
Es el contrato vivo: la pestaña **Tokens** de su demo lista estas mismas
claves y las resuelve sobre el escenario.
| Token (`--tooltip-…`) | Valor por defecto |
| ---------------------- | -------------------------------------------------------------------------- |
| `content-z` | `var(--z-index-overlay-tooltip)` |
| `max-width` | `22rem` |
| `padding-block-sm` | `var(--space-1)` |
| `padding-inline-sm` | `var(--space-2)` |
| `padding-block-md` | `var(--space-1-5)` |
| `padding-inline-md` | `var(--space-2-5)` |
| `padding-block-lg` | `var(--space-2)` |
| `padding-inline-lg` | `var(--space-3)` |
| `font-size-sm` | `var(--size-sm-font-size)` |
| `font-size-md` | `var(--size-md-font-size)` |
| `font-size-lg` | `var(--size-lg-font-size)` |
| `font-family` | `var(--style-label-font-family)` |
| `font-weight` | `var(--font-weight-regular)` |
| `line-height` | `var(--leading-text)` |
| `radius` | `var(--radius-md)` |
| `border-width` | `var(--border-width)` |
| `bg` | `var(--color-surface-overlay)` |
| `fg` | `var(--color-content-primary)` |
| `border` | `color-mix( in srgb, var(--color-border-default) 84%, var(--tooltip-bg) )` |
| `shadow` | `var(--depth-overlay-shadow), var(--depth-overlay-halo)` |
| `ghost-blur` | `var(--blur-md)` |
| `outline-arrow-bg` | `var(--color-surface-default)` |
| `outline-arrow-border` | `var(--color-border-strong)` |
**Lo que el guard R-5.4 da por silencioso, con su razón medida**
(`scripts/theming-sentinel-exceptions.ts`):
- `content-z` — it lands on the floating WRAPPER, which carries no data-tooltip-\* attr and so is outside the measured set; read on the wrapper -> reaches (90 -> 4321)
- `bg` — SUPERSEDED by the overlay plane: [data-depth=overlay] declares background at the same specificity and later in the cascade, so the recipe loses. Measured: --tooltip-bg moves nothing, --depth…
- `border` — same supersession: --depth-overlay-border repaints it, --tooltip-border does not
- `shadow` — same supersession: --depth-overlay-shadow repaints it, --tooltip-shadow does not
- `font-family` — same plane, the typography half of it (PLAN 12.9, unsigned)
- `line-height` — same plane, same open decision
- `outline-arrow-bg` — the arrow is painted through a SIBLING selector that needs the content carrying data-variant=outline AND the panel open; measured with the demo switch -> reaches (oklch(0.9911 0 0) -> rgb(1,…
## Comparativa
| Referencia | Superficie relevante | Estado Eidos |
| --- | --- | --- |
| Air `glm-5` | No existe `tooltip` en Air. | Sin baseline Air. La referencia local es Soma/Morfo. |
| Soma actual | `Group`, `Provider`, `Trigger`, `Content`, `Arrow`; delay/skip-delay, hover/focus, hoverable content, disabled, side/align/collision, Floating CSS vars, `aria-describedby`, `role="tooltip"`. | Cubierto por passthrough. Eidos solo anade receta visual. |
| Radix Tooltip | Provider global, Root, Trigger, Portal, Content, Arrow; abre en hover/focus, cierra en activacion del trigger o Escape, custom timings, collision, CSS vars para transform-origin/available size/trigger size. | Cubierto. Se alinea Soma para cerrar al click de trigger por defecto y Eidos consume vars de Floating para medidas/animacion. |
| Ark UI Tooltip | Root, Trigger, Positioner, Arrow/ArrowTip, Content; control, root provider, delay, positioning, fixed containers, context. | Cubierto salvo `Positioner`/`ArrowTip` explicitos: en UIX viven dentro de Soma Floating/Arrow. |
| Bits UI / shadcn-svelte | Provider recomendado en layout, Root, Trigger, Portal, Content, Arrow; delayDuration, skipDelayDuration, disableHoverableContent, forceMount, Floating vars, nested providers. | Cubierto. `disableCloseOnTriggerClick` se soporta en Soma como escape hatch. |
Fuentes externas consultadas:
- Radix Tooltip: https://www.radix-ui.com/primitives/docs/components/tooltip
- Ark UI Tooltip: https://ark-ui.com/docs/components/tooltip
- Bits UI Tooltip: https://bits-ui.com/docs/components/tooltip
- shadcn-svelte Tooltip: https://www.shadcn-svelte.com/docs/components/tooltip
## Decisiones
- No se crea `Tooltip.Positioner`. La posicion pertenece a Soma Floating;
Eidos consume `data-side`, `data-align` y variables CSS publicadas por Soma.
- No se crea `Tooltip.ArrowTip`. Soma Arrow ya encapsula la geometria del
arrow; la receta solo pinta fill/stroke.
- `Tooltip.Content` mantiene `size` y `variant`, y anade `matchAnchorWidth`,
`width`, `minWidth`, `maxWidth`, `height`, `minHeight`, `maxHeight` como
props visuales responsivas.
- Las medidas se serializan como variables privadas del recipe
(`--_tooltip-content-*`); el contrato publico de tokens sigue siendo la
recipe.
- La receta usa `--floating-transform-origin` para animaciones
origin-aware y `--floating-available-height` como max-height por
defecto cuando Floating ya lo conoce.
- Soma cierra al activar/clicar el trigger por defecto, alineado con Radix. Si
se necesita mantenerlo abierto, usar `disableCloseOnTriggerClick`.
## Eventos Sema
El morfo declara tres eventos `emerge` minimos para que Sema pueda emitir
feat(morfo,sema,eidos): todo evento dice de que familia es, y el cruce por fin se ve El framework llamaba a la misma cosa de dos maneras: `open` pelado en ocho componentes y `emerge-open` en tres. No era estetica — un preset de movimiento engancha el nombre con `^=`, asi que el dialecto pelado no casaba con ninguna firma y simplemente no animaba, sin romper una sola prueba. Los 40 nombres sin prefijo pasan a `{familia}-{verbo}[-{matiz}]`: 256 eventos, 256 con prefijo, 0 ambiguos. El plan decia 36 y decia `handle-drag-start`; eran 40, y el canon (c25) dice que esos verbos son `pick` y `drop` — `handle-pick` y `handle-drop` ya existian en 10 y 4 componentes. `validateMorfo` cierra la puerta: un `events[].name` que no empiece por su familia ahora lanza. Visto fallar antes con un nombre pelado inyectado. Lo que el renombrado destapo, y va aqui tambien: - La receta del splitter enganchaba `commit-resize`, muerto desde `bd2e40366`. No casaba desde mayo y nadie chillo. Reescrita por FAMILIA, como slider y knob, y `eidos-lint` valida ahora el VALOR de `data-event*` contra el catalogo de morfos — el guard que lo habria cazado en su dia. - La familia `shift` era muda en el canal visual, contra su propia doctrina (c27: el cruce debe percibirse; c34 tipifica el «shift invisible»). Su mapa ya describia la firma que le faltaba y su sonido por defecto es `slide`. Ahora tiene firma direccional: sexto atributo del sello (`data-event-direction`, `forward`|`backward`, por emision) y deslizamiento de 320ms RTL-safe por `:dir()`. Medido: LTR -30px/+30px, RTL los invierte. - El sello de `shift-navigate` pasa del BOTON al `grid` en los cuatro calendarios. Medido: el boton recibia `contact-activate` y 8,5 ms despues —media trama— el `shift-navigate` pisaba la misma ranura y el `press-squeeze` moria sin pintar un fotograma. Una superficie, una ranura (A-36). - 101 contradicciones docs<->morfo adjudicadas con evidencia (git log, docs de decision, el componente vivo). Las docs desfasadas, corregidas; los nueve DEFECTOS de codigo obsoleto quedan abiertos y sin tocar. - `SoundDirection` -> `SoundContour`: era un contorno de tono, no un sentido, y habia tres cosas distintas deletreadas «direction». check en su linea base con 0 errores nuevos por diferencia de conjuntos · docs:check 0/0 · eidos-lint invalid 0 · el censo y las escenas de navegador medidas con raton real y rAF vivo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
percepcion en hover/focus reveal: `emerge-present`, `emerge-dismiss` y
`emerge-dismiss-escape` (Escape) — verbos del libro cap. 26 §8/§9: el tooltip
se OFRECE (present), no se invoca como lugar (open).
Ninguno carga intent — la aparicion de un tooltip no tiene peso evaluativo
propio. Si una experiencia necesita reforzar percepcion al mostrar ayuda
contextual con un tinte concreto, esa politica debe vivir en el componente
que dispara el tooltip, no en Tooltip por defecto.
## Gaps
| ID | Disposicion | Detalle |
| --- | --- | --- |
| `ignoreNonKeyboardFocus` (Bits UI) | **diferir** | Sin caso real en accesibilidad/focus management. No debe vivir en Eidos hasta que aparezca el patron concreto. |
| `customAnchor` (Bits UI) | **diferir** | Popover ya cubre panel flotante anclado a otro elemento. Si Tooltip lo necesita, anadir primero a Soma. |
| `data-disabled` aplicado a `Trigger` | **implementar** | Morfo declara `data-disabled` opcional; soma debe propagar la prop del wrapped element. La receta ya estiliza el estado disabled. |
| Tinte sema configurable por `intent` prop | **descartar** | Reveal asistivo no carga intent; forzar uno duplica responsabilidades con el componente que dispara el tooltip. |

Powered by TurnKey Linux.