---
title: Plugins
path: /v6/plugins/
index: 13
---
Plugins are an extensible way to add functionality to tippy instances. By
splitting functionality into a plugin, components or routes that don't need the
plugin are not burdened with its bundle size cost.
### Exported plugins
These plugins are exported by the package:
- `animateFill`
- `followCursor`
- `inlinePositioning`
- `sticky`
### Usage
#### CDN (umd)
Included plugins (part of the [All Props](/all-props/) table) will work as
normal.
```js
tippy(targets, {
followCursor: true,
});
```
#### Modules (esm)
Modules have the benefit of tree-shaking, so explicitly importing the plugin is
required:
```js
import tippy, {followCursor} from 'tippy.js';
tippy(targets, {
followCursor: true,
plugins: [followCursor],
});
```
### Creating your own custom plugin
A plugin is created by defining an object with the following shape:
```js
const plugin = {
// Optional (if the plugin provides a prop to use)
name: 'propName', // e.g. 'followCursor' or 'sticky'
defaultValue: 'anyValue',
// Required
fn(instance) {
// Internal state
return {
// Lifecycle hooks
};
},
};
```
The plugin's function `fn` returns an object of lifecycle hooks. Plugins are
invoked per-instance and the plugin function definition takes the instance as an
argument, so you can use private variables to create internal state in the
plugin closure.
Here are some examples:
#### hideOnPopperBlur
Causes a popper to hide if no elements within it are in focus.
```js
const hideOnPopperBlur = {
name: 'hideOnPopperBlur',
defaultValue: true,
fn(instance) {
return {
onCreate() {
instance.popper.addEventListener('focusout', (event) => {
if (
instance.props.hideOnPopperBlur &&
event.relatedTarget &&
!instance.popper.contains(event.relatedTarget)
) {
instance.hide();
}
});
},
};
},
};
```
#### globalStore
Manages tippy instances within a global store.
```js
let tippyInstances = [];
const globalStore = {
fn(instance) {
return {
onCreate() {
tippyInstances.push(instance);
},
onDestroy() {
tippyInstances = tippyInstances.filter((i) => i !== instance);
},
};
},
};
// APIs to manipulate all tippy instances
export function updateAll(props) {
tippyInstances.forEach((instance) => {
instance.setProps(props);
});
}
```
#### hideOnEsc
Hides the tippy when the escape key is pressed.
```js
const hideOnEsc = {
name: 'hideOnEsc',
defaultValue: true,
fn({hide}) {
function onKeyDown(event) {
if (event.keyCode === 27) {
hide();
}
}
return {
onShow() {
document.addEventListener('keydown', onKeyDown);
},
onHide() {
document.removeEventListener('keydown', onKeyDown);
},
};
},
};
```
### TypeScript
Types that take `Props` (e.g. `Tippy`, `Delegate`, `CreateSingleton`) are
generics that accept an extended props interface:
```ts
import tippy, {Tippy, Props, Plugin, LifecycleHooks} from 'tippy.js';
interface CustomProps {
myCustomProp: boolean;
}
type FilteredProps = CustomProps &
Omit;
type ExtendedProps = FilteredProps & LifecycleHooks;
export const myCustomProp: Plugin = {
name: 'myCustomProp',
defaultValue: false,
fn: () => ({}),
};
export default (tippy as unknown) as Tippy;
```