Skip to content
This repository has been archived by the owner on Nov 9, 2024. It is now read-only.

v4.0.0

Compare
Choose a tag to compare
@atomiks atomiks released this 09 Feb 10:02
· 624 commits to master since this release

Install

npm i tippy.js@latest

Overall minzipped size has been reduced by about 400 bytes

Features / Improvements

  • followCursor: 'initial' works on touch devices too

  • scale animation has its transform origin sticking to the reference element

  • tippy.hideAll() method is now actually useful!

It no longer checks hideOnClick unexpectedly. In other words:

tippy.hideAll()

Does exactly what it says. All tippys will be hidden no matter what (using their own specified durations).

There's even options now too, for example, make all of them hide instantly (useful for scrolling):

tippy.hideAll({ duration: 0 })

Or exclude a particular instance from hiding:

tippy.hideAll({ exclude: tippyInstance })

  • tippy.group() method - finally, a built-in solution to #81!

How to use it:

const instances = tippy('button', { delay: 1000 })
tippy.group(instances)

// Optional:
tippy.group(instances, {
  duration: number | [number, number], // instead of 0 between each show,
  delay: number | [number, number], // if you didn't specify a delay in the instances
})

As simple as that, the tooltips will now instantly show when hovering between items in the group instead of waiting for the delay sluggishly.


  • updateDuration option is now 0 instead of 200 by default

Flips don't have the weird transition if using flipOnUpdate: true (note that it's off by default now). Specifying a number now uses true smooth flips, where the popper element smoothly transitions from one placement to another. The effect is quite satisfying.


  • role option - instead of tooltip, certain popovers may need to be menu or dialog for accessibility reasons.
tippy('button', {
  role: 'menu'
})

Breaking changes

  • 🔴 You no longer need to import CSS when using modules. It gets injected to the very top of the <head>, like the UMD version.
// v3
import tippy from 'tippy.js'
import 'tippy.js/dist/tippy.css'

// v4
import tippy from 'tippy.js'

Also, files renamed to index instead of tippy.

In case you don't want this, you still can import it separately:

import tippy from 'tippy.js/esm'
import 'tippy.js/index.css'

Additionally, everything exists in the root directory instead of under dist/. For example, themes:

import 'tippy.js/themes/light.css'

Why: cleaner import experience for consumers


  • 🔴 popper.js is external in all formats, so no more tippy.standalone. This means CDN includes must reference it separately.
<script src="https://unpkg.com/popper.js@1/dist/umd/popper.min.js"></script>
<script src="https://unpkg.com/tippy.js@4"></script>
<script>
  tippy('button')
</script>

Why: to prevent popper.js from becoming outdated and lagging behind popper releases, works like a dependency should


  • 🔴 Remove tippy.one(). Instead, an instance will be returned in two cases: if the reference is either an element or a virtual element
// v3
const collection = tippy('.btn')
const collection = tippy(document.querySelector('.btn'))
const instance = tippy.one('.btn')
const instance = tippy.one(document.querySelectorAll('.btn'))

// v4
// Instance
const instance = tippy(document.querySelector('.btn'))
const instance = tippy(virtualElement)
// Instance[]
const instances = tippy('#btn')
const instances = tippy('.btn')
const instances = tippy(document.querySelectorAll('.btn'))

Why: collections are not useful and don't need to exist. But we want to avoid an opaque return value if using a certain type. Therefore even if only a single element is given an instance when using a CSS selector, it always returns an array.


  • 🔴 Remove tippy.useCapture() and tippy.disableAnimations()

Why: .useCapture() is now default in v3 anyway. .disableAnimations() was for testing environments however the new delay value causes async behavior when hiding. In testing environments, use the following call to make everything synchronous:

tippy.setDefaults({ duration: 0, delay: 0 })

  • 🔴 Remove arrowTransform option

Why: Since introducing a bordered theme (light-border), using transforms distorts the shape of the arrow border. Arrow transforms should be specified in CSS using a theme.


  • 🔴 Remove autoFocus and shouldPopperHideOnBlur options. Remove all focus handling and leave it up to the developer.

Why: The recommended accessible popover is to append it directly after the reference element which requires no focus handling. This will ensure focusable elements inside the tippy can be tabbed to afterwards. Sometimes this can be problematic though, with regards to z-index /stacking issues and the popover needs to be appended to the body. In this case it's up to the developer to create modal-like behavior with a close button and focus trapping, they can programmatically call .focus() where need be.


  • 🔴 The AJAX image example (smooth transition): you must explicitly define transition styles on the tooltip now.

e.g. in the onShow() lifecycle:

onShow(instance) {
  const { tooltip } = instance.popperChildren
  tooltip.style.transitionDuration = '0.2s'
  tooltip.style.transitionProperty = 'visibility, opacity, height'
}

  • ⚠️ Rename performance to ignoreAttributes

Why: ignoreAttributes describes what it's doing, performance described the side effect of doing it


  • ⚠️ Rename tippy.hideAllPoppers() to tippy.hideAll()

Why: Shorter and more concise and conveys the same meaning


  • ⚠️ In event delegation mode, content and appendTo as functions receive the target element rather than the delegate reference

Why: It's actually useful this way


  • ⚠️ Rename livePlacement to flipOnUpdate, with much better behavior. It's now false by default. The tippy will still update its position on scroll, but flipping while scrolling/resizing, etc is disabled by default.

Why: Better UX (subjective) to keep the placement static after showing and prevent flips while scrolling


  • ⚠️ If your content is an element, and you change elements inside it, you must call instance.popperInstance.scheduleUpdate().

Why: MutationObserver is not as robust as a ResizeObserver and has been removed. If you want complete accuracy consider using a polyfill for ResizeObserver.


  • ⚠️ Opinioned CSS like font-smoothing has been removed. Tippy elements should inherit the global styles as much as possible.

Why: Let the developer have more control and not introduce unexpected styling


Fixes

  • Fix for tippys with delays when leaving the popper, it sometimes would not close

  • Correctly parse null in attributes