CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rc-trigger

Base abstract trigger component for React that manages popup behavior and positioning with hover, click, focus actions and precise alignment.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

positioning.mddocs/

Positioning and Alignment

Advanced popup positioning system with precise alignment configuration, overflow handling, and built-in placement presets. The positioning system integrates with rc-align to provide flexible and intelligent popup placement.

Capabilities

Alignment Configuration

Core alignment interface for controlling popup positioning relative to the trigger element.

/**
 * Alignment configuration for popup positioning
 */
interface AlignType {
  /** 
   * Alignment points between source and target nodes
   * Format: ['sourcePoint', 'targetPoint'] where points are combinations of:
   * - 't' (top), 'b' (bottom), 'c' (center) for vertical
   * - 'l' (left), 'r' (right), 'c' (center) for horizontal
   * Example: ['tr', 'bl'] aligns top-right of popup with bottom-left of trigger
   */
  points?: AlignPoint[];
  
  /** 
   * Offset popup by [x, y] pixels from aligned position
   * Supports percentage strings relative to popup size
   */
  offset?: number[];
  
  /** 
   * Offset target by [x, y] pixels before alignment
   * Supports percentage strings relative to target size
   */
  targetOffset?: number[];
  
  /** Overflow adjustment configuration */
  overflow?: {
    /** Auto-adjust horizontally if popup overflows viewport */
    adjustX?: boolean | number;
    /** Auto-adjust vertically if popup overflows viewport */
    adjustY?: boolean | number;
  };
  
  /** Use CSS right property instead of left for positioning */
  useCssRight?: boolean;
  
  /** Use CSS bottom property instead of top for positioning */
  useCssBottom?: boolean;
  
  /** Use CSS transform for positioning (better performance) */
  useCssTransform?: boolean;
  
  /** Ignore small position adjustments to prevent shake */
  ignoreShake?: boolean;
}

type AlignPoint = string; // Two-character combinations like 'tl', 'tr', 'bl', 'br', 'cc', 'tc', 'bc', 'cl', 'cr'

Built-in Placements

Predefined placement configurations for common positioning scenarios.

/**
 * Built-in placement configurations mapping placement names to alignment configs
 */
type BuildInPlacements = Record<string, AlignType>;

interface TriggerProps {
  /** Popup alignment configuration */
  popupAlign?: AlignType;
  
  /** Placement key from builtinPlacements */
  popupPlacement?: string;
  
  /** Predefined placement configurations */
  builtinPlacements?: BuildInPlacements;
  
  /** Generate CSS class name from alignment result */
  getPopupClassNameFromAlign?: (align: AlignType) => string;
  
  /** Callback when popup alignment completes */
  onPopupAlign?: (element: HTMLElement, align: AlignType) => void;
}

Point Alignment

Align popup to mouse cursor position for context menus and tooltips.

interface TriggerProps {
  /** Whether to align popup to mouse point instead of trigger element */
  alignPoint?: boolean;
}

interface Point {
  pageX: number;
  pageY: number;
}

interface TriggerState {
  /** Current mouse point for alignment */
  point?: Point;
}

Usage Examples:

import React from "react";
import Trigger from "rc-trigger";

// Basic alignment with offset
function BasicAlignment() {
  return (
    <Trigger
      action={['click']}
      popup={<div>Popup content</div>}
      popupAlign={{
        points: ['tl', 'bl'], // Popup top-left to trigger bottom-left
        offset: [0, 4], // 4px gap below trigger
        overflow: { adjustX: true, adjustY: true }
      }}
    >
      <button>Click me</button>
    </Trigger>
  );
}

// Built-in placements
function BuiltinPlacements() {
  const placements = {
    topLeft: {
      points: ['bl', 'tl'],
      offset: [0, -4],
      overflow: { adjustX: true, adjustY: true }
    },
    topRight: {
      points: ['br', 'tr'],
      offset: [0, -4],
      overflow: { adjustX: true, adjustY: true }
    },
    bottomLeft: {
      points: ['tl', 'bl'],
      offset: [0, 4],
      overflow: { adjustX: true, adjustY: true }
    },
    bottomRight: {
      points: ['tr', 'br'],
      offset: [0, 4],
      overflow: { adjustX: true, adjustY: true }
    }
  };

  return (
    <Trigger
      action={['click']}
      popup={<div>Popup with built-in placement</div>}
      popupPlacement="bottomLeft"
      builtinPlacements={placements}
    >
      <button>Click me</button>
    </Trigger>
  );
}

// Point alignment for context menu
function ContextMenu() {
  return (
    <Trigger
      action={['contextMenu']}
      popup={
        <ul style={{ margin: 0, padding: 8, listStyle: 'none', background: 'white', boxShadow: '0 2px 8px rgba(0,0,0,0.1)' }}>
          <li>Menu Item 1</li>
          <li>Menu Item 2</li>
          <li>Menu Item 3</li>
        </ul>
      }
      alignPoint={true}
      popupAlign={{
        points: ['tl', 'tl'],
        overflow: { adjustX: true, adjustY: true }
      }}
    >
      <div style={{ padding: 20, background: '#f0f0f0' }}>
        Right-click for context menu
      </div>
    </Trigger>
  );
}

// Advanced alignment with CSS positioning
function AdvancedAlignment() {
  return (
    <Trigger
      action={['click']}
      popup={<div>Positioned with CSS transform</div>}
      popupAlign={{
        points: ['cc', 'cc'], // Center to center
        useCssTransform: true, // Use transform for better performance
        ignoreShake: true // Prevent micro-adjustments
      }}
    >
      <button>Center-aligned popup</button>
    </Trigger>
  );
}

// Dynamic class name from alignment
function DynamicClassName() {
  const getClassName = (align) => {
    const points = align.points || [];
    return `popup-${points[0]}-${points[1]}`;
  };

  return (
    <Trigger
      action={['hover']}
      popup={<div>Popup with dynamic class</div>}
      popupAlign={{
        points: ['tc', 'bc'],
        offset: [0, -4]
      }}
      getPopupClassNameFromAlign={getClassName}
      onPopupAlign={(element, align) => {
        console.log('Popup aligned:', align);
      }}
    >
      <button>Hover for popup</button>
    </Trigger>
  );
}

Common Alignment Patterns

Dropdown Menu

popupAlign={{
  points: ['tl', 'bl'],
  offset: [0, 4],
  overflow: { adjustX: true, adjustY: true }
}}

Tooltip Above

popupAlign={{
  points: ['bc', 'tc'],
  offset: [0, -8],
  overflow: { adjustX: true, adjustY: true }
}}

Tooltip Below

popupAlign={{
  points: ['tc', 'bc'],
  offset: [0, 8],
  overflow: { adjustX: true, adjustY: true }
}}

Side Panel

popupAlign={{
  points: ['tl', 'tr'],
  offset: [4, 0],
  overflow: { adjustX: true, adjustY: true }
}}

Centered Modal

popupAlign={{
  points: ['cc', 'cc'],
  useCssTransform: true
}}

Install with Tessl CLI

npx tessl i tessl/npm-rc-trigger

docs

animation.md

events.md

index.md

positioning.md

trigger-component.md

tile.json