React collapsible panel component with accordion support and extensive customization options
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
RC-Collapse integrates with rc-motion to provide smooth expand and collapse animations. The animation system supports extensive customization through motion configuration props.
interface CSSMotionProps {
motionName?: string;
motionAppear?: boolean;
motionEnter?: boolean;
motionLeave?: boolean;
motionLeaveImmediately?: boolean;
motionDeadline?: number;
removeOnLeave?: boolean;
leavedClassName?: string;
onAppearStart?: MotionEventHandler;
onEnterStart?: MotionEventHandler;
onLeaveStart?: MotionEventHandler;
onAppearActive?: MotionEventHandler;
onEnterActive?: MotionEventHandler;
onLeaveActive?: MotionEventHandler;
onAppearEnd?: MotionEventHandler;
onEnterEnd?: MotionEventHandler;
onLeaveEnd?: MotionEventHandler;
}
type MotionEventHandler = (
element: HTMLElement,
event?: React.TransitionEvent | React.AnimationEvent
) => React.CSSProperties | void;
interface MotionEvent {
deadline?: boolean;
target?: HTMLElement;
}motionName: string - CSS class prefix for motion statesmotionAppear: boolean - Enable appear animation (default: true)motionEnter: boolean - Enable enter animation (default: true)motionLeave: boolean - Enable leave animation (default: true)motionLeaveImmediately: boolean - Start leave animation immediatelymotionDeadline: number - Maximum animation duration in millisecondsremoveOnLeave: boolean - Remove element from DOM after leave animationleavedClassName: string - CSS class applied to hidden panels (default: 'rc-collapse-content-hidden')Animation lifecycle event handlers that allow custom animation control:
onAppearStart: Fired when appear animation startsonEnterStart: Fired when enter animation startsonLeaveStart: Fired when leave animation startsonAppearActive: Fired during appear animationonEnterActive: Fired during enter animationonLeaveActive: Fired during leave animationonAppearEnd: Fired when appear animation endsonEnterEnd: Fired when enter animation endsonLeaveEnd: Fired when leave animation endsimport Collapse from "rc-collapse";
const BasicAnimation = () => {
const openMotion = {
motionName: 'rc-collapse-motion',
motionAppear: false,
motionEnter: true,
motionLeave: true,
};
const items = [
{ key: '1', label: 'Animated Panel', children: 'Content with animation' },
];
return <Collapse openMotion={openMotion} items={items} />;
};import Collapse from "rc-collapse";
const CustomDuration = () => {
const openMotion = {
motionName: 'custom-collapse',
motionDeadline: 300, // 300ms max duration
onEnterStart: (element) => {
element.style.transition = 'height 0.3s ease-out';
return { height: 0 };
},
onEnterActive: (element) => {
return { height: element.scrollHeight };
},
onLeaveStart: (element) => {
return { height: element.scrollHeight };
},
onLeaveActive: () => {
return { height: 0 };
},
};
const items = [
{ key: '1', label: 'Custom Duration Panel', children: 'Animated content' },
];
return <Collapse openMotion={openMotion} items={items} />;
};import Collapse from "rc-collapse";
const SmoothHeightAnimation = () => {
const smoothMotion = {
motionName: 'smooth-collapse',
onEnterStart: (element: HTMLElement) => {
element.style.height = '0px';
element.style.opacity = '0';
return {
height: 0,
opacity: 0,
};
},
onEnterActive: (element: HTMLElement) => {
element.style.transition = 'height 0.2s ease, opacity 0.2s ease';
return {
height: `${element.scrollHeight}px`,
opacity: 1,
};
},
onLeaveStart: (element: HTMLElement) => {
return {
height: `${element.scrollHeight}px`,
opacity: 1,
};
},
onLeaveActive: () => {
return {
height: 0,
opacity: 0,
};
},
};
const items = [
{ key: '1', label: 'Smooth Animation', children: 'Smoothly animated content' },
];
return <Collapse openMotion={smoothMotion} items={items} />;
};import Collapse from "rc-collapse";
const NoAnimation = () => {
const noMotion = {
motionName: '',
motionAppear: false,
motionEnter: false,
motionLeave: false,
};
const items = [
{ key: '1', label: 'Instant Toggle', children: 'No animation content' },
];
return <Collapse openMotion={noMotion} items={items} />;
};import Collapse from "rc-collapse";
const AdvancedAnimation = () => {
const advancedMotion = {
motionName: 'advanced-collapse',
motionDeadline: 500,
onEnterStart: (element: HTMLElement) => {
console.log('Panel opening started');
element.style.transformOrigin = 'top';
return {
transform: 'scaleY(0)',
opacity: 0,
};
},
onEnterActive: (element: HTMLElement) => {
element.style.transition = 'transform 0.3s ease, opacity 0.3s ease';
return {
transform: 'scaleY(1)',
opacity: 1,
};
},
onEnterEnd: () => {
console.log('Panel opening completed');
},
onLeaveStart: (element: HTMLElement) => {
console.log('Panel closing started');
return {
transform: 'scaleY(1)',
opacity: 1,
};
},
onLeaveActive: () => {
return {
transform: 'scaleY(0)',
opacity: 0,
};
},
onLeaveEnd: () => {
console.log('Panel closing completed');
},
};
const items = [
{ key: '1', label: 'Advanced Animation', children: 'Advanced animated content' },
];
return <Collapse openMotion={advancedMotion} items={items} />;
};RC-Collapse applies the following CSS classes during animations:
/* Panel content container */
.rc-collapse-content {
overflow: hidden;
}
/* Hidden panel state */
.rc-collapse-content-hidden {
display: none;
}
/* Active panel state */
.rc-collapse-content-active {
/* Panel is visible and expanded */
}
/* Inactive panel state */
.rc-collapse-content-inactive {
/* Panel is hidden or collapsed */
}/* Custom animation example */
.custom-collapse-motion-enter {
opacity: 0;
transform: translateY(-10px);
}
.custom-collapse-motion-enter-active {
opacity: 1;
transform: translateY(0);
transition: opacity 0.2s, transform 0.2s;
}
.custom-collapse-motion-leave {
opacity: 1;
transform: translateY(0);
}
.custom-collapse-motion-leave-active {
opacity: 0;
transform: translateY(-10px);
transition: opacity 0.2s, transform 0.2s;
}transform and opacity properties for better performanceheight directly when possiblewill-change CSS property for smooth animationsmotionDeadline to prevent long-running animationsconst optimizedMotion = {
motionName: 'optimized-collapse',
removeOnLeave: true, // Remove from DOM after animation
motionDeadline: 300, // Limit animation duration
};import Collapse from "rc-collapse";
const AccessibleAnimation = () => {
// Respect user's motion preferences
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const respectfulMotion = prefersReducedMotion
? {
motionName: '',
motionEnter: false,
motionLeave: false,
}
: {
motionName: 'smooth-collapse',
motionEnter: true,
motionLeave: true,
};
const items = [
{ key: '1', label: 'Accessible Panel', children: 'Respects motion preferences' },
];
return <Collapse openMotion={respectfulMotion} items={items} />;
};The animation system is designed to work with screen readers:
Install with Tessl CLI
npx tessl i tessl/npm-rc-collapse