Skip to content

Anchored tooltips gain hover intent: show delay, warm window, tooltip-delay attribute#130

Open
ctate wants to merge 5 commits into
mainfrom
feat/tooltip-hover-intent
Open

Anchored tooltips gain hover intent: show delay, warm window, tooltip-delay attribute#130
ctate wants to merge 5 commits into
mainfrom
feat/tooltip-hover-intent

Conversation

@ctate

@ctate ctate commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Fixes the reported issue: tooltips painted the instant their trigger was hovered, so sweeping a toolbar flashed every tooltip. (Investigation found the reported behavior was actually the floor of a missing capability — <tooltip> was a static always-painted leaf with no hover path at all.)

  • Anchored tooltips become runtime-owned hover chrome: hidden until hover intent fires (700ms dwell), with a warm window — once any tooltip has shown, moving to a sibling trigger within 300ms shows it instantly (the Radix skipDelayDuration behavior our components mirror). <tooltip> joins dropdown-menu as an anchorable element; non-anchored tooltips keep their classic paint-when-rendered behavior, so every existing document lowers byte-identically.
  • Cores never hear hover — visibility is presentation chrome stamped through the same semantics.hidden channel as the dismissal echo, so accessibility snapshots and replay fingerprints reflect it.
  • Replay-honest timing: arming, deadlines, and the warm window derive entirely from journaled input/frame timestamps (the animation-anchor discipline) — no OS clock. A record→replay test pins that a hover-dwell session reproduces its show/hide frames byte-identically.
  • tooltip-delay attribute (milliseconds; 0 restores instant) on the tooltip element, registry attr code 80, schema_version 1 (additive). Defaults live as themable metric tokens (tooltip_show_delay_ms, tooltip_warm_window_ms). Validator teachings scope it to anchored tooltips; both engines verified in parity.
  • Behavior tests (each verified to execute via deliberate sabotage): sweep-shows-nothing, dwell-shows, leave-disarms, warm-window-transfer-and-expiry, delay-zero-instant, plus validator/lowering/parity tests and the replay pin. Docs: components tooltip page, generated vocab, LSP tables, and the native-ui skill.

Suites: full battery, validate, test-tooling, test-examples-native, test-ts-core-e2e, and the docs check — all green.

Fixes #125

@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
native-sdk Ready Ready Preview, Comment Jul 14, 2026 6:27am

ctate and others added 5 commits July 14, 2026 01:18
- ui_schema: tooltip (39) becomes anchorable; fresh attr code 80 tooltip-delay (.whole, field tooltip_delay) with the pins test re-pinned for the addition
- Options/Widget carry tooltip_delay (ms; -1 follows the new ControlMetricTokens tooltip_show_delay_ms/tooltip_warm_window_ms defaults of 700/300)
- Validator scopes tooltip-delay to tooltip beside anchor with teaching messages, mirrored in the LSP/docs attribute tables and covered in ui_markup_tests

Co-authored-by: Marcus Schiesser <17126+marcusschiesser@users.noreply.github.com>
- Anchored tooltips become runtime-owned chrome: adoption stamps them hidden, hover on their trigger arms the show delay, leaving disarms, a dwell past the deadline shows on the presented frame's recorded timestamp, and hiding opens the shared warm window that shows the next trigger's tooltip instantly
- Every transition steps on journaled input/frame timestamps (canvasRenderAnimationStartNsForView at pointer dispatch, GpuSurfaceFrameEvent.timestamp_ns at frame advance) and an armed delay rides the render-animation frame pump, so recorded sweeps replay byte-identically
- Escape dismissal clears the intent machine with the surface, and five behavior tests cover sweep-shows-nothing, dwell-shows, leave-disarms, warm transfer/expiry, and tooltip-delay=0
- Interpreter test: anchor + tooltip-delay stamp the widget declaration, the token-default and static leaves keep -1/null so existing documents lower byte-identically
- Compiled-vs-interpreter parity: identical trees and identical anchor/delay stamps across both engines for declared, defaulted, and static tooltips
- The markup e2e fixture gains an anchored tooltip (tooltip-delay="200") on the Add trigger through the stack pattern
- A recorded dwell arms, shows on the frame at the deadline, and hides on leave; two recordings are byte-identical and the replay verifies every per-frame fingerprint checkpoint on the journaled clock
… skill

- Tooltip reference page teaches the anchored stack pattern, the 700ms/300ms hover-intent windows, tooltip-delay=0, and gains the scoped attribute table (tooltip joins the anchor family in the generated vocab)
- native-ui skill enumerates anchor on tooltip and the tooltip-delay attribute; changelog fragment tells the feature story
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tooltip component should support delayed hover intent

1 participant