Base abstract trigger component for React that manages popup behavior and positioning with hover, click, focus actions and precise alignment.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
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'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;
}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>
);
}popupAlign={{
points: ['tl', 'bl'],
offset: [0, 4],
overflow: { adjustX: true, adjustY: true }
}}popupAlign={{
points: ['bc', 'tc'],
offset: [0, -8],
overflow: { adjustX: true, adjustY: true }
}}popupAlign={{
points: ['tc', 'bc'],
offset: [0, 8],
overflow: { adjustX: true, adjustY: true }
}}popupAlign={{
points: ['tl', 'tr'],
offset: [4, 0],
overflow: { adjustX: true, adjustY: true }
}}popupAlign={{
points: ['cc', 'cc'],
useCssTransform: true
}}Install with Tessl CLI
npx tessl i tessl/npm-rc-trigger