- Notifications
You must be signed in to change notification settings - Fork98
React component for Tippy.js (official)
License
atomiks/tippyjs-react
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
If you're new here, we recommend usingFloating UI's React DOM Interactions package instead of this library. It offers a first class React experience rather than being a wrapper around a vanilla library and encourages much better accessibility practices with more flexibility.
If you want some out-of-the-box styling and animations, and are adding simple tooltips/popovers to your app, Tippy will still work fine. For more advanced/headless solutions, it's best to use Floating UI!
Tippy.js is the complete tooltip,popover, dropdown, and menu solution for the web, powered by Popper.
Tippy is an abstraction over Popper that provides common logic involved in alltypes of elements that pop out on top of the UI, positioned next to a target orreference element. This is a React wrapper for the core library, providing fullintegration including headless rendering abilities.
# npmnpm i @tippyjs/react# Yarnyarn add @tippyjs/react
CDN:https://unpkg.com/@tippyjs/react
There are two ways to use this component:
- Default: With the built-in DOM rendering and optionally the default CSS.This is complete "out of the box" behavior and requires no setup. If you wantsomething that just works, this is for you.
- Headless: With React's DOM rendering for improved usage with CSS-in-JS andspring libraries. If you want greater control over your poppers to integratefully with design systems, this is for you.
Both may be used in conjunction.
Import theTippy
component and (optionally) the core CSS. Wrap the<Tippy />
component around the element, supplying the tooltip's content as thecontent
prop. It can take a string or a tree of React elements.
importReactfrom'react';importTippyfrom'@tippyjs/react';import'tippy.js/dist/tippy.css';// optionalconstStringContent=()=>(<Tippycontent="Hello"><button>My button</button></Tippy>);constJSXContent=()=>(<Tippycontent={<span>Tooltip</span>}><button>My button</button></Tippy>);
Default Tippy "just works" out of the box.
Render your own tippy element from scratch:
importReactfrom'react';importTippyfrom'@tippyjs/react/headless';// different import path!constHeadlessTippy=()=>(<Tippyrender={attrs=>(<divclassName="box"tabIndex="-1"{...attrs}> My tippy box</div>)}><button>My button</button></Tippy>);
attrs
is an object containingdata-placement
,data-reference-hidden
, anddata-escaped
attributes. This allows you to conditionally style your tippy.
To make Popper position your custom arrow, set adata-popper-arrow
attributeon it:
<Tippyrender={attrs=>(<Box{...attrs}> Hello<Arrowdata-popper-arrow=""/></Box>)}><button>Reference</button></Tippy>
For details on styling the arrow from scratch,take a look at the Popper tutorial.
Note: your arrow must be anHTMLElement
(not anSVGElement
). To use an SVGarrow, wrap it in a<div>
tag with thedata-popper-arrow
attribute.
You may also pass a ref to the element directly without the attribute using acallback ref:
functionApp(){const[arrow,setArrow]=useState(null);return(<Tippyrender={attrs=>(<Box{...attrs}> Content<Arrowref={setArrow}/></Box>)}popperOptions={{modifiers:[{name:'arrow',options:{element:arrow,// can be a CSS selector too},},],}}><button>Reference</button></Tippy>);}
When rendering an element with therender
prop, you're rendering the innerelement that the root popper (positioned) node wraps.
For advanced cases you can access the root element viainstance.popper
.
Here'smoveTransition
with Framer Motion.
If you want to use a component element as a child of the component, ensure youforward the ref to the DOM node:
importReact,{forwardRef}from'react';functionThisWontWork(){return<button>Reference</button>;}constThisWillWork=forwardRef((props,ref)=>{return<buttonref={ref}>Reference</button>;});functionApp(){return(<Tippycontent="Tooltip"><ThisWillWork/></Tippy>);}
styled-components
v4+ does this for you automatically, so it should beseamless when using thestyled
constructor.
Workaround for old libraries that don't forward the ref is to use a<span>
wrapper tag:
<Tippycontent="Tooltip"><spantabIndex="0"><LegacyComponent>Reference</LegacyComponent></span></Tippy>
All of the native Tippy.js props can be passed to the component.
VisitAll Props to view thecomplete list.
<Tippycontent="Tooltip"interactive={true}interactiveBorder={20}delay={100}><button>Reference</button></Tippy>
In addition, there are 3 more props added specifically for the React component.
<Tippycontent="Tooltip"className="hello world"><button>Reference</button></Tippy>
This allows you to usestyled(Tippy)
or thecss
prop instyled-components
oremotion
.
Note: Does not apply if using Headless Tippy.
functionApp(){const[disabled,setDisabled]=useState(false);return(<Tippycontent="Tooltip"disabled={disabled}><button>Reference</button></Tippy>);}
Use React's state to fully control the tippy instead of relying on the nativetrigger
andhideOnClick
props:
functionApp(){const[visible,setVisible]=useState(true);constshow=()=>setVisible(true);consthide=()=>setVisible(false);return(<Tippycontent="Tooltip"visible={visible}onClickOutside={hide}><buttononClick={visible ?hide :show}>Reference</button></Tippy>);}
Available from
v4.1.0
If you can't place your reference element as a child inside<Tippy />
, you canuse this prop instead. It accepts a ReactRefObject
(.current
property) or aplainElement
.
functionApp(){constref=useRef();return(<><buttonref={ref}/><Tippycontent="Tooltip"reference={ref}/></>);}
Tippy.js splits certain props into separate pieces of code called plugins toenable tree-shaking, so that components or routes that don't need the prop'sfunctionality are not burdened with the bundle size cost of it. In addition,they enable a neat way to extend the functionality of tippy instances.
importTippyfrom'@tippyjs/react';// ⚠️ import from 'tippy.js/headless' if using Headless Tippyimport{followCursor}from'tippy.js';functionApp(){return(<Tippycontent="Tooltip"followCursor={true}plugins={[followCursor]}><button>Reference</button></Tippy>);}
You can nest the components like so:
<Tippycontent="Tooltip"placement="bottom"><Tippycontent="Tooltip"placement="left"><Tippycontent="Tooltip"placement="right"><Tippycontent="Tooltip"><button>Reference</button></Tippy></Tippy></Tippy></Tippy>
By default, Tippy mounts yourcontent
orrender
elements into a containerelement once created, even if the tippy isn't mounted on the DOM. In most cases,this is fine, but in performance-sensitive scenarios or cases where mounting thecomponent should fire effects only when the tippy mounted, you can lazify thecomponent.
View the following gists to optimize your<Tippy />
if needed.
A Hook for thecreateSingleton()
addon to re-use a single tippy element for many different reference elementtargets.
importTippy,{useSingleton}from'@tippyjs/react';functionApp(){const[source,target]=useSingleton();return(<>{/* This is the tippy that gets used as the singleton */}<Tippysingleton={source}delay={500}/>{/* These become "virtual" */}<Tippycontent="Hello"singleton={target}><button>Reference</button></Tippy><Tippycontent="Bye"singleton={target}><button>Reference</button></Tippy></>);}
useSingleton()
takes an optional props argument:
const[source,target]=useSingleton({disabled:true,overrides:['placement'],});
Therender
prop takes the singleton content as a second parameter:
importTippy,{useSingleton}from'@tippyjs/react/headless';functionApp(){const[source,target]=useSingleton();return(<><Tippysingleton={source}render={(attrs,content)=>(<divclassName="box"tabIndex="-1"{...attrs}>{content}</div>)}delay={500}/><Tippycontent="Hello"singleton={target}><button>Reference</button></Tippy><Tippycontent="Bye"singleton={target}><button>Reference</button></Tippy></>);}
MIT
About
React component for Tippy.js (official)
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.