Components
TooltipLayer
One tooltip for the whole application, driven by a data-tip attribute.
One tooltip for the whole application. Mounted once at the root, after which any element with a data-tip attribute gets a tooltip — nothing to wrap and nothing to import.
Example
import { TooltipLayer } from "@toimetdev/pathlogs-core";
// once, at the root of the app
<TooltipLayer />
// anywhere afterwards
<button data-tip="Archive project">…</button>
<span data-tip="Blocked by UI-12">🔒</span>The tooltip appears above the element, or below it when there is not enough room above, and is always kept inside the window horizontally.
Why a layer and not a wrapper
Side benefits of the approach:
- a tooltip can be attached to a server component — the attribute needs no JS;
- the DOM holds one bubble rather than a hundred hidden ones;
- nothing has to be imported at the point of use.
The price: fixed coordinates go stale on scroll, so the tooltip simply hides while scrolling.
Accessibility
Screen readers announce the native title, but not a custom attribute. So the layer sets aria-label itself on elements that have no visible text and no aria-label of their own:
<!-- before -->
<button data-tip="Column settings"><svg …/></button>
<!-- after -->
<button data-tip="Column settings" aria-label="Column settings"><svg …/></button>Elements with text are left alone: their accessible name is already the visible text, and duplicating it in a tooltip would mean reading the same thing twice. New elements are picked up through a MutationObserver.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
attribute | string | "data-tip" | The anchor attribute. Change it if data-tip is already taken. |
maxWidth | number | 220 | Maximum bubble width, px. |
gap | number | 8 | Gap between the element and the bubble, px. |
attributestringdefaults to: "data-tip"
The anchor attribute. Change it if data-tip is already taken.
maxWidthnumberdefaults to: 220
Maximum bubble width, px.
gapnumberdefaults to: 8
Gap between the element and the bubble, px.