## tooltip (`poetry_tooltip`)

A floating label describing an element on hover or focus.

Class: Poetry::Ui::Tooltip::Component - BEM block `poetry-ui-tooltip`.
Slot REQUIRED: with_trigger (the described control) - a call without it raises.
- `align:` (symbol) - one of start|center|end, default "center" - Panel alignment along the chosen side.
- `align_offset:` (integer) - default 0 - Shift in pixels along the alignment axis.
- `avoid_collisions:` (boolean) - default true - Flips and shifts the panel to stay inside the viewport.
- `content_class:` (string) - The bubble's class merge seam (caller classes win on conflicts).
- `delay_duration:` (integer) - The hover-open delay in ms; nil inherits the provider's (default 0).
- `disable_hoverable_content:` (boolean) - When true the bubble closes as the pointer leaves the trigger - it cannot be hovered into; nil inherits the provider.
- `label:` (string) - Plain-text announcement override for rich content (the visual children stay; the announced body becomes this text).
- `open:` (boolean) - default false - Server-renders the tooltip open.
- `side:` (symbol) - one of top|right|bottom|left, default "top" - Which side of the anchor the panel opens on.
- `side_offset:` (integer) - default 0 - Gap in pixels between the anchor and the panel.
Slots: trigger (The described control - commonly a poetry Button (with_trigger(variant: :outline) { "Hover" }). The slot owns the state + timing wiring regardless of the composed content. NO aria-haspopup/expanded/controls - the tooltip is invisible as a popup; aria-describedby is written by the controller on open (and server-rendered only when open: true).; takes poetry_button props, not a block; with_trigger yields NOTHING to the block - no |param|, write content directly).
- PART `tooltip` - Root wrapper around the trigger and the bubble
- PART `tooltip-content` - The role=tooltip bubble - positioning, animation, and the open state ride here | states: data-open (bubble is open (the controller flips the pair at runtime)); data-closed (bubble is closed (the server-rendered state; hidden rides along)); data-instant=delay|focus (the open skipped the delay - warm-grace/programmatic or keyboard focus (runtime-only; absent on a delayed open)); data-side=top|right|bottom|left (always - the side (initial placement, re-resolved live by popper after flip)); data-align=start|center|end (always - the alignment (re-resolved live by popper)) | vars: --transform-origin (the anchor-facing origin popper writes for scale-in animation); --available-width (viewport space left for the bubble (popper, post-flip)); --available-height (viewport space left for the bubble (popper, post-flip)); --anchor-width (the anchor's measured width (popper)); --anchor-height (the anchor's measured height (popper))
- PART `tooltip-arrow` - The arrow wrapper (aria-hidden) - popper pins it to the bubble's anchor-facing edge and rotates it toward the anchor | states: data-side=top|right|bottom|left (written by popper alongside the content's - the resolved side, for per-side restyling)
- WIRING root: `poetry--core--tooltip` registers; values open, delay_duration (unless), disable_hoverable_content (unless) | `poetry--core--popper` registers; values side, align, side_offset, align_offset, avoid_collisions
- WIRING trigger: `poetry--core--tooltip` actions pointerMove on pointermove, pointerLeave on pointerleave, pointerDown on pointerdown, clickClose on click, focusOpen on focus, blurClose on blur | `poetry--core--popper` targets anchor
- WIRING content: `poetry--core--popper` targets content
- WIRING arrow: `poetry--core--popper` targets arrow
- RULE: with_trigger(compose: true) { |wiring| ... } composes YOUR control as the trigger: the block is yielded the trigger wiring (the Stimulus behavior the overlay needs; poppers add id/aria and their trigger slot, modals hand only the open action) - splat it onto a wiring-free control (poetry_sidebar_menu_button, a plain tag); without compose: the classic composed Button renders.
- RULE: Use poetry_tooltip - never hand-roll title-attribute replacements or hover divs.
- RULE: Tooltip content is TEXT and never interactive/focusable - links, buttons, or inputs inside are a contract violation (use Popover).
- RULE: Never put essential information only in a tooltip - touch users NEVER see it (no long-press path, by design).
- RULE: The tooltip DESCRIBES; it never names. Icon-only triggers still require label: on the composed Button.
- RULE: Wrap toolbar/button rows in ONE poetry_tooltip_provider so the warm grace makes the row feel continuous.
- RULE: Rich visual content needs label: (the plain-text announcement).
- RULE: Do not pin tooltips open as onboarding callouts - that is a Popover.
