j3w1 / TooltipVue · HTML · React · Astro

J3W1 / DESIGN SYSTEM

Tooltip

A short description of a control shown on hover and focus; role tooltip linked by aria-describedby, a 1px overlay border on the raised surface, no arrow.

stable · LIGHT DOM · 1.1.0

Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.

Live variants

default

<j3w1-tooltip id="example-tooltip-default"><div class="tooltip">
  <button class="tooltip-trigger" type="button" aria-describedby="example-tooltip-default-tt-reload">Reload</button>
  <div class="tooltip-popup" role="tooltip" id="example-tooltip-default-tt-reload">Reload the window and keep the layout.</div>
</div></j3w1-tooltip>

with-shortcut

<j3w1-tooltip id="example-tooltip-with-shortcut"><div class="tooltip">
  <button class="tooltip-trigger" type="button" aria-describedby="example-tooltip-with-shortcut-tt-split">Split</button>
  <div class="tooltip-popup" role="tooltip" id="example-tooltip-with-shortcut-tt-split">Split the focused container horizontally <kbd class="tooltip-shortcut">Mod+h</kbd></div>
</div></j3w1-tooltip>

Install and register

Use the exact version. If npm publication is pending, install the release tarball from the installation guide.

npm install --save-exact @j3w1/ui@1.1.0
import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/tooltip.css';
import '@j3w1/ui/register/tooltip';

Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.

Vue SFC, React, Astro and plain HTML integration →

Copy the complete implementation

npx --package=@j3w1/ui@1.1.0 j3w1-ui copy tooltip --out ./vendor/j3w1/tooltip

The CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.

Public API

attributes

NameType / signatureMeaning
disabledCustomEventDisable the native controls owned by this instance.
loadingCustomEventMark the primary control busy and prevent duplicate activation.

properties

NameType / signatureMeaning
disabledbooleanDelegates disabled state to native children.
namestringNative control name; application form keys remain explicit.
openbooleanCurrent tooltip visibility. Read only.

methods

NameType / signatureMeaning
refresh(): voidReconnect behavior after replacing native child structure.
focus(options?: FocusOptions): voidFocus the first usable native control.
show(): voidShow the description unless dismissed in this hover/focus session.
hide(): voidHide and cancel pending timers.

events

NameType / signatureMeaning

Dependencies and verification

Registered components: none. Style dependencies: none.

Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.

Full implementation manifest, API and token dependency closure

Canonical specification

Purpose

A few words that explain a control without being its name: what an icon button does, which shortcut opens it, why it is disabled. It is a description only. Anything a person must read to use the control belongs in the control or its label, and anything interactive is a popover.

Anatomy

The trigger and the popup. The popup is color.surface.raised behind a 1px color.border.overlay, text in color.text.default, optional shortcut in a kbd with color.text.bright inside a 1px color.border.control; no arrow, no shadow, no radius. The demonstration renders it in flow below the trigger.

States

StateVisualNon-colour channel
defaulttrigger at rest; the popup shown for the demonstrationaria-describedby on the trigger
hovertrigger background → color.action.tertiary.hover-bg; the popup appears after 300 mscursor: pointer; the popup itself
focus-visiblering 1px dashed color.interaction.focus.ring at −2px on the trigger; the popup appears at oncethe ring; the popup
openthe popup visible, 1px color.border.overlay on color.surface.raisedthe popup is present in the accessibility tree
closedthe popup absent; the trigger unchangedhidden; the description is still read from the DOM

The popup itself has no hover, pressed or focus state: it is not interactive.

Keyboard

Focus on the trigger shows the tooltip without delay; moving focus away hides it. Escape hides it and does nothing else, so a dialog behind the trigger does not close. The popup never receives focus and contains no focusable element.

Accessibility

The trigger points at the popup with aria-describedby, so the description is available whether or not the popup is shown; the popup is role="tooltip". It opens on hover and on focus, stays open while the pointer is over the trigger or the popup (WCAG 1.4.13: hoverable, dismissible, persistent), and closes on Escape. The trigger has its own accessible name; the tooltip never supplies it. Touch has no hover: the description is available through a long-press or is shown inline. Contrast: text 8.43:1 on the raised surface, shortcut 10.10:1, border 4.57:1.

Portability

A box with a border and text; placement is the host’s positioning primitive. Toolkits with a native tooltip use it with the tokens for border and background and record any radius they cannot remove.

Non-examples

A rounded bubble with an arrow. A tooltip with a shadow or a fade longer than 150 ms. A tooltip as the only accessible name of an icon button. A tooltip with a link or a button inside. One that opens on focus but not on hover, or on hover with no delay. A title attribute. A tooltip that follows the pointer.

j3w1 / command

  • SPEC Overview
  • SPEC Foundations
  • SPEC Components
  • SPEC Patterns
  • SPEC Tokens
  • SPEC Tools
  • SPEC Implement
  • SPEC For agents
  • SPEC Ports
  • SPEC Releases
  • DEMO Vue application demo
  • SPEC Complete UI theme specification