Tooltip
Tooltips
מנוע אחד לטולטיפים בארסנל: Tippy.js, מתווית קצרה ועד תוכן עשיר (HTML, תמונה, קישור בפנים). בטלפון אין טולטיפ
#tooltips-which-one
Which one
- A short text label on a button, an icon, a corner button: Tippy as well, one engine.
- HTML (a picture, a link to click), many elements from one query, a text that changes on show: Tippy.js, set up in an effect.
- A product card (picture, title, price, tags) over a thumbnail: not a tooltip to build, a component.
#tippy
Tippy.js
tippy(element, options) in a useEffect, destroyed in its cleanup. The content can be a string of HTML, and one call can take many elements.For a picture, a link inside (interactive), the fields in a list, a label that changes on show (onShow + setContent, the slider arrows). All propscontent: 'text'
allowHTML: true
interactive: true
a picture, loading="lazy"
placement: top | bottom | left | right
import tippy from 'tippy.js'
import 'tippy.js/dist/tippy.css'
const ref = useRef<HTMLButtonElement>(null)
useEffect(() => {
if (!ref.current) return
// optional: skip it entirely where nothing can hover
// if (!matchMedia('(hover: hover) and (pointer: fine)').matches) return
const inst = tippy(ref.current, {
content: 'Open in a new tab',
placement: 'top',
animation: 'fade',
offset: [0, 8],
touch: false, // a tap goes straight through on a phone
})
return () => inst.destroy()
}, [])contentstring | Element | (ref) => …default''What it shows. A string prints as text unless allowHTML.allowHTMLbooleandefaultfalseRead a string content as HTML: a picture, a link, markup.placementPlacementdefault'top'top | bottom | left | right, each with-start/-end, orauto.interactivebooleandefaultfalseThe pointer can move into the tooltip and click a link in it.arrowboolean | string | SVGElementdefaulttrueThe demos setfalseon HTML content.offset[skidding, distance]default[0, 10]px. Most instances here use[0, 8].delaynumber | [show, hide]default0ms. The footer's field peek:[60, 0].themestringdefault''A name that CSS styles as.tippy-box[data-theme~='name']. The one theme here:uk-peek(components/uikit/UkPeek).touchboolean | 'hold' | ['hold', ms]defaulttrueAlwaysfalsein this project: see on a phone.
| Prop | Type | Default | What |
|---|---|---|---|
content | string | Element | (ref) => … | '' | What it shows. A string prints as text unless allowHTML. |
allowHTML | boolean | false | Read a string content as HTML: a picture, a link, markup. |
placement | Placement | 'top' | top | bottom | left | right, each with -start / -end, or auto. |
interactive | boolean | false | The pointer can move into the tooltip and click a link in it. |
arrow | boolean | string | SVGElement | true | The demos set false on HTML content. |
offset | [skidding, distance] | [0, 10] | px. Most instances here use [0, 8]. |
delay | number | [show, hide] | 0 | ms. The footer's field peek: [60, 0]. |
theme | string | '' | A name that CSS styles as .tippy-box[data-theme~='name']. The one theme here: uk-peek (components/uikit/UkPeek). |
touch | boolean | 'hold' | ['hold', ms] | true | Always false in this project: see on a phone. |
Rules
touch: falseon every instance (below).- A picture in the content gets
loading="lazy": tippy builds the content when the instance is created, so without it every page downloads every picture. - Create in the effect,
destroy()in its cleanup: every component here does.
Live in
- /about · UkExternalLink, the domain before you leave
- /docs/swiper · SyncWithVerticalText, the arrows name the next slide
- The studio footer · the fields column peeks at each field's picture (theme
uk-peek)
#tooltips-on-a-phone
On a phone: no tooltip
A tooltip needs hover, and a finger has none: on a phone a tap that opens one first is one tap too many (the link should just follow, the X should just close). By the input, never by the screen's width (a tablet with a mouse has hover, a touch laptop may not):
- Tippy:
touch: falseon the instance, its own switch for an input with no hover. The tooltip never opens from a touch and the tap goes straight through. The default for every tooltip here. - Tippy, not created at all:
matchMedia('(hover: hover) and (pointer: fine)')beforetippy(), when the element is hidden on a phone anyway or every instance costs something (UkLiveFrame's device buttons, the DEMOS tab).
