Code Monkey home page Code Monkey logo

tippyjs-react's Introduction

Logo

Tippy.js for React

⚠️⚠️⚠️

If you're new here, we recommend using Floating 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 all types of elements that pop out on top of the UI, positioned next to a target or reference element. This is a React wrapper for the core library, providing full integration including headless rendering abilities.

🚀 Installation

# npm
npm i @tippyjs/react

# Yarn
yarn add @tippyjs/react

CDN: https://unpkg.com/@tippyjs/react

🖲 Usage

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 want something that just works, this is for you.
  • Headless: With React's DOM rendering for improved usage with CSS-in-JS and spring libraries. If you want greater control over your poppers to integrate fully with design systems, this is for you.

Both may be used in conjunction.

Default Tippy

Import the Tippy component and (optionally) the core CSS. Wrap the <Tippy /> component around the element, supplying the tooltip's content as the content prop. It can take a string or a tree of React elements.

import React from 'react';
import Tippy from '@tippyjs/react';
import 'tippy.js/dist/tippy.css'; // optional

const StringContent = () => (
  <Tippy content="Hello">
    <button>My button</button>
  </Tippy>
);

const JSXContent = () => (
  <Tippy content={<span>Tooltip</span>}>
    <button>My button</button>
  </Tippy>
);

Default Tippy "just works" out of the box.

Headless Tippy

Render your own tippy element from scratch:

import React from 'react';
import Tippy from '@tippyjs/react/headless'; // different import path!

const HeadlessTippy = () => (
  <Tippy
    render={attrs => (
      <div className="box" tabIndex="-1" {...attrs}>
        My tippy box
      </div>
    )}
  >
    <button>My button</button>
  </Tippy>
);

attrs is an object containing data-placement, data-reference-hidden, and data-escaped attributes. This allows you to conditionally style your tippy.

Headless animation

Headless arrow

To make Popper position your custom arrow, set a data-popper-arrow attribute on it:

