Releases: atomiks/tippyjs
v4.0.2
v4.0.1
v4.0.0
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 now0
instead of200
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 oftooltip
, certain popovers may need to bemenu
ordialog
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 moretippy.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()
andtippy.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
andshouldPopperHideOnBlur
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'
}
⚠️ Renameperformance
toignoreAttributes
Why: ignoreAttributes
describes what it's doing, performance
described the side effect of doing it
⚠️ Renametippy.hideAllPoppers()
totippy.hideAll()
Why: Shorter and more concise and conveys the same meaning
⚠️ In event delegation mode,content
andappendTo
as functions receive the target element rather than the delegate reference
Why: It's actually useful this way
⚠️ RenamelivePlacement
toflipOnUpdate
, with much better behavior. It's nowfalse
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 yourcontent
is an element, and you change elements inside it, you must callinstance.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
v4.0.0-alpha.0
Install
npm i tippy.js@next
Overall minzipped size has been reduced by about 400 bytes
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 moretippy.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()
andtippy.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
andshouldPopperHideOnBlur
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.
⚠️ Renameperformance
toignoreAttributes
Why: ignoreAttributes
describes what it's doing, performance
described the side effect of doing it
⚠️ Renametippy.hideAllPoppers()
totippy.hideAll()
Why: Shorter and more concise and conveys the same meaning
⚠️ In event delegation mode,content
andappendTo
as functions receive the target element rather than the delegate reference
Why: It's actually useful this way
⚠️ RenamelivePlacement
toflipScroll
, with much better behavior. It's nowfalse
by default. The tippy will still update its position on scroll, but flipping while scrolling is disabled.
Why: Better UX (subjective) to keep the placement static after showing and prevent flips while scrolling
⚠️ If yourcontent
is an element, and you change elements inside it, you must callinstance.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
Features / Improvements
- ✅
followCursor: 'initial'
works on touch devices too
- ✅
updateDuration
option is now0
instead of200
by default
Flips don't have the weird transition if using flipScroll: 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.
- ✅ Padding between popper and container/viewport edges has been reduced to 2px from 5px by default
- ✅
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.
- ✅
role
option - instead oftooltip
, certain popovers may need to bemenu
ordialog
for accessibility reasons.
tippy('button', {
role: 'menu'
})
v3.4.1
v3.4.0
v3.3.0
Features
Fixes
popper.js^1.14.6
includes position rounding fixes- Fix slight text blurriness on Safari when
animateFill: true
google
theme adheres tosize
option- Arrow centering fixes for
light-border.css
due to Popper.js issue
v3.2.0
Deprecations
- Deprecate
tippy.useCapture()
and make capture phase for the global click listener default. This prevents the need to wrap calls to.show()
insetTimeout
if manually triggering the tooltip after a click event somewhere
Fixes
- Add
characterData
to the popper mutation observer so changes to textual content within a tippy is detected and its position updated accordingly. Mainly noticeable in React updates. - Use
state.isMounted
overstate.isVisible
to determine ifhide(0)
should be called when destroying a tippy. This was not a leak but caused glitches when using the React component after changing routes and unmounting the Tippy component.