CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tippyjs--react

React component wrapper for Tippy.js providing complete tooltip, popover, dropdown, and menu solution for the web

Pending
Overview
Eval results
Files

singleton-mode.mddocs/

Singleton Mode

Singleton mode is a performance optimization technique that allows multiple tooltips to share a single instance, reducing memory usage and improving performance. This is particularly useful when you have many tooltips on a page that don't need to be shown simultaneously.

Capabilities

useSingleton Hook

Creates a singleton configuration that can be shared across multiple Tippy components.

/**
 * Hook for creating singleton tooltip configuration
 * @param props - Optional singleton configuration
 * @returns Tuple of [source, target] singleton objects
 */
function useSingleton(
  props?: UseSingletonProps
): [SingletonObject, SingletonObject];

interface UseSingletonProps {
  /** Disable singleton functionality */
  disabled?: boolean;
  /** Array of prop names that individual tooltips can override */
  overrides?: Array<keyof Props>;
}

interface SingletonObject {
  /** Internal singleton data */
  data?: any;
  /** Lifecycle hook function for singleton behavior */
  hook(args: SingletonHookArgs): void;
}

interface SingletonHookArgs {
  /** Tippy instance */
  instance: Instance;
  /** Tooltip content */
  content: React.ReactNode;
  /** Tippy props */
  props: Props;
}

Usage Examples:

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

// Basic singleton usage
function BasicSingleton() {
  const [source, target] = useSingleton();

  return (
    <>
      {/* Source tooltip - the actual tooltip instance */}
      <Tippy singleton={source} delay={500} />

      {/* Target tooltips - these become "virtual" */}
      <Tippy content="First tooltip" singleton={target}>
        <button>Button 1</button>
      </Tippy>
      
      <Tippy content="Second tooltip" singleton={target}>
        <button>Button 2</button>
      </Tippy>
      
      <Tippy content="Third tooltip" singleton={target}>
        <button>Button 3</button>
      </Tippy>
    </>
  );
}

Singleton Configuration

Configure singleton behavior with props and overrides.

interface UseSingletonProps {
  /** Disable singleton functionality */
  disabled?: boolean;
  /** Props that individual tooltips can override */
  overrides?: Array<keyof Props>;
}

Usage Examples:

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

// Singleton with configuration
function ConfiguredSingleton() {
  const [source, target] = useSingleton({
    disabled: false,
    overrides: ['placement', 'theme'], // Allow individual tooltips to override these
  });

  return (
    <>
      <Tippy 
        singleton={source} 
        delay={300} 
        theme="dark"
        placement="top" 
      />

      <Tippy content="Top tooltip" singleton={target}>
        <button>Default (top, dark)</button>
      </Tippy>
      
      <Tippy 
        content="Bottom tooltip" 
        singleton={target}
        placement="bottom" // Override allowed
      >
        <button>Bottom placement</button>
      </Tippy>
      
      <Tippy 
        content="Light tooltip" 
        singleton={target}
        theme="light" // Override allowed
      >
        <button>Light theme</button>
      </Tippy>
    </>
  );
}

Headless Singleton

Use singleton mode with headless rendering for custom tooltip appearance.

// Headless singleton render function receives content as second parameter
interface HeadlessRenderFunction {
  (
    attrs: RenderAttrs,
    content?: React.ReactNode,
    instance?: Instance
  ): React.ReactNode;
}

Usage Examples:

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

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

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

      <Tippy content="Hello" singleton={target}>
        <button>Button 1</button>
      </Tippy>
      
      <Tippy content="World" singleton={target}>
        <button>Button 2</button>
      </Tippy>
    </>
  );
}

Disabled Singleton

Temporarily disable singleton behavior while keeping components mounted.

Usage Examples:

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

function DisableableSingleton() {
  const [singletonDisabled, setSingletonDisabled] = useState(false);
  const [source, target] = useSingleton({
    disabled: singletonDisabled,
  });

  return (
    <div>
      <button onClick={() => setSingletonDisabled(!singletonDisabled)}>
        {singletonDisabled ? 'Enable' : 'Disable'} Singleton
      </button>
      
      <Tippy singleton={source} delay={300} />

      <Tippy content="Tooltip 1" singleton={target}>
        <button>Button 1</button>
      </Tippy>
      
      <Tippy content="Tooltip 2" singleton={target}>
        <button>Button 2</button>
      </Tippy>
    </div>
  );
}

Complex Singleton Example

Advanced singleton usage with dynamic content and state management.

Usage Examples:

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

interface User {
  id: number;
  name: string;
  email: string;
  role: string;
}

function UserList() {
  const [source, target] = useSingleton({
    overrides: ['content'], // Allow each tooltip to have different content
  });
  
  const users: User[] = [
    { id: 1, name: 'Alice', email: 'alice@example.com', role: 'Admin' },
    { id: 2, name: 'Bob', email: 'bob@example.com', role: 'User' },
    { id: 3, name: 'Charlie', email: 'charlie@example.com', role: 'Moderator' },
  ];

  const renderUserTooltip = (user: User) => (
    <div>
      <strong>{user.name}</strong>
      <br />
      {user.email}
      <br />
      Role: {user.role}
    </div>
  );

  return (
    <>
      <Tippy 
        singleton={source} 
        placement="top"
        delay={[800, 200]}
        interactive={true}
      />

      <div className="user-list">
        {users.map(user => (
          <Tippy 
            key={user.id}
            content={renderUserTooltip(user)} 
            singleton={target}
          >
            <div className="user-card">
              {user.name}
            </div>
          </Tippy>
        ))}
      </div>
    </>
  );
}

Performance Benefits

Singleton mode provides several performance advantages:

  1. Memory Efficiency: Only one tooltip DOM element exists instead of multiple
  2. Reduced Overhead: Shared event listeners and positioning calculations
  3. Smooth Transitions: Tooltips can smoothly transition between different targets
  4. Better UX: Prevents multiple tooltips from appearing simultaneously

Key Considerations

  • The source tooltip defines the shared configuration (styling, positioning, delays, etc.)
  • Target tooltips can only override props specified in the overrides array
  • Only one tooltip can be visible at a time in singleton mode
  • The content prop on individual target tooltips is automatically included in overrides
  • Singleton mode works with both default and headless rendering
  • Use singleton when you have many tooltips that don't need to be shown simultaneously

Install with Tessl CLI

npx tessl i tessl/npm-tippyjs--react

docs

default-rendering.md

headless-rendering.md

index.md

singleton-mode.md

tile.json