<Tippy
  render={attrs => (
    <Box {...attrs}>
      Hello
      <Arrow data-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 an HTMLElement (not an SVGElement). To use an SVG arrow, wrap it in a <div> tag with the data-popper-arrow attribute.

You may also pass a ref to the element directly without the attribute using a callback ref:

function App() {
  const [arrow, setArrow] = useState(null);

  return (
    <Tippy
      render={attrs => (
        <Box {...attrs}>
          Content
          <Arrow ref={setArrow} />
        </Box>
      )}
      popperOptions={{
        modifiers: [
          {
            name: 'arrow',
            options: {
              element: arrow, // can be a CSS selector too
            },
          },
        ],
      }}
    >
      <button>Reference</button>
    </Tippy>
  );
}

Headless root element

When rendering an element with the render prop, you're rendering the inner element that the root popper (positioned) node wraps.

For advanced cases you can access the root element via instance.popper.

Here's moveTransition with Framer Motion.

Component children

If you want to use a component element as a child of the component, ensure you forward the ref to the DOM node:

import React, {forwardRef} from 'react';

function ThisWontWork() {
  return <button>Reference</button>;
}

const ThisWillWork = forwardRef((props, ref) => {
  return <button ref={ref}>Reference</button>;
});

function App() {
  return (
    <Tippy content="Tooltip">
      <ThisWillWork />
    </Tippy>
  );
}

styled-components v4+ does this for you automatically, so it should be seamless when using the styled constructor.

Workaround for old libraries that don't forward the ref is to use a <span> wrapper tag:

<Tippy content="Tooltip">
  <span tabIndex="0">
    <LegacyComponent>Reference</LegacyComponent>
  </span>
</Tippy>

🧬 Props

All of the native Tippy.js props can be passed to the component.

Visit All Props to view the complete list.

<Tippy content="Tooltip" interactive={true} interactiveBorder={20} delay={100}>
  <button>Reference</button>
</Tippy>

In addition, there are 3 more props added specifically for the React component.

className?: string

<Tippy content="Tooltip" className="hello world">
  <button>Reference</button>
</Tippy>

This allows you to use styled(Tippy) or the css prop in styled-components or emotion.

Note: Does not apply if using Headless Tippy.

disabled?: boolean

function App() {
  const [disabled, setDisabled] = useState(false);

  return (
    <Tippy content="Tooltip" disabled={disabled}>
      <button>Reference</button>
    </Tippy>
  );
}

visible?: boolean (controlled mode)

Use React's state to fully control the tippy instead of relying on the native trigger and hideOnClick props:

function App() {
  const [visible, setVisible] = useState(true);
  const show = () => setVisible(true);
  const hide = () => setVisible(false);

  return (
    <Tippy content="Tooltip" visible={visible} onClickOutside={hide}>
      <button onClick={visible ? hide : show}>Reference</button>
    </Tippy>
  );
}

reference?: React.RefObject | Element

Available from v4.1.0

If you can't place your reference element as a child inside <Tippy />, you can use this prop instead. It accepts a React RefObject (.current property) or a plain Element.

function App() {
  const ref = useRef();

  return (
    <>
      <button ref={ref} />
      <Tippy content="Tooltip" reference={ref} />
    </>
  );
}

Plugins

Tippy.js splits certain props into separate pieces of code called plugins to enable tree-shaking, so that components or routes that don't need the prop's functionality are not burdened with the bundle size cost of it. In addition, they enable a neat way to extend the functionality of tippy instances.

import Tippy from '@tippyjs/react';
// ⚠️ import from 'tippy.js/headless' if using Headless Tippy
import {followCursor} from 'tippy.js';

function App() {
  return (
    <Tippy content="Tooltip" followCursor={true} plugins={[followCursor]}>
      <button>Reference</button>
    </Tippy>
  );
}

Read more about plugins here.

🌈 Multiple tippies on a single element

You can nest the components like so:

<Tippy content="Tooltip" placement="bottom">
  <Tippy content="Tooltip" placement="left">
    <Tippy content="Tooltip" placement="right">
      <Tippy content="Tooltip">
        <button>Reference</button>
      </Tippy>
    </Tippy>
  </Tippy>
</Tippy>

Lazy mounting

By default, Tippy mounts your content or render elements into a container element 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 the component should fire effects only when the tippy mounted, you can lazify the component.

View the following gists to optimize your <Tippy /> if needed.

📚 useSingleton

A Hook for the createSingleton() addon to re-use a single tippy element for many different reference element targets.

View on CodeSandbox

import Tippy, {useSingleton} from '@tippyjs/react';

function App() {
  const [source, target] = useSingleton();

  return (
    <>
      {/* This is the tippy that gets used as the singleton */}
      <Tippy singleton={source} delay={500} />

      {/* These become "virtual" */}
      <Tippy content="Hello" singleton={target}>
        <button>Reference</button>
      </Tippy>
      <Tippy content="Bye" singleton={target}>
        <button>Reference</button>
      </Tippy>
    </>
  );
}

useSingleton() takes an optional props argument:

const [source, target] = useSingleton({
  disabled: true,
  overrides: ['placement'],
});

Headless singleton

The render prop takes the singleton content as a second parameter:

import Tippy, {useSingleton} from '@tippyjs/react/headless';

function App() {
  const [source, target] = useSingleton();

  return (
    <>
      <Tippy
        singleton={source}
        render={(attrs, content) => (
          <div className="box" tabIndex="-1" {...attrs}>
            {content}
          </div>
        )}
        delay={500}
      />

      <Tippy content="Hello" singleton={target}>
        <button>Reference</button>
      </Tippy>
      <Tippy content="Bye" singleton={target}>
        <button>Reference</button>
      </Tippy>
    </>
  );
}

📝 License

MIT

tippyjs-react's People

Contributors

atomiks avatar benkeen avatar cpatchane avatar dependabot-preview[bot] avatar ejdzipi avatar fezvrasta avatar iamharky avatar inxilpro avatar karl avatar katevuilova avatar kubajastrz avatar lgraziani2712 avatar mskelton avatar nguyen-darianhuy avatar viljark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tippyjs-react's Issues

How to hideAllPoppers in react?

With native tippy it's like this:
window.addEventListener('scroll', () => tippy.hideAllPoppers())

But how to do it in react?

`import Tippy from '@tippy.js/react'
import 'tippy.js/dist/tippy.css'

Tippy.defaultProps = {
  performance: true,
  animateFill: false,
  delay: [300, 0],
  animation: 'scale',
  theme: 'MyTheme',
  duration: [300, 300],
  distance: 5,
  maxWidth: '330px',
  sticky: true,
  touchHold: true
}

export default Tippy
`

if i add somewhere in code:
window.addEventListener('scroll', () => Tippy.hideAllPoppers())

i get error
Uncaught TypeError: shared_useTippy__WEBPACK_IMPORTED_MODULE_5__.default.hideAllPoppers is not a function
    at eval (Home.js:18)

Uncaught TypeError: Object(...) is not a function

After install and import I get this error in browser console:

image

184 line is:

/* 184 */ var Tippy$1 = Object(react__WEBPACK_IMPORTED_MODULE_0__["forwardRef"])(function TippyWrapper(props, _ref) {
  return react__WEBPACK_IMPORTED_MODULE_0__["default"].createElement(Tippy, props, Object(react__WEBPACK_IMPORTED_MODULE_0__["cloneElement"])(props.children, {
    ref: function ref(node) {
      preserveRef(_ref, node);
      preserveRef(props.children.ref, node);
    }
  }));
});

What am I doing wrong? 😢

React: 16.8.4
@tippy.js/react: 2.1.1

Transform on Interactive Tool Tip

The Tippy I have in React is as follows:

<Tippy content={document.getElementById('cocatalyst-hover')} placement="top"
arrow= {true} theme= {'light'} duration= {50} interactive= {true} animation= 'scale' >

The unexpected behavior is that the tooltip is about 400px below the button. I inspected the CSS for the tippy, and you can see the translate3d is 540px rather than ~100px that would align where it should be.

z-index: 9999; visibility: visible; transition-duration: 0ms; position: absolute; will-change: transform;
top: 0px; left: 0px; transform: translate3d(471px, 540px, 0px);

What's even weirder is that this is only for below the button. When the tooltip has enough space to go above the button, it renders as expected. What are the factors for calculating the translate3d, and is there an override that I missed in the tippy params?

className is not a valid option/prop

I'm trying to pass in className as a prop and it's not possible at the moment.

This would enable you to style the Tooltip container( .tippy-popper ) using styled-components or any other CSS-in-JS option.

screen shot 2018-11-06 at 8 10 09 am

Tippy within <label> with htmlFor prop doesn't show tooltip

When embedding my Tippy within a label that has an htmlFor attribute, the tippy doesn't show up. Looking at the DOM, I think it's adding then removing the tippy with a single click.

<label htmlFor="targetElement">
    Text here.
     <Tippy ... />
</label>

How to use with css modules

I'm using css-modules in my project. I think this might be the reason why my tooltip does not contain any styling. I've imported the css in my App.js and implemented the tooltip as following:

<Tippy content="Hello">
    <button>My button</button> 
</Tippy>

Do I have to follow some extra steps to get the tooltip working while using css-modules or am I doing something else wrong?

passing `popperOptions: undefined` crashes page

NB: This seems to be an issue within tippy itself but I thought I'd make an issue here in case a check/default on the component side is enough.

I created a wrapper around Tippy to provide custom defaults but found that the page became unresponsive when hovering over the target element; page using 100% cpu according to devtools. This started recently, so possibly a tippy v4 regression.

Since the wrapper passes undefined to Tippy when it is not explicitly set by the component, it is necessary to use {} as the default param.

Working:

<Tippy content="hello">
  <span>works</span>
</Tippy>

Breaking:

<Tippy content="hello" popperOptions={undefined}>
  <span>breaks</span>
</Tippy>

Typescript support

Thank you for this amazing react wrapper ❤️
Are you planning on adding typescript support to this package? I've seen the discussion on the main tippy repo (atomiks/tippyjs#186).
If you need any help, I'd love to assist 🙂

option to use render props to pass ref to custom components

Some third party components (in my case, the Field component from Formik) use a custom name for their ref prop (eg. innerRef). Having an option to use the render prop pattern to pass the ref down could ease some of these use cases; the alternative being rolling your own wrapper component that uses forwardRef.

Feature request: support for className prop

I realize this was brought up in other tickets and you can get around it by passing a theme prop, but within the React ecosystem passing a className prop is pretty much a standard - everyone expects it when consuming components. Using theme lets you get add your class string to the DOM, but because it dynamically appends a -theme suffix to the name, it's unexpected.

Just FYI, my particular use-case is that we're integrating this component into an existing system with test automation. Our automation team uses a convention to target DOM nodes via classes, so because it appends the -theme we're having to do a little extra legwork to get around the problem.

Thanks!

[Edit: if the maintainer of this lib approves the idea, I'm happy to put in a PR]

Changing dimensions of HTML tooltip

How do I change the dimensions of the HTML tool tip? It's standard at 350px, and I want to make it wider.

I tried the following, but not sure what the actual tag is supposed to be.

<Tippy content={document.getElementById('hover')} placement="top" arrow= {true} theme= {'light'} width= {'400px'} duration= {50} interactive= {true} animation= 'scale' offset={5}> {core_tags}

TypeError: Cannot set property attributes of [object Object] which has only a getter

I am in the process of writing tests using Enzyme for a React component that I created based on the Tippy component I imported from @tippy.js/react. When I called Enzyme's mount function using the Tooltip component I created with a nested DOM element, I receive the following error: TypeError: Cannot set property attributes of [object Object] which has only a getter.

Here is the code that causes the error: beforeEach(() => { wrapper = mount(

Test
); })
However, when I replace
Test
with simple text, it works.

Any idea of how to resolve this issue? Thanks in advance for your help.

Here is the stack trace:
at polyfillElementPrototypeProperties (node_modules/tippy.js/dist/tippy.all.js:3379:27)
at tippy (node_modules/tippy.js/dist/tippy.all.js:4465:5)
at Function.Object..tippy.one (node_modules/tippy.js/dist/tippy.all.js:4504:10)
at Tippy.componentDidMount (node_modules/@tippy.js/react/dist/Tippy.js:141:26)
at commitLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:14684:22)
at commitAllLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:15904:7)
at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:145:14)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:126:9)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:36:27)
at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35)
at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:195:16)
at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:248:31)
at commitRoot (node_modules/react-dom/cjs/react-dom.development.js:16074:7)
at completeRoot (node_modules/react-dom/cjs/react-dom.development.js:17462:3)
at performWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:17390:9)
at performWork (node_modules/react-dom/cjs/react-dom.development.js:17294:7)
at performSyncWork (node_modules/react-dom/cjs/react-dom.development.js:17266:3)
at requestWork (node_modules/react-dom/cjs/react-dom.development.js:17154:5)
at scheduleWork (node_modules/react-dom/cjs/react-dom.development.js:16948:5)
at scheduleRootUpdate (node_modules/react-dom/cjs/react-dom.development.js:17636:3)
at updateContainerAtExpirationTime (node_modules/react-dom/cjs/react-dom.development.js:17663:10)
at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:17690:10)
at ReactRoot.Object..ReactRoot.render (node_modules/react-dom/cjs/react-dom.development.js:17956:3)
at node_modules/react-dom/cjs/react-dom.development.js:18096:14
at unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:17517:10)
at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:18092:5)
at Object.render (node_modules/react-dom/cjs/react-dom.development.js:18151:12)
at Object.render (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:314:114)
at new ReactWrapper (node_modules/enzyme/build/ReactWrapper.js:119:16)
at mount (node_modules/enzyme/build/mount.js:21:10)
at Object.test (src/components/Card/tests/Card.test.js:9:44)
at new Promise ()
at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
at
at process._tickCallback (internal/process/next_tick.js:188:7)

