# Migration Guide
- [5.x to 6.x](#5x-to-6x)
- [4.x to 5.x](#4x-to-5x)
---
# 5.x to 6.x
Popper.js was updated to v2. The `instance.popperInstance` and `popperOptions`
APIs have changed. You can
[view its documentation here](https://popper.js.org/docs/v2/).
## Imports
`iife` was replaced with `umd` (Rollup chunking has been removed).
## HTML Content
To protect against XSS by default, `allowHTML` is now `false` by default. If
you're passing strings of HTML to `content`, you must set `allowHTML: true`.
## Themes
### If you were creating custom themes
View details
`.tippy-tooltip` has become `.tippy-box`, and theming is done via an attribute
now, to match the other props.
The following:
```css
.tippy-tooltip.tomato-theme {
background-color: tomato;
}
```
Has become:
```css
.tippy-box[data-theme~='tomato'] {
background-color: tomato;
}
```
> The `~=` attribute operator allows you to specify mutliple theme names like
> before with class names.
For `.tippy-arrow`, you'll need to specify its color on the `::before`
pseudo-element.
The following:
```css
.tippy-tooltip.tomato-theme[data-placement^='top'] > .tippy-arrow {
border-top-color: tomato;
}
```
Has become:
```css
.tippy-box[data-theme~='tomato'][data-placement^='top'] > .tippy-arrow::before {
border-top-color: tomato;
}
```
In addition, if you were altering the pixel values, it may need to be adjusted.
In addition, Popper 2 changed some attribute names.
This:
```css
.tippy-tooltip[data-out-of-boundaries] {
visibility: hidden;
}
```
Has become:
```css
.tippy-box[data-reference-hidden] {
visibility: hidden;
}
```
### If you were targeting `.tippy-popper`
View details
`.tippy-popper` is no longer a selector, and is considered an implementation
detail for the most part now. `[data-tippy-root]` attribute selector replaces it
if necessary.
## Instance
### If you were using `instance.popperChildren`
View details
This no longer exists due to the user's ability to specify any structured DOM
with `render()` (Headless Tippy).
To access the `.tippy-box` element with the default render function
(`.tippy-tooltip` in v5):
```js
const box = instance.popper.firstElementChild;
```
## Methods
### If you were using `.show()` or `.hide()` with a duration argument
View details
These no longer take a duration argument. Instead, use
`.setProps({duration: ...})` before calling them if necessary.
To replicate `.hide(0)`:
```js
instance.unmount();
```
## Props
### If you were using `boundary`
View details
Often, this was to solve a problem in Popper 1, where you set
`boundary: "window"`. This is no longer necessary. If you'd like to change it
anyway, you can set it in `popperOptions`:
```js
tippy(targets, {
popperOptions: {
modifiers: [
{
name: 'preventOverflow',
options: {
// equivalent to boundary: 'window' in v1, usually NOT necessary in v2
rootBoundary: 'document',
},
},
],
},
});
```
### If you were using `distance` or `offset`
View details
These have been merged into a single `offset` prop, to match Popper 2's new API.
The following:
```js
tippy(targets, {
offset: 5,
distance: 10,
});
```
Has become:
```js
tippy(targets, {
offset: [5, 10],
});
```
This tuple also directly replaces `offset: "5, 10"`.
### If you were using `flip`, `flipBehavior`, or `flipOnUpdate`
View details
All of these have been removed. To configure these, specify them in
`popperOptions`:
```js
tippy(targets, {
placement: 'bottom',
popperOptions: {
modifiers: [
{
name: 'flip',
// flip: false
enabled: false,
options: {
// flipBehavior: ['bottom', 'right', 'top']
fallbackPlacements: ['right', 'top'],
},
},
],
},
});
```
`flipOnUpdate` has no replacement yet. It's always `true`.
### If you were using `aria`
View details
This has become an object to allow for better configurability. By default Tippy
will infer what to use (`auto`), but this can be overridden.
Types:
```ts
interface Props {
// ...
aria: {
content?: 'auto' | 'describedby' | 'labelledby' | null;
expanded?: 'auto' | boolean;
};
}
```
```js
tippy(targets, {
aria: {
// `null` when interactive is enabled
content: 'auto', // `aria-*` attribute
// `true` when interactive is enabled
expanded: 'auto', // `aria-expanded` attribute
},
});
```
### If you were using `multiple` or relying on its behavior
View details
Due to static typing issues, it's been removed. Calling `tippy()` again on the
same element will now always create a new tippy for it. Avoid calling `tippy()`
multiple times on the same reference if you don't want multiple tippies created
for it.
### If you were using `updateDuration`
View details
It's now `moveTransition`, which is a whole transition string. This allows you
to specify the easing function.
```js
tippy(targets, {
moveTransition: 'transform 0.2s ease-out',
});
```
### If you were using `lazy`
View details
It's been removed. The `popperInstance` is now created and destroyed on
mount/unmount. If you were using this for ReferenceObjects, see below.
The following:
```js
tippy(targets, {
lazy: false,
onCreate(instance) {
instance.popperInstance.reference = {
clientWidth: 0,
clientHeight: 0,
getBoundingClientRect() {
return {
// ...
};
},
};
},
});
```
Has become a single prop:
```js
tippy(targets, {
getReferenceClientRect: () => ({
// ...
}),
});
```
This implements Popper 2's
[Virtual Elements API](https://popper.js.org/docs/v2/virtual-elements/).
## IE11
IE11 is not supported by default anymore, but can be polyfilled. View the
Browser Support page on the documentation for details.
---
# 4.x to 5.x
### Node
Make sure you have DEV warnings enabled by setting `NODE_ENV=development` and
ensuring your bundler replaces `process.env.NODE_ENV` with the string
`"development"`.
- **webpack**: via `mode` option
- **Rollup**: via `rollup-plugin-replace`
- **Parcel**: automatic
- **Browserify/Gulp/Grunt/others**:
[View details](https://vuejs.org/v2/guide/deployment.html#With-Build-Tools)
### Browser
```html
```
## Imports
Previously, the default import injected the CSS stylesheet into `
`:
```js
import tippy from 'tippy.js';
```
In v5, this import is now side-effect free to work better with dependencies when
users have CSP enabled or using frameworks that control the ``.
You should import the CSS separately:
```js
import tippy from 'tippy.js';
import 'tippy.js/dist/tippy.css';
```
You can however opt-in to use the injected CSS version, just like v4:
```js
// Just like v4
import tippy from 'tippy.js/dist/tippy-bundle.esm';
// Or CommonJS:
const tippy = require('tippy.js/dist/tippy-bundle.cjs');
```
## `data-tippy` attribute
This technique of auto initialization was removed to keep the import side-effect
free. Initializing via the `tippy()` constructor is required.
## Animations
### If you want the `animateFill` effect back (it's no longer default)
View details
Node:
```js
import tippy, {animateFill} from 'tippy.js';
import 'tippy.js/dist/tippy.css';
// These stylesheets are required for it to work
import 'tippy.js/dist/backdrop.css';
import 'tippy.js/animations/shift-away.css';
tippy(targets, {
animateFill: true,
plugins: [animateFill],
});
```
Browser:
```html
```
### If you were using default animations or creating custom animations
View details
- Make sure your `visible` state has no translation (of 0px, instead of 10px
like before).
- `shift-away`, `shift-toward`, `scale` and `perspective` need to be imported
separately now.
Node:
```js
import 'tippy.js/animations/scale.css';
```
Browser:
```html
```
## Props
### If you were using `interactive: true`
View details
When using `interactive: true`, the tippy may be invisible or appear cut off if
your reference element is in a container with:
- `position` (e.g. fixed, absolute, sticky)
- `overflow: hidden`
To fix add the following prop (recommended):
```js
tippy(reference, {
// ...
popperOptions: {
positionFixed: true,
},
});
```
Or, if the above causes issues:
```js
tippy(reference, {
// ...
appendTo: document.body,
});
```
⚠️ For the latter, you need to be employing focus mangement for accessibility.
### If you were using `arrowType: 'round'`
View details
Import the `svg-arrow` CSS, and the `roundArrow` string, and use the `arrow`
prop instead.
Node:
```js
import {roundArrow} from 'tippy.js';
import 'tippy.js/dist/svg-arrow.css';
tippy(targets, {
arrow: roundArrow,
});
```
Browser:
```html
```
### If you were using `followCursor`
View details
Node:
```js
import tippy, {followCursor} from 'tippy.js';
tippy('button', {
followCursor: true,
plugins: [followCursor],
});
```
Browser:
(Works as before.)
### If you were using `sticky`
View details
Node:
```js
import tippy, {sticky} from 'tippy.js';
tippy('button', {
sticky: true,
plugins: [sticky],
});
```
Browser:
(Works as before.)
### If you were using `target`
View details
Use `delegate()`.
Node:
```js
import tippy, {delegate} from 'tippy.js';
delegate('#parent', {target: 'button'});
```
Browser:
```html
```
### If you were using `showOnInit`
View details
It's now named `showOnCreate`, to match the `onCreate` lifecycle hook
### If you were using `size`
View details
It's been removed, as it's more flexible to just use a theme and specify the
`font-size` and `padding` properties.
### If you were using `touchHold`
View details
Use `touch: "hold"` instead.
### If you were using `a11y`
View details
Ensure non-focusable elements have `tabindex="0"` added to them. Otherwise, use
natively focusable elements everywhere possible.
### If you were using `wait`
View details
Use the `onTrigger` and `onUntrigger` lifecycles and temporarily disable the
instance.
```js
tippy(targets, {
onTrigger(instance) {
instance.disable();
// Make your async call...
// Once finished:
instance.enable();
instance.show();
},
onUntrigger(instance) {
// Re-enable the instance here depending on the async cancellation logic
instance.enable();
},
});
```
## Instances
### If you were using `instance.set()`
View details
```diff
- instance.set({});
+ instance.setProps({});
```
## Static methods
### If you were using `tippy.setDefaults()`
View details
```diff
- tippy.defaults;
+ tippy.defaultProps;
```
```diff
- tippy.setDefaults({});
+ tippy.setDefaultProps({});
```
### If you were using `tippy.hideAll()`
View details
In ESM/CJS contexts, it's no longer attached to `tippy`
Node:
```js
import {hideAll} from 'tippy.js';
hideAll();
```
Browser:
(Works as before.)
### If you were using `tippy.group()`
View details
Use `createSingleton()`.
Node:
```js
import tippy, {createSingleton} from 'tippy.js';
createSingleton(tippy('button'), {delay: 1000});
```
Browser:
```html
```
## Themes
### If you were using the included themes
View details
- `google` is now `material`
### If you were creating custom themes
View details
- `[x-placement]` attribute is now `[data-placement]`
- `[x-out-of-boundaries]` is now `[data-out-of-boundaries]`
- `.tippy-roundarrow` is now `.tippy-svg-arrow`
- `.tippy-tooltip` no longer has `padding` on it, rather the `.tippy-content`
selector does.
- `.tippy-tooltip` no longer has `text-align: center`
## Other
### If you were using virtual reference objects
View details
Set `instance.popperInstance.reference = ReferenceObject` in the `onTrigger`
lifecycle, or `onCreate` with `lazy: false`.
## Types
View details
- `Props` is not `Partial` anymore, it's `Required`
- `Options` removed (use `Partial`)
- `BasicPlacement` renamed to `BasePlacement`