Navigation

Tooltip

<oblyx-tooltip> shows a short hint anchored to its own light-DOM trigger content on hover or keyboard focus. It's advisory only: for a surface with real interactive content, use popover instead.

Basic tooltip

Hover the button, or Tab to it, to reveal the tooltip.

HTMLKotlin
<oblyx-tooltip content="Search this table">
  <oblyx-button icon-only label="Search">
    <oblyx-icon name="search"></oblyx-icon>
  </oblyx-button>
</oblyx-tooltip>
oblyxTooltip(content = "Search this table") {
  oblyxButton(iconOnly = true, label = "Search") {
    oblyxIcon(name = OblyxIconName.SEARCH)
  }
}

Trigger content

<oblyx-tooltip> decides how to anchor itself from the shape of its own content, once, on connect. With exactly one element child, that real child element is the trigger: no wrapper is introduced around it, and anchor positioning is applied to it directly, as in the icon button above. With anything else (plain text, or more than one top-level element), the content is wrapped in one inline span that Oblyx owns and anchors instead.

Text-only trigger

No single element child, so Oblyx wraps the text in its own anchor span.

Prices update nightly.

HTMLKotlin
<p>
  Prices update
  <oblyx-tooltip content="Every night at 2am UTC, based on the previous day's close.">nightly</oblyx-tooltip>.
</p>
p {
  +"Prices update "
  oblyxTooltip(content = "Every night at 2am UTC, based on the previous day's close.") {
    +"nightly"
  }
  +"."
}

A trigger with no tabindex of its own (a plain <span>, for instance) still gets hover behaviour, but can never show the tooltip on keyboard focus, because it can never receive focus in the first place: the same as any other unfocusable element.

Showing and dismissing

Hover shows the tooltip after delay milliseconds (default 200) and hides it after hide-delay milliseconds (default 100) once the pointer leaves. That hide delay is also a deliberate hover bridge: moving the pointer from the trigger onto the tooltip's own popup surface cancels the pending hide, so a tooltip with a link or extra detail in it doesn't vanish while the pointer is still travelling toward it.

Keyboard focus shows the tooltip too, but only keyboard focus: a trigger focused programmatically (by a dialog auto-focusing it, say) or by a touch tap doesn't count, matched against :focus-visible directly. Touch is suppressed entirely on the hover path (matchMedia('(hover: none)')): the trigger itself is always fully tappable, only the hover hint is skipped, since a tap has no equivalent long-press gesture built in here. Escape dismisses an open tooltip immediately, and so does activating the trigger itself: a tooltip lingering over a control the user just pressed would be more distracting than useful.

Custom show and hide delays

Fast show (50ms) Slow hide (600ms)
HTMLKotlin
<oblyx-tooltip content="Shows almost immediately" delay="50">
  <oblyx-button variant="secondary">Fast show (50ms)</oblyx-button>
</oblyx-tooltip>
<oblyx-tooltip content="Lingers after the pointer leaves" hide-delay="600">
  <oblyx-button variant="secondary">Slow hide (600ms)</oblyx-button>
</oblyx-tooltip>
oblyxTooltip(content = "Shows almost immediately", delay = 50) {
  oblyxButton(variant = OblyxButtonVariant.SECONDARY) { +"Fast show (50ms)" }
}
oblyxTooltip(content = "Lingers after the pointer leaves", hideDelay = 600) {
  oblyxButton(variant = OblyxButtonVariant.SECONDARY) { +"Slow hide (600ms)" }
}

Focus

Tooltip never moves DOM focus off the trigger, and there is no focus trap anywhere in this component, the opposite of popover, deliberately. The popup is role="tooltip", connected to the trigger only through aria-describedby(merged with any description the trigger already has, so nothing is overwritten), never aria-label or aria-labelledby": a tooltip only ever adds to a trigger's existing accessible name, it never replaces it.

Placement and alignment

placement defaults to above and alignment to center, both different from popover's own defaults (below / start), matching where a hint conventionally appears versus where a menu-like surface does.

Tooltip placement and alignment

Below End / start
HTMLKotlin
<oblyx-tooltip content="Opens below" placement="below">
  <oblyx-button variant="secondary">Below</oblyx-button>
</oblyx-tooltip>
<oblyx-tooltip content="Opens to the end side, start-aligned" placement="end" alignment="start">
  <oblyx-button variant="secondary">End / start</oblyx-button>
</oblyx-tooltip>
oblyxTooltip(content = "Opens below", placement = OblyxTooltipPlacement.BELOW) {
  oblyxButton(variant = OblyxButtonVariant.SECONDARY) { +"Below" }
}
oblyxTooltip(content = "Opens to the end side, start-aligned", placement = OblyxTooltipPlacement.END, alignment = OblyxTooltipAlignment.START) {
  oblyxButton(variant = OblyxButtonVariant.SECONDARY) { +"End / start" }
}

Positioning

Placement is CSS anchor positioning (anchor-name / position-anchor /position-area / position-try-fallbacks), the same mechanism popover and menu use, with no JavaScript measurement and no positioning library. In a browser without it, the tooltip still shows and hides on hover and focus correctly, but not anchored beside its trigger: only the positioning degrades.

Reference

<oblyx-tooltip>

AttributeTypeDefaultDescription
contentstring | undefinedThe tooltip's text. Required; a tooltip with nothing to say has no reason to exist. A missing value is flagged loudly rather than silently rendering an empty popup.
placementabovebelowstartendaboveSide of the trigger the popup opens on.
alignmentstartcenterendcenterCross-axis alignment.
delaynumber200Hover show delay, in ms.
hide-delaynumberDEFAULT_HIDE_DELAY_MSHover hide delay, in ms. Also the WCAG 1.4.13 hover-bridge grace period, so a pointer moving from the trigger toward the tooltip content has time to arrive before it closes.