Styling the arrow using styled components

Hello! I'm trying to change the color of the arrow. However, I need to check the x-placement property of element with class .tippy-popper (as it is written in doc https://atomiks.github.io/tippyjs/themes/#styling-the-arrow )

I want to change the color using styled components without adding global styles. But the className that I pass to <TippyTooltip> component is only applied to .tippy-tooltip div which is a child of
.tippy-popper. There's no way I can check the x-placement property of .tippy-popper. Maybe there should be another className prop that will add my additional class to .tippy-popper ? Or maybe there's another way I can solve this problem

onFocus popup doesn't pops

Can you show how to use trigger=focus, as it is not working in my case.
I want to handle tippy popup on onClick and also when arrow keys of keyboard focus on a particular cell.

Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

After update to latest tippy i've started to get this error. Reproduction case:
Work's fine:

          <Tooltip content={'ам'}>
              <div>1</div>
          </Tooltip>

Got error:

          <Tooltip content={'ам'} >
                <Icon />
          </Tooltip>

or

          <Tooltip content={'ам'} >
            1
          </Tooltip>

Icon code:

export const Icon = props => (
  <svg {...props}>
     // svg image code
  </svg>
)

Tooltip code:

import Tippy from '@tippy.js/react'
import React, { useEffect, useState } from 'react'

