V3 API / Wishlist 🌟
See original GitHub issueV3 Philosophy
Reduce mutations and side effects. There are a lot of mutations and side-effects happening right now everywhere in the lib which has caused strange hard to debug issues in the past and still does.
Since v0 the API has been to set the title attribute on the reference which is the tooltip content (if not html).
The idea behind that was it’s just like the native tooltip, but a tippy one instead - all you have to do is invoke tippy(). Additionally, it provided automatic fallback for unsupported browsers. But this involves removing the title and replacing it with a tippy one, a mutation that has caused various kinds of issues.
No setup for beginners: declaratively indicate that elements should have a tooltip 🐤
<button data-tippy="My tooltip">My button</button>
On load, all references with a data-tippy will have their tooltips initialized with the value specified. This isn’t required though, it’s just a “no setup required” way to create tooltips as long as the script is loaded in the document.
TODO: List of changes so far
Tests 🚥
v3 won’t be released until it has extensive coverage of the entire library. I’ve been putting this off because it’s a lot of work but it will be done for v3.
-
utils.js90% -
tippy.js100% -
createTippy.js70% -
bindGlobalEventListeners.js80%
tippy() call
- If a user supplies an invalid option that does not exist in
tippy.defaults, an error will be thrown
tippy(reference, { invalidOption: true })
// Error: invalidOption is not a valid option
- collection object is different
selector is not a good name for the first argument given to tippy, it can be a wide range of values. Therefore it will be named targets (inspired by animejs).
tooltips will be renamed to instances
tippy(firstArg, secondArg)
/*
{
targets: firstArg,
options: { ...Defaults, ...secondArg },
instances: [tip, tip, ...],
destroyAll() { ... }
}
*/
Instances
-
Refactored to a closure instead of a class for true privacy. Would rather not use a WeakMap or leave underscored
_propertyNamevariables on the instance. -
popperChildrenproperty. As you know tippys have the following structure:
<div class="tippy-popper">
<div class="tippy-tooltip">
<!-- if no arrow -->
<div class="tippy-backdrop"></div>
<!-- if no backdrop -->
<div class="tippy-arrow"></div>
<div class="tippy-content"></div>
</div>
</div>
The tippy instance will now contain this property to easily access the element nodes:
popperChildren: {
tooltip: Element,
content: Element,
arrow: Element || null,
backdrop: Element || null
}
-
set()
instance.set(options)
Currently there is no way to update options at runtime reliably except for ones that aren’t init-related. You need to destroy the tooltip instance and make a new one. Also it involves mutating the options object. For example, while options.delay can be updated any time and the change will be reflected, options.arrow can’t.
instance.set({ arrow: true, duration: 0 }) // the tooltip will be "re-rendered" to reflect the change
Naming
is will be added as a prefix to things that are bools to make them more semantic.
- Semantic naming
In tippy instances:
state: {
isEnabled,
isDestroyed,
isVisible
}
In tippy.browser
{
isIE: /MSIE |Trident\//.test(nav.userAgent),
isIOS: /iPhone|iPad|iPod/.test(nav.platform) && !win.MSStream,
isSupported: 'MutationObserver' in win,
supportsTouch: 'ontouchstart' in win,
isUsingTouch: false,
userInputDetectionEnabled: true,
onUserInputChange: () => {}
}
DOM
-
[data-tippy-reference]attribute has replaced the[data-tippy]attribute to indicate an element has an active tippy.
setAttr(
reference,
options.target ? 'data-tippy-delegate' : 'data-tippy-reference'
)
CSS
-
.tippy-iOS { cursor: pointer }replaces the.tippy-touchselector, as it only ever applies to iOS devices. - inline animation styles for configurable shifting/scale etc.
- skewed arrows
Options
-
touchis the tooltip displayed on touch devices? -
allowTitleHTML=>allowHTML -
multiplenow means: can the reference have more than one tippy instance? (Will need to think of a different name for the previous one). -
createPopperInstanceOnInit=>lazy(reversed). Current is too verbose and lazy describes the behavior pretty well. -
content
Removed: ~title~ attribute, ~html~
We’ll just have a content option, which covers both title and html. This is distinct from setting a value to data-tippy if you don’t want it created on load.
<button data-tippy-content="My tooltip">My button<button>
<script>tippy('button')</script>
or
<button>My button</button>
<script>
tippy('button', {
// text
content: 'My tooltip',
// html
content: '<strong>My tooltip</strong>',
// element
content: document.querySelector('template'),
// clone element (no more selector string)
content: document.querySelector('template').cloneNode(true)
})
</script>
-
a11y: true/false
Ensures accessibility by determining if the reference element can receive focus.
export const elementCanReceiveFocus = el =>
matches.call(
el,
'a[href],area[href],button,details,input,textarea,select,iframe,[tabindex]'
) && !el.hasAttribute('disabled')
// Usage
if (!elementCanReceiveFocus(reference)) {
// set tabindex="0" attribute.
}
Browser support 💻
For V3, I’m officially declaring that I don’t care about browsers whose usage share is less than 0.5% worldwide. 📉
This means IE11 is still supported. I will continue to care about it until it falls under the threshold 😞 .
Desktop fallback 🖥
Fallback will need to be handled manually, as it’s a mutation that I don’t want to deal with and can vary a lot based on your usage during the lifetime of a tooltip.
const content = 'My tooltip'
tippy(reference, { content })
if (!tippy.browser.isSupported) {
reference.title = content
}
Mobile fallback 📱
title attributes don’t show up on mobile. The ideal solution would honestly to be just inline the tooltip content next to the reference if it’s not a supported browser. It won’t be pretty, but at least the tooltip content will be shown to the user.
Maybe I can have a built-on solution for this.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:4
- Comments:18 (7 by maintainers)

Top Related StackOverflow Question
Yep, I haven’t added one yet, but I’m going to make a PR for it and clean up all the Rollup scripts 😄 so the next version will have it. Not really related to V3 as it’s not a breaking change
I am using Tippy with Angular. When the new version comes out I will make a DefinitelyTyped definition for the new API
Thanks for creating such a customizable library 👍