CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-popperjs--core

Tooltip and popover positioning engine that automatically calculates optimal placement for UI elements with advanced positioning logic and overflow prevention

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

core-positioning.mddocs/

Core Positioning

Core createPopper function and instance management for tooltip and popover positioning with automatic updates and lifecycle management.

Capabilities

createPopper Function

Creates a popper instance to position a popper element relative to a reference element.

/**
 * Creates a popper instance to position a popper element relative to a reference element
 * @param reference - Reference element or virtual element to position relative to
 * @param popper - HTML element to be positioned (the tooltip/popover)
 * @param options - Configuration options for positioning behavior
 * @returns Instance object with methods to control the popper
 */
function createPopper(
  reference: Element | VirtualElement,
  popper: HTMLElement,
  options?: Partial<Options>
): Instance;

Usage Examples:

import { createPopper } from '@popperjs/core';

// Basic usage
const button = document.querySelector('#button');
const tooltip = document.querySelector('#tooltip');
const popperInstance = createPopper(button, tooltip);

// With options
const popperInstance = createPopper(button, tooltip, {
  placement: 'bottom-start',
  strategy: 'fixed',
  modifiers: [
    {
      name: 'preventOverflow',
      options: {
        boundary: 'clippingParents',
      },
    },
  ],
});

// With callback on first update
const popperInstance = createPopper(button, tooltip, {
  placement: 'top',
  onFirstUpdate: (state) => {
    console.log('Popper positioned at:', state.placement);
  },
});

Instance Management

The popper instance provides methods for controlling positioning and lifecycle.

interface Instance {
  /** Current state of the popper */
  state: State;
  /** Destroy the popper instance and cleanup event listeners */
  destroy(): void;
  /** Force immediate synchronous update of popper position */
  forceUpdate(): void;
  /** Asynchronously update popper position (debounced) */
  update(): Promise<Partial<State>>;
  /** Update popper options and recalculate position */
  setOptions(setOptionsAction: SetAction<Partial<Options>>): Promise<Partial<State>>;
}

type SetAction<S> = S | ((prev: S) => S);

Usage Examples:

// Update positioning manually
await popperInstance.update();

// Force immediate update (synchronous)
popperInstance.forceUpdate();

// Update options
await popperInstance.setOptions({
  placement: 'bottom',
});

// Update options with function
await popperInstance.setOptions((prevOptions) => ({
  ...prevOptions,
  modifiers: [...prevOptions.modifiers, { name: 'flip', enabled: true }],
}));

// Cleanup
popperInstance.destroy();

Options Configuration

Configuration object for customizing popper behavior.

interface Options {
  /** Initial placement of the popper relative to reference */
  placement: Placement;
  /** Array of modifiers to customize positioning behavior */
  modifiers: Array<Partial<Modifier<any, any>>>;
  /** CSS positioning strategy to use */
  strategy: PositioningStrategy;
  /** Callback executed after first update */
  onFirstUpdate?: (state: Partial<State>) => void;
}

type Placement = 
  | 'auto' | 'auto-start' | 'auto-end'
  | 'top' | 'top-start' | 'top-end'
  | 'bottom' | 'bottom-start' | 'bottom-end'
  | 'right' | 'right-start' | 'right-end'
  | 'left' | 'left-start' | 'left-end';

type PositioningStrategy = 'absolute' | 'fixed';

Usage Examples:

// Different placement options
const topPopper = createPopper(button, tooltip, { placement: 'top' });
const rightStartPopper = createPopper(button, tooltip, { placement: 'right-start' });
const autoPopper = createPopper(button, tooltip, { placement: 'auto' });

// Fixed positioning (useful in modals)
const fixedPopper = createPopper(button, tooltip, {
  strategy: 'fixed',
  placement: 'bottom',
});

// Custom modifiers
const customPopper = createPopper(button, tooltip, {
  modifiers: [
    {
      name: 'offset',
      options: { offset: [0, 10] },
    },
    {
      name: 'flip',
      enabled: false,
    },
  ],
});

State Object

Complete state information about the popper instance.

interface State {
  /** Reference to DOM elements */
  elements: {
    reference: Element | VirtualElement;
    popper: HTMLElement;
    arrow?: HTMLElement;
  };
  /** Current options configuration */
  options: Options;
  /** Current computed placement */
  placement: Placement;
  /** CSS positioning strategy being used */
  strategy: PositioningStrategy;
  /** Ordered list of active modifiers */
  orderedModifiers: Array<Modifier<any, any>>;
  /** Computed rectangles for positioning */
  rects: StateRects;
  /** Scroll parent elements for both reference and popper */
  scrollParents: {
    reference: Array<Element | Window | VisualViewport>;
    popper: Array<Element | Window | VisualViewport>;
  };
  /** Computed CSS styles to apply */
  styles: { [key: string]: Partial<CSSStyleDeclaration> };
  /** HTML attributes to apply */
  attributes: { [key: string]: { [key: string]: string | boolean } };
  /** Data from individual modifiers */
  modifiersData: { [key: string]: any };
  /** Whether positioning needs to be recalculated */
  reset: boolean;
}

interface StateRects {
  reference: Rect;
  popper: Rect;
}

interface Rect {
  width: number;
  height: number;
  x: number;
  y: number;
}

Usage Examples:

// Access current state
const { placement, rects } = popperInstance.state;
console.log('Current placement:', placement);
console.log('Popper dimensions:', rects.popper);

// Check modifier data
const offsetData = popperInstance.state.modifiersData.offset;
console.log('Applied offset:', offsetData);

// Get applied styles
const popperStyles = popperInstance.state.styles.popper;
console.log('Transform applied:', popperStyles.transform);

Error Handling

Common error scenarios and handling patterns.

// Check if elements are valid before creating popper
function createSafePopper(referenceSelector, popperSelector, options) {
  const reference = document.querySelector(referenceSelector);
  const popper = document.querySelector(popperSelector);
  
  if (!reference || !popper) {
    throw new Error('Reference or popper element not found');
  }
  
  // Popper will handle invalid elements gracefully
  return createPopper(reference, popper, options);
}

// Handle destroyed instances
let popperInstance = createPopper(button, tooltip);

// Later...
popperInstance.destroy();
popperInstance = null; // Clear reference

// Attempting to use destroyed instance will not throw but has no effect

Install with Tessl CLI

npx tessl i tessl/npm-popperjs--core

docs

built-in-modifiers.md

core-positioning.md

index.md

variants-tree-shaking.md

virtual-elements.md

tile.json