export function Tooltip({ children, sharedContent, content, pure, ...rest }) {
  const [tip, tipSet] = useState(false)

  useEffect(() => {
    if (sharedContent) {
      switch (sharedContent) {
        case 'something':
          content = (
            <div>
               shared tips
            </div>
          )
      }
    }
    tipSet(content)
  }, [content])

  if (!tip) return false

  return (
    <Tippy content={tip} {...rest}>
      {pure
        ? React.cloneElement(children)
        : React.cloneElement(children, { className: 'tippy-target' })}  // change cursor to one with question mark
    </Tippy>
  )
}

Tooltip.defaultProps = {
  ignoreAttributes: true,
  animateFill: false,
  delay: [300, 0],
  interactive: true,
  animation: 'scale',
  theme: 'knigAm',
  duration: [300, 300],
  distance: 5,
  maxWidth: '330px',
  sticky: true,
  touchHold: true,
  a11y: false
}

Any thoughts to try?

Error in snapshot testing

Upgrading to Tippy 2 produces an error while snapshot testing with jest:

TypeError: d.current.set is not a function at props (node_modules/@tippy.js/react/src/Tippy.js:61:38)

Any advise?

Doesn't accept target property

I am not able to add a target property to Tippy.

TypeScript has children property set to required but the native library also supports a target element.

