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
Motion configuration using rc-motion for smooth popup transitions and mask animations. The animation system supports both modern motion props and legacy animation configurations.
Modern animation configuration using rc-motion for smooth, performant transitions.
/**
* Motion configuration for popup and mask animations
*/
interface TriggerProps {
/** RC-Motion configuration for popup animations */
popupMotion?: CSSMotionProps;
/** RC-Motion configuration for mask animations */
maskMotion?: CSSMotionProps;
}
/**
* RC-Motion properties (from rc-motion library)
*/
interface CSSMotionProps {
/** CSS class name or object for motion styling */
motionName?: string | {
appear?: string;
enter?: string;
leave?: string;
appearActive?: string;
enterActive?: string;
leaveActive?: string;
};
/** Whether to trigger motion on initial mount */
motionAppear?: boolean;
/** Whether to trigger motion on enter */
motionEnter?: boolean;
/** Whether to trigger motion on leave */
motionLeave?: boolean;
/** Motion event callbacks */
onAppearStart?: (element: HTMLElement) => void;
onEnterStart?: (element: HTMLElement) => void;
onLeaveStart?: (element: HTMLElement) => void;
onAppearActive?: (element: HTMLElement) => void;
onEnterActive?: (element: HTMLElement) => void;
onLeaveActive?: (element: HTMLElement) => void;
onAppearEnd?: (element: HTMLElement) => void;
onEnterEnd?: (element: HTMLElement) => void;
onLeaveEnd?: (element: HTMLElement) => void;
/** Remove element from DOM after leave animation */
removeOnLeave?: boolean;
/** Force render even when not visible (for enter animations) */
forceRender?: boolean;
/** Deadline for motion to complete (ms) */
motionDeadline?: number;
}Deprecated animation properties maintained for backwards compatibility.
/**
* @deprecated Use popupMotion instead
*/
interface TriggerProps {
/** @deprecated CSS transition name for popup */
popupTransitionName?: TransitionNameType;
/** @deprecated CSS animation name for popup */
popupAnimation?: AnimationType;
/** @deprecated CSS transition name for mask */
maskTransitionName?: TransitionNameType;
/** @deprecated CSS animation name for mask */
maskAnimation?: string;
}
type TransitionNameType = string;
type AnimationType = string;Usage Examples:
import React from "react";
import Trigger from "rc-trigger";
// Basic fade animation
function FadeAnimation() {
return (
<Trigger
action={['click']}
popup={<div>Fade in/out popup</div>}
popupMotion={{
motionName: 'fade',
motionAppear: false,
motionEnter: true,
motionLeave: true
}}
>
<button>Click for fade</button>
</Trigger>
);
}
// Slide down animation
function SlideAnimation() {
return (
<Trigger
action={['click']}
popup={<div>Slide down popup</div>}
popupMotion={{
motionName: {
enter: 'slide-up-enter',
enterActive: 'slide-up-enter-active',
leave: 'slide-up-leave',
leaveActive: 'slide-up-leave-active'
}
}}
>
<button>Click for slide</button>
</Trigger>
);
}
// Animation with mask
function AnimationWithMask() {
return (
<Trigger
action={['click']}
popup={<div>Animated popup with mask</div>}
mask={true}
popupMotion={{
motionName: 'zoom',
removeOnLeave: true
}}
maskMotion={{
motionName: 'fade'
}}
>
<button>Click for modal</button>
</Trigger>
);
}
// Animation callbacks
function AnimationCallbacks() {
return (
<Trigger
action={['click']}
popup={<div>Popup with callbacks</div>}
popupMotion={{
motionName: 'bounce',
onEnterStart: (element) => {
console.log('Animation starting:', element);
},
onEnterEnd: (element) => {
console.log('Animation completed:', element);
},
onLeaveStart: (element) => {
console.log('Exit animation starting:', element);
}
}}
>
<button>Click for bounce</button>
</Trigger>
);
}
// Legacy animation (deprecated)
function LegacyAnimation() {
return (
<Trigger
action={['click']}
popup={<div>Legacy animation</div>}
popupTransitionName="rc-trigger-popup-slide-up"
maskTransitionName="rc-trigger-mask-fade"
>
<button>Legacy animation</button>
</Trigger>
);
}.fade-enter {
opacity: 0;
}
.fade-enter-active {
opacity: 1;
transition: opacity 0.3s ease;
}
.fade-leave {
opacity: 1;
}
.fade-leave-active {
opacity: 0;
transition: opacity 0.3s ease;
}.slide-up-enter {
opacity: 0;
transform: translateY(10px);
}
.slide-up-enter-active {
opacity: 1;
transform: translateY(0);
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
.slide-up-leave {
opacity: 1;
transform: translateY(0);
}
.slide-up-leave-active {
opacity: 0;
transform: translateY(-10px);
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}.zoom-enter {
opacity: 0;
transform: scale(0.8);
}
.zoom-enter-active {
opacity: 1;
transform: scale(1);
transition: all 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
}
.zoom-leave {
opacity: 1;
transform: scale(1);
}
.zoom-leave-active {
opacity: 0;
transform: scale(0.8);
transition: all 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
}.bounce-enter {
opacity: 0;
transform: scale(0.3);
}
.bounce-enter-active {
opacity: 1;
transform: scale(1);
transition: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
.bounce-leave {
opacity: 1;
transform: scale(1);
}
.bounce-leave-active {
opacity: 0;
transform: scale(0.3);
transition: all 0.3s ease-out;
}transform and opacity for smooth 60fps animationswidth, height, marginuseCssTransform: true in alignment for better performanceremoveOnLeave: true to clean up DOM after animationsprefers-reduced-motion preferenceInstall with Tessl CLI
npx tessl i tessl/npm-rc-trigger