דילוג לתוכן הראשי
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 props
content: '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.
  • allowHTMLbooleandefault false
    Read a string content as HTML: a picture, a link, markup.
  • placementPlacementdefault 'top'
    top | bottom | left | right, each with -start / -end, or auto.
  • interactivebooleandefault false
    The pointer can move into the tooltip and click a link in it.
  • arrowboolean | string | SVGElementdefault true
    The demos set false on HTML content.
  • offset[skidding, distance]default [0, 10]
    px. Most instances here use [0, 8].
  • delaynumber | [show, hide]default 0
    ms. 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]default true
    Always false in this project: see on a phone.
Rules
  • touch: false on 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: false on 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)') before tippy(), when the element is hidden on a phone anyway or every instance costs something (UkLiveFrame's device buttons, the DEMOS tab).