Am I missing something here?

import React, { Component } from "react";
import Tippy from "@tippy.js/react";
import "tippy.js/dist/tippy.css";
import "./App.css";

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          
          <div className="target">Testing</div>
          <Tippy target=".target" content="Yaay works" />
        
        </header>
      </div>
    );
  }
}

export default App;

scheduleUpdate() of Popper is continuously called when wrapper of target is scrolled

I found that the performance was falling when I scrolled the page included Tippy component.
And the reason was that scheduleUpdate() of Popper was continuously called in the part of update.
It should be called disableEventListeners() of Popper.

componentDidUpdate() {
/*
    this.tip.set({
        ...getNativeTippyProps(this.props),
        content: this.getContent()
    });
*/
}

Passing handlers to the `<Tippy />`

I have a simple Icon wrapped by a <Tippy /> component. When the tippy is focused, I want an onKeyDown handler catching the "Enter" key to trigger the same onClick handler. This is for accessibility and usability purposes, for keyboard users.

The below code is what I have:

<Tippy content="Close Options" arrow={true} duration={500} delay={[100, 50]}>
      <i className="fal fa-times" onClick={this.toggleTableControls} />
</Tippy>

I want to have this:

<Tippy content="Close Options" arrow={true} duration={500} delay={[100, 50]} onKeyDown={this.toggleTableControls}>
      <i className="fal fa-times" onClick={this.toggleTableControls} />
