JavaScript Tooltip
@lemonadejs/tooltip · ✓ 13 contract checks · framework-agnostic · zero dependencies
<Tooltip /> — a floating label for any element.
Wraps its children and shows a small dark pill on hover/focus of the
wrapper; hides on leave/blur/Escape. The popper is HOVERABLE (WCAG
1.4.13): leaving the wrapper starts a short grace timer instead of
hiding, so the pointer can travel across the gap onto the popper —
re-entering the subtree (trigger or popper) cancels the hide. While
visible, the trigger children are wired to the popper through
aria-describedby. Self-contained on purpose: a tooltip is too small to
compose <Modal /> — no chrome, no drag, no focus management, just one
branch and four coordinates.
<${Tooltip} title=“Save your work” position=“top”>
<button>Save</button>
</${Tooltip}>
Placement: the popper is position:fixed, its coordinates computed from the wrapper’s getBoundingClientRect at show time. When the requested side would leave the viewport the popper FLIPS to the opposite side (the modal’s autoadjust idea, specialized to four sides) — the effective side is published as data-position so the arrow follows.
Example
import { html } from 'lemonadejs';
import Tooltip from '@lemonadejs/tooltip';
const App = (props, { state }) => {
const saved = state('');
return html`<div style="display:flex;gap:12px;align-items:center;padding:36px 0">
<${Tooltip} title="Save the draft (Ctrl+S)" position="top">
<button onclick="${() => (saved.value = 'Draft saved at ' + new Date().toLocaleTimeString())}">Save</button>
</${Tooltip}>
<${Tooltip} title="Share a read-only link" position="bottom">
<button>Share</button>
</${Tooltip}>
<${Tooltip} title="Deleting is permanent" position="right">
<button>Delete</button>
</${Tooltip}>
<span>${saved}</span>
</div>`;
};Installation
npm install @lemonadejs/tooltip
import Tooltip from '@lemonadejs/tooltip';
import '@lemonadejs/tooltip/style.css';
Three deployment forms, one component:
html`<${Tooltip} />` // by value (no registration)
setComponents({ Tooltip }); // then <Tooltip /> by name anywhere
createWebComponent(Tooltip); // <lm-tooltip> in plain HTML/any framework
Props
Every declared prop arrives as a live state — pass a value for a snapshot or a state for a two-way live wire. Attribute strings are coerced to the declared type.
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | '' | the tooltip text (live) |
position | string | '' | ” = top |
delay | number | 100 | ms before showing |
arrow | boolean | true | small arrow pointing at the wrapper |
disabled | boolean | false | never shows |
Events
All event names are lowercase (the platform convention — LJS-305 warns otherwise).
onopen— fires when the popper appearsonclose— fires when a visible popper hides
Styling
All classes follow the lm-tooltip-* convention; visual variants are data-*
attributes on the root. Override freely — there is no styling engine to fight.
Contract
The machine-readable schema ships with the package:
import contract from '@lemonadejs/tooltip/contract.json';
verify.json carries the conformance proof produced by verify(Tooltip).
Looking for the v5 plugin? See the archived v5 documentation.