Tippy.js

repository·master·Indexed 11 days ago

https://github.com/atomiks/tippyjs

A complete tooltip, popover, dropdown, and menu solution for the web, built on top of Popper.js for positioning. Version 6.3.7 includes support for custom themes, ARIA attributes, and a plugin system for features like followCursor and sticky.

Tokens
37.3K
Snippets
160
Records
192
Agent score
92%

What's inside Tippy.js

  1. What is Headless Tippy?

    master

    Headless Tippy refers to using Tippy.js without its default element rendering or CSS. This mode is used when you want to provide your own custom DOM elements and styles while leveraging Tippy's underlying logic (positioning, lifecycle, etc.).

    Note: When using Headless mode, props marked with the R symbol in the standard documentation no longer function automatically; you are responsible for implementing those features (like rendering and animations) yourself.

  2. Understand Gatsby project structure

    master

    A standard Gatsby starter includes several key configuration and source files:

    • src/: Contains front-end code like page templates and components. Edit src/pages/index.js to change your home page.
    • gatsby-config.js: The main configuration file for site metadata and plugins.
    • gatsby-node.js: Used for implementing Gatsby Node APIs to customize the build process.
    • gatsby-browser.js: Used for implementing Gatsby browser APIs to customize client-side behavior.
    • gatsby-ssr.js: Used for implementing Gatsby server-side rendering (SSR) APIs.
    • package.json: The Node.js manifest file containing project metadata and dependencies.
    • .prettierrc: Configuration for the Prettier code formatter.
  3. Compare Tippy.js with CSS tooltip libraries

    master

    While CSS-only tooltip libraries (like Microtip or Balloon.css) are smaller in size (~1 kB), they lack several advanced features provided by Tippy.js:

    • Positioning: CSS tooltips lack a positioning engine, meaning they cannot perform overflow prevention or automatic flipping.
    • Interactivity: Making CSS tooltips interactive or accessible is complex.
    • Dynamic Content: Using HTML content (especially with frameworks like React) is cumbersome, and reacting to state changes is limited.
    • Advanced Features: CSS tooltips do not support dynamic arrow positioning or features like followCursor.
  4. How `tippy()` returns instances based on input type

    master

    The tippy() function's return type depends on the argument provided:

    Argument TypeReturn TypeDescription
    ElementInstanceReturns a single instance for the specific target element.
    stringInstance[]Returns an array of instances for all elements matching the selector.
    NodeListInstance[]Returns an array of instances for all elements in the NodeList.
    Element[]Instance[]Returns an array of instances for the provided array of elements.
    // Single instance
    const instance = tippy(document.querySelector('button'));
    
    // Array of instances
    const instances1 = tippy('button');
    const instances2 = tippy([element1, element2]);
    const instances3 = tippy(document.querySelectorAll('.btn'));
  5. Difference between an addon and a plugin

    master

    Understanding the distinction between these two extension types:

    • Addon: An external function that calls the tippy() constructor. It controls or creates many different Tippy instances.
    • Plugin: A plain object that hooks into and adds functionality to a single Tippy instance that has already been created.
  6. How plugins work in tippy.js

    master

    A plugin is an object that allows you to add new properties (props) and lifecycle hooks to a tippy instance. Plugins are invoked per-instance, and the plugin function fn receives the instance as an argument, allowing you to use closures for internal state.

    Plugin Shape:

    • name (Optional): The name of the new prop this plugin provides.
    • defaultValue (Optional): The default value for the new prop.
    • fn (Required): A function that takes the instance and returns an object containing lifecycle hooks.
    const plugin = {
      // Optional
      name: 'propName', 
      defaultValue: 'anyValue',
    
      // Required
      fn(instance) {
        // Internal state
        return {
          // Lifecycle hooks
        };
      },
    };
  7. Understand the relationship between Tippy.js and Popper.js

    master

    Tippy.js is an abstraction built on top of Popper.js.

    • Popper.js is a positioning engine. Its sole purpose is to position an absolutely positioned element near a reference element while handling complex edge cases like viewport overflow, flipping to the opposite side of the reference, and staying attached during scrolling.
    • Tippy.js provides the "out of the box" behavior, appearance, and features (like animations and plugins) that Popper alone does not provide.

    You can use them together without additional cost as Tippy depends on Popper. If you are using the CDN, the Popper constructor is already available globally.

    import Popper from 'popper.js';
    import tippy from 'tippy.js';
  8. Handle touch device input differences

    master

    Touch devices handle taps differently: iOS often requires a second tap to fire a click event (allowing a tooltip to be seen first), while Android fires the click event immediately.

    To manage this, you can use tippy.currentInput.isTouch to detect if the user is currently using touch input. This is a dynamic property that changes based on the user's current input method (useful for hybrid devices).

    Strategies:

    • Make iOS behave like Android (Single tap to click): Trigger a manual .click() on the element inside the onShow lifecycle hook if the platform is detected as iOS.
    • Make Android behave like iOS (Double tap to click): Wrap your click listener in a function that requires two clicks (or detects non-touch input) before executing the logic.
    // Detecting iOS
    const isIOS = /iPhone|iPad|iPod/.test(navigator.platform);
    
    // Strategy A: Single tap to click on iOS
    tippy(button, {
      onShow() {
        if (isIOS) {
          button.click();
        }
      },
    });
    
    // Strategy B: Emulate iOS double-tap behavior on Android/Touch
    function emulateIOS(listener) {
      let clicks = 0;
      return function () {
        clicks++;
        if (clicks === 2 || isIOS || !tippy.currentInput.isTouch) {
          clicks = 0;
          listener.apply(this, arguments);
        }
      };
    }
  9. Compare Tippy.js with Tooltipster

    master

    Tooltipster is a similar library but has a significant dependency difference:

    • Tooltipster requires jQuery, which adds significant weight to your bundle (jQuery is ~30 kB minzipped, and Tooltipster is ~10 kB).
    • Tippy.js does not require jQuery, making it more suitable for modern frameworks like React, Vue, or Angular where large legacy dependencies are often undesirable.