</Tippy>

I don't want to attach a onKeyDown handler to the icon tag. That would require me to attach a tabIndex, which involves the user to tab twice, once for the <Tippy /> and another tab to reach the nested <i /> to trigger the key event. It's unintuitive to have to tab twice for what the user sees as one element on the page.

How to handle false component?

I have a component like this:

<Tooltip content={'some tooltip'}>
        <Button>text</Button>
</Tooltip>

But button component first return as false and after some time (applying styles) it will return Button.

In first part you will get an error because you will render false without ref, example:

<Tooltip content={'some tooltip'}>
        false
</Tooltip>

You can return button with defaultTheme instead false and this will work, but there will be visible transition from defaultColorTheme to calculatetOne

let ButtonComponent = forwardRef(
  ({theme, ...other},  ref ) => {
    const [theme, themeSet] = useState(false)

    useEffect(() => {
      // do some calculations
      themeSet('newTheme')
    }, [])

    if (!theme) return  (<StyledButton
        theme={defaultTheme}
        {...other}
        ref={ref}
      >
        {children}
      </StyledButton>)

    return (
      <StyledButton
        theme={theme}
        {...other}
        ref={ref}
      >
        {children}
      </StyledButton>
    )
  }
)

If you will return some invisible block, there will be no error, but tooltip will not be on button after it render.

let ButtonComponent = forwardRef(
  ({theme, ...other},  ref ) => {
    const [theme, themeSet] = useState(false)

    useEffect(() => {
      // do some calculations
      themeSet('newTheme')
    }, [])

    if (!theme) return <div ref ={ref }><div>

    return (
      <StyledButton
        theme={theme}
        {...other}
        ref={ref}
      >
        {children}
      </StyledButton>
    )
  }
)

What can be solution for this?

Cannot change the animation

Hello, I am having problems with Tippy.

First of all, I am using it in nextjs and I don't know if this is the cause of my problems. I am adding Tippy to a span and it is working, the problem is that I cannot change the animation no matter which animation I set

<Tippy
    content={<span>Circle</span>}
    animation={'shift-away'}>
    <span className="circle"></span>
</Tippy>

By the way, the animation that I always see is apparently fade.

Other thing I am noticing is that the animation only works when showing up but when on mouse out the Tippy just disappears without animation.

I tried adding arrows but then there is not animation at all (mouse in/mouse out).

Nesting tooltips

I have a use case where there is a table, the columns have an interactive tooltip that currently triggers on click; however there are columns which need to display data on hover as well such as the users name.

Is there a right way of doing this as when I seem to add a nested tooltip even though the child is only supposed to show on hover and the parent on click it only ever appears to show the child on hover.

        <Tippy
          arrow={true}
          interactive={true}
          trigger='click'
          content={this.tippyContent}
          theme='light quick-option'
          offset='0,-10'
          size='large'
          onShow={this.props.onShowQuickOptions}
          onHide={this.props.onHideQuickOptions}
          onCreate={this.props.assignTippy}
        >
          <div className='ticket-table-cell-tippy-content-wrapper'>
            <CellLoadingOverlay in={this.props.loading}><Dots /></CellLoadingOverlay>
            <div className='ticket-table-assignee-wrapper'>
              <Tippy content='onlythishoverworks'><span className={`user-${this.props.userId}`} title={this.props.userName} /></Tippy>
            </div>
          </div>
        </Tippy>

Not sure what else I can add so hopefully this explains it. Any pointers much appreciated.

How to style target component?

Is there a way to add some class or style to target element?

In my case i want to make every element with cursor: help.

Issue with className prop passing with Styled Components

Thanks for a great project! Is there any insight into this warning I receive from styled-components when using it with Tippy React?

It looks like you've wrapped styled() around your React component (Popover), but the className prop is not being passed down to a child. No styles will be rendered unless className is composed within your React component.

