---
title: Addons
path: /v5/addons/
index: 13
---

Addons are external functions that control or create many different Tippy
instances, and can be tree-shaken away by bundlers.

### Event delegation

Event delegation allows you to let a common parent element handle the creation
of tippy instances for child elements.

This allows two things:

- It prevents the need to create new instances for new child elements appended
  to the parent.
- It improves performance as the creation of the tippy instances is deferred
  until they are triggered for the first time.

#### Usage

Your markup should have a structure like this example:

```html
<div class="parent">
  <button class="child">Text</button>
  <button class="child">Text</button>
  <button class="child">Text</button>
</div>
```

Pass a `targets` argument to the `delegate()` addon function (the same type the
`tippy()` function can accept) which represents the parent element(s) that
should act as a delegate, and a `target` prop representing a CSS selector that
should match the child elements which should receive a tippy.

```js
import {delegate} from 'tippy.js';

delegate('#parent', {
  target: '.child',
});
```

In the CDN (`iife`) version, it's available as `tippy.delegate()`

#### Return type

Because `delegate()` can create many different instances, it returns an opaque
value depending on the type supplied, just like `tippy()`.

```js
const delegateInstances = delegate('.parent', {
  target: '.child',
}); // Instance[]

const delegateInstance = delegate(parentElement, {
  target: '.child',
}); // Instance
```

#### Cleanup

By default, when you destroy a delegate instance, it also destroys any child
instances that may have been created by it. If you want to prevent this
behavior, pass `false` as an argument:

```js
const delegateInstance = delegate(parentElement, {
  target: '.child',
});

// Prevents further creation and destroys any created child tippy instances
delegateInstance.destroy();
// Prevents further creation only
delegateInstance.destroy(false);
```

#### Polyfill

This addon uses `Element.prototype.closest()`, which is not supported in older
browsers. You will need to polyfill this method to get full support.

---

### Singleton

A singleton is a single tippy element that takes the place of an array of
regular tippy instances.

This allows two things:

- Smooth transitions of the tippy between many different reference element
  targets
- Elements with tooltips next to each other that have a `delay` can be "grouped"
  so they appear to share a timeout, which greatly improves UX

See the [demo](/#singleton) for it in action.

#### Usage

Pass an **array** of tippy instances to the `createSingleton` addon function,
and a `delay` prop:

```js
import tippy, {createSingleton} from 'tippy.js';

const tippyInstances = tippy('button');
const singleton = createSingleton(tippyInstances, {delay: 1000});
```

In the CDN (`iife`) version, it's available as `tippy.createSingleton()`

#### Smooth transitions

Utilize the `updateDuration` prop, which is the transition duration between
position updates of the tippy element:

```js
const singleton = createSingleton(tippyInstances, {
  delay: 1000,
  updateDuration: 500,
});
```

> **Note**
>
> Enabling transitions may cause overflow issues if the tippy content is near
> the right/bottom edge of a boundary (e.g. window) and the tippy content
> changes from small to large. This is because of the transition causing the
> tippy to expand the boundary, making Popper.js think it will fit.

To solve this, constrain the tippy to the viewport:

```js
createSingleton(instances, {
  boundary: 'viewport',
});
```

#### Timing function

The `transition-timing-function` by default is `easeOutQuint`. Usually this
looks nice, but you can change this (to add an inertial slingshot effect for
example) like so:

```js
const singleton = createSingleton(tippyInstances, {
  updateDuration: 500,
  onCreate({popper}) {
    // Any easing function you want.
    popper.style.transitionTimingFunction = 'cubic-bezier(...)';
  },
});
```
