Tooltip
Hover- and focus-activated tooltip with a configurable delay and four placements (top, bottom, left, right). State holds visible only — the bubble's position comes from a single CSS attribute selector keyed on data-placement.
Live preview
Markup
<div class="tooltip-wrap"
data-component="tooltip-demo"
data-label="Saved 3 minutes ago"
data-placement="top">
<button
@mouseenter="show" @mouseleave="hide"
@focus="show" @blur="hide">
Hover me
</button>
<span class="tooltip-bubble"
data-if="visible"
data-bind="data-placement:placement"
data-text="label"></span>
</div>
Definition
Micra.define('tooltip-demo', {
state: { visible: false, label: '', placement: 'top' },
onCreate() {
this.state.label = this.prop('label', '')
this.state.placement = this.prop('placement', 'top')
},
onDestroy() {
clearTimeout(this._timer)
},
show() {
clearTimeout(this._timer)
this._timer = setTimeout(() => { this.state.visible = true }, 200)
},
hide() {
clearTimeout(this._timer)
this.state.visible = false
},
})
Integration
- Hover + focus. Bind both @mouseenter / @mouseleave and @focus / @blur so keyboard users see the tooltip too. Skipping focus events makes the tooltip inaccessible.
- Delay. The 200ms setTimeout avoids flashing on accidental hover. Always clear it in hide() and onDestroy().
- Placement. Passed via data-placement server-side, read once in onCreate. The CSS attribute selector .tooltip-bubble[data-placement="top"] positions the bubble — no JS positioning math needed for static placements.
Pitfalls
- Don't set visible = true synchronously in show() if you want a delay — the user sees a flicker on transient hover.
- Don't forget clearTimeout in onDestroy. Without it, a pending timer fires after destroy and writes to state of a torn-down instance (silent no-op, but a real leak).
- For dynamic positioning (collision detection, viewport flips) use a positioning library like Floating UI — Micra doesn't ship geometry helpers.