Here is a codesandbox with the warning. Oddly enough, the example works as expected. I am wrapping the <Tippy /> component in a styled-component and that in turn styles the .tippy-tooltip element.

The warning is due to the fact I am passing in a custom component for content but my custom component is not receiving the props from styled-components (but I don't need it to).

For now I'm just passing suppressClassNameWarning into StyledPopover (in my example).

Any thoughts would be great! Thanks again!

setContent is not working

Hi,

I want to use dynamic content for a tippy. Unfortunately I'm not able to change the content.

This is my component:

import React, { Component } from 'react'
import Tooltip from '@tippy.js/react'

export class ContextMenu extends Component {
	onCreate = tippy => {
		this.tippy = tippy
	}

	closeTippy = () => {
		this.tippy.hide()
	}

	renderInitialContent = () => (
        <button onClick={this.showConfirmation}>
            Delete
        </button>
	)

	renderConfirmationContent = () => (
        <button onClick={() => { this.closeTippy(); this.props.onRemove() }}>
            DELETE!
        </button>
	)

	showInitialContent = () => {
		this.tippy.setContent(this.renderInitialContent())
	}

	showConfirmation = () => {
		this.tippy.setContent(this.renderConfirmationContent())
	}

	render() {
		return (
			<Tooltip
				onCreate={this.onCreate}
				trigger="click"
				interactive
				content={this.renderInitialContent()}
			>
				<button>
					Show modal
				</button>
			</Tooltip>
		)
	}
}

export default ContextMenu

I have no errors in the console, but clicking on the "Delete"-Button doesn't switch the content to show the confirmation button "DELETE!".

What is my failure here?

Thanks in advance and kind regards
Sebastian

Importing Tippy 1.0.0-beta.1

After adding import Tippy from '@tippy.js/react' to my code, in the browser the Tippy.js source code looks like this:

    // NOTE: DOM access here
    // restores the original style properties after the offsets have been com"use strict";
puted
    popperStyles.top = top;
    popperStyles.left = left;
    popperStyles[transformProp] = transform;

Looks like the comment is interrupting the code flow. "puted" is added to a new line. Can you look into this?

What is the best way to fully customize the theme?

Currently I make it to transparent and use content's styles

.tippy-tooltip.tomato-theme {
  background-color: transparent;
  color: transparent;
}

.tippy-tooltip.tomato-theme[data-animatefill] {
  background-color: transparent;
}

.tippy-tooltip.tomato-theme .tippy-backdrop {
  background-color: transparent;
}

.tippy-popper[x-placement^='top'] .tippy-tooltip.tomato-theme .tippy-arrow {
  border-top-color: transparent;
}
.tippy-popper[x-placement^='bottom'] .tippy-tooltip.tomato-theme .tippy-arrow {
  border-bottom-color: transparent;
}
.tippy-popper[x-placement^='left'] .tippy-tooltip.tomato-theme .tippy-arrow {
  border-left-color: transparent;
}
.tippy-popper[x-placement^='right'] .tippy-tooltip.tomato-theme .tippy-arrow {
  border-right-color: transparent;
}

.tippy-tooltip.tomato-theme .tippy-roundarrow {
  fill: transparent;
}

Flash of tooltip content on DOM when using SSR + JSX content

The tooltip content exists on the DOM when using SSR + JSX content because it exists in the render tree. It's not seen when using regular JS rendering because Tippy appends the node to the tooltip before the first animation frame.

Anyone have any ideas to prevent this? It can be hackishly done by using an inline style display: none on the content and then removing it onShow.

Can using portals prevent this?

Activating a trigger="manual" tooltip

I am trying to activate a Tooltip in one static location on a page based on clicks elsewhere. Maybe I am just getting turned around. Could you provide/is there a minimal working example of how to do this?

Here's what I am working with to test it out. I'm just not sure where to go next based on previous issues and documentation.

class Tooltest extends React.Component{
      constructor(props){
    super(props);
    this.myRef = React.createRef();
  }
  render(){
    return(
      <Tooltip
        ref={this.myRef}
        html={(
            <div dangerouslySetInnerHTML={{ __html: "There were once dinsoaurs"}}></div>
        )}
        trigger="manual"
       >
         <p>"TESTING"</p>
      </Tooltip>
    )
  }
}

Then I need to somehow callthis.myRef.current.tippy.show() from another component like so:

Within App render method:

someFunction(){
    //This will fire the tooltip based on a click in ClickMe
}
render(
  <div>
    <Tooltest />
    <ClickMe/>
  </div>
)

Hiding all tooltips except the last one

Is it possible to hide all other tooltips when one is showing or maybe call the static method hideAllPoppers for the tooltip show event?
When there are multiple tooltips on a page and the animation duration is long, it leaves a trail of tooltips, I want to be able to "destroy" the events of the other tooltips and only show the last target that was supposed to show (Like the solo option in qtip2).

using JSX as content breaks jest snapshots tests

While this works …
<Tippy content="Test">Component</Tippy>

… passing JSX breaks all my jest snapshot tests
<Tippy content={<span>Test</span>}>Component</Tippy>

   Warning: An invalid container has been provided. This may indicate that another renderer is being used in addition to the test renderer. (For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) This is not supported.
        in span (created by Tooltip)
        in Tippy (created by Tooltip)

Multiple tippys on a single reference

Doesn't seem possible at the moment.

This doesn't work:

<Tippy content="..." placement="bottom" multiple>
  <Tippy content="..." multiple>
    <button />
  </Tippy>
</Tippy>

Anyone have ideas what the API should look like?

How to prevent wrapping?

Hi,

I would like to display a rather long string, and I would like to show it in one line (in a very wide popup), but the contents gets wrapped... I have not found any settings with which I could keep it from wrapping.

Any ideas? Thank you very much in advance!

Can I trigger a tip by code?

I'd like to use the tip as a validation message, can I trigger it in a function that runs validation on a form?

Throw `useLayoutEffect` warning in version 2.1.0

As title, this warning throw when server-side rendering

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client.

Failed prop type: Invalid prop `content` supplied to `Tippy`.

For some reason i've get a "Warning: Failed prop type: Invalid prop content supplied to Tippy." with this code

export default function Home() {
  const [somevar, setSomevar] = useState(1) //new react api
  return (
      <Tippy content={somevar}>
        <button>My button</button>
      </Tippy>
  )
}

Is there some problem with new api?

Tippy not playing well with styled component and redux

I have styled component wrapped with tippy in a component. the component is connected to the redux store to dispatch/receive props.

everything works fine until store state change and causing rerender. after that, the popover won't show.

I have created codesandbox to demonstrate the problem:

https://codesandbox.io/s/5w394qqzlk

Please look in 'Component.jsx' and follow instructions.

Thanks,

Guid

Hi there! thanks for this react wrapper. I often get this and wonder if anyone else got this too?

VM3168:306 Uncaught TypeError: Cannot read property 'guid' of undefined
    at v (<anonymous>:306:1429)
    at removeEventListeners (popper.js:1070)
    at Popper.disableEventListeners (popper.js:1095)
    at Popper.disableEventListeners$$1 (popper.js:2515)
    at tippy.standalone.js:1718
    at tippy.standalone.js:1421
    at HTMLDivElement.listener (tippy.standalone.js:1448)

and

VM3449:306 Uncaught TypeError: Cannot read property 'guid' of undefined
    at v (<anonymous>:306:1429)
    at removeEventListeners (popper.js:1070)
    at Popper.disableEventListeners (popper.js:1095)
    at Popper.disableEventListeners$$1 (popper.js:2515)
    at tippy.standalone.js:1718
    at tippy.standalone.js:1421
    at onTransitionEnd (tippy.standalone.js:1439)
    at onTransitionedOut (tippy.standalone.js:1419)
    at hide (tippy.standalone.js:1711)
    at destroy (tippy.standalone.js:1738)
    at show (tippy.standalone.js:1607)
    at tippy.standalone.js:1129

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.