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
Panel configuration defines the structure and behavior of individual collapsible sections within a Collapse component. The modern approach uses the items prop with ItemType objects.
interface ItemType {
key?: React.Key;
label?: React.ReactNode;
children?: React.ReactNode;
collapsible?: CollapsibleType;
onItemClick?: (panelKey: React.Key) => void;
destroyInactivePanel?: boolean;
className?: string;
style?: object;
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
extra?: React.ReactNode;
forceRender?: boolean;
showArrow?: boolean;
headerClass?: string;
ref?: React.RefObject<HTMLDivElement>;
}
type CollapsibleType = 'header' | 'icon' | 'disabled';
type SemanticName = 'header' | 'title' | 'body' | 'icon';key: React.Key - Unique identifier for the panel (defaults to array index)label: React.ReactNode - Panel header content (text, JSX, or React components)children: React.ReactNode - Panel body contentcollapsible: CollapsibleType - Override global collapsible behavior for this panel
'header': Click header area to toggle'icon': Click expand icon only to toggle'disabled': Panel cannot be toggledonItemClick: (panelKey: React.Key) => void - Panel-specific click handlerdestroyInactivePanel: boolean - Override global destroy behavior for this panelforceRender: boolean - Always render panel content even when inactiveshowArrow: boolean - Show/hide expand arrow for this panel (default: true)ref: React.RefObject<HTMLDivElement> - React ref for the panel elementclassName: string - Custom CSS class for the panel containerstyle: object - Inline styles for the panel containerheaderClass: string - Custom CSS class for the panel headerclassNames: Partial<Record<SemanticName, string>> - Semantic CSS classesstyles: Partial<Record<SemanticName, React.CSSProperties>> - Semantic inline stylesextra: React.ReactNode - Additional content rendered in the header areaimport Collapse from "rc-collapse";
const BasicPanels = () => {
const items = [
{
key: 'panel1',
label: 'First Panel',
children: <div>This is the content of the first panel</div>,
},
{
key: 'panel2',
label: 'Second Panel',
children: 'Simple text content for second panel',
},
];
return <Collapse items={items} />;
};import Collapse from "rc-collapse";
const AdvancedPanels = () => {
const items = [
{
key: 'interactive',
label: (
<div onKeyDown={(e) => e.stopPropagation()}>
<input placeholder="This input won't trigger panel toggle" />
</div>
),
children: 'Panel with interactive header',
showArrow: true,
},
{
key: 'disabled',
label: 'Disabled Panel',
children: 'This panel cannot be toggled',
collapsible: 'disabled',
},
{
key: 'icon-only',
label: 'Icon Only Toggle',
children: 'Click the arrow icon to toggle this panel',
collapsible: 'icon',
},
];
return <Collapse items={items} />;
};import Collapse from "rc-collapse";
const PanelWithExtra = () => {
const items = [
{
key: 'with-extra',
label: 'Panel with Extra Content',
children: 'Main panel content here',
extra: (
<button onClick={(e) => {
e.stopPropagation();
console.log('Extra button clicked');
}}>
Action
</button>
),
},
];
return <Collapse items={items} />;
};import Collapse from "rc-collapse";
const SemanticStyling = () => {
const items = [
{
key: 'styled',
label: 'Styled Panel',
children: 'Content with custom styling',
classNames: {
header: 'custom-header-class',
title: 'custom-title-class',
body: 'custom-body-class',
icon: 'custom-icon-class',
},
styles: {
header: { backgroundColor: '#f0f0f0', padding: '12px' },
title: { fontWeight: 'bold', color: '#333' },
body: { padding: '16px', border: '1px solid #ddd' },
icon: { color: '#1890ff' },
},
},
];
return <Collapse items={items} />;
};import Collapse from "rc-collapse";
const PerformancePanels = () => {
const items = [
{
key: 'heavy-content',
label: 'Heavy Content Panel',
children: <ExpensiveComponent />,
destroyInactivePanel: true, // Destroy when inactive
},
{
key: 'always-rendered',
label: 'Always Rendered Panel',
children: <ImportantComponent />,
forceRender: true, // Always keep in DOM
},
{
key: 'lazy-content',
label: 'Lazy Content Panel',
children: <LazyComponent />,
// Default behavior: render when first opened
},
];
return <Collapse items={items} />;
};import Collapse from "rc-collapse";
const CustomClickHandlers = () => {
const handlePanelClick = (panelKey: React.Key) => {
console.log(`Panel ${panelKey} was clicked`);
// Custom logic here
};
const items = [
{
key: 'tracked',
label: 'Tracked Panel',
children: 'This panel logs clicks',
onItemClick: handlePanelClick,
},
{
key: 'analytics',
label: 'Analytics Panel',
children: 'This panel sends analytics events',
onItemClick: (key) => {
// Send analytics event
analytics.track('panel_toggled', { panelKey: key });
},
},
];
return <Collapse items={items} />;
};key is not provided, the panel's array index is used as the key// Good: Meaningful, stable keys
const goodItems = [
{ key: 'user-profile', label: 'Profile', children: '...' },
{ key: 'user-settings', label: 'Settings', children: '...' },
];
// Avoid: Index-based keys when order might change
const avoidItems = [
{ key: 0, label: 'Dynamic Item', children: '...' },
{ key: 1, label: 'Another Item', children: '...' },
];// Legacy approach (deprecated)
<Collapse>
<Panel header="Panel 1" key="1">Content 1</Panel>
<Panel header="Panel 2" key="2">Content 2</Panel>
</Collapse>
// Modern approach (recommended)
<Collapse
items={[
{ key: '1', label: 'Panel 1', children: 'Content 1' },
{ key: '2', label: 'Panel 2', children: 'Content 2' },
]}
/>Install with Tessl CLI
npx tessl i tessl/npm-rc-collapse