--- 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; ```