Collapsible Panel
Expandable and collapsible content sections with smooth animations, multiple variants, accordion group behavior, and a horizontal tabs layout for side-by-side split panes.
Basic Usage
Individual panels expand and collapse with a smooth CSS Grid height animation. Each panel manages its own state or can be externally controlled.
Basic Usage
Welcome to the CollapsiblePanel component. Click the header to expand or collapse the content area with a smooth height animation. This panel starts open by default.
Panels support subtitles, icons, custom header actions, multiple variants, sizes, and full keyboard accessibility. They can be used standalone or grouped in an accordion.
Use the lazy prop to defer rendering of content until the panel is first opened, or destroyOnCollapse to unmount content when collapsed.
import { CollapsiblePanel } from 'fluxo-ui';
<CollapsiblePanel title="Getting Started" defaultOpen>
<p>Welcome to the CollapsiblePanel component! Click the header to toggle.</p>
</CollapsiblePanel>
<CollapsiblePanel title="Advanced Features" subtitle="Explore more options">
<p>This panel has a subtitle and starts collapsed.</p>
</CollapsiblePanel>Variants
Five visual styles to match different UI contexts — from subtle defaults to prominent elevated shadows.
Variants
This is the default variant. Subtle border with clean background. Best for general use.
This is the bordered variant. Prominent border that highlights on open with the primary accent color.
This is the elevated variant. Shadow-based depth. Gains more elevation when expanded.
This is the ghost variant. No background or border. Blends into surrounding content seamlessly.
This is the separated variant. Distinct header background with a divider line when open.
<CollapsiblePanel variant="default" title="Default" defaultOpen>...</CollapsiblePanel>
<CollapsiblePanel variant="bordered" title="Bordered">...</CollapsiblePanel>
<CollapsiblePanel variant="elevated" title="Elevated">...</CollapsiblePanel>
<CollapsiblePanel variant="ghost" title="Ghost">...</CollapsiblePanel>
<CollapsiblePanel variant="separated" title="Separated">...</CollapsiblePanel>Sizes
Three size presets control header padding, font size, and indicator dimensions.
Sizes
Content rendered at the sm size. Header padding, font size, and indicator icon all scale proportionally.
Content rendered at the md size. Header padding, font size, and indicator icon all scale proportionally.
Content rendered at the lg size. Header padding, font size, and indicator icon all scale proportionally.
<CollapsiblePanel size="sm" title="Small Panel">...</CollapsiblePanel>
<CollapsiblePanel size="md" title="Medium Panel">...</CollapsiblePanel>
<CollapsiblePanel size="lg" title="Large Panel">...</CollapsiblePanel>Icon Positions
Place the toggle chevron at the start or end of the header.
Icon Positions
The toggle indicator sits at the trailing edge of the header. This is the default behavior.
Placing the indicator at the start gives a tree-view or sidebar-style appearance.
<CollapsiblePanel iconPosition="end" title="Icon End (default)">...</CollapsiblePanel>
<CollapsiblePanel iconPosition="start" title="Icon Start">...</CollapsiblePanel>With Icons
Add a leading icon to visually categorize panel content — settings, security, notifications, etc.
With Icons
Configure application-level settings like language, timezone, and display preferences.
Two-factor authentication, API keys, session management, and access control rules.
Email alerts, push notifications, and in-app notification preferences.
<CollapsiblePanel
title="Settings"
icon={<GearIcon />}
>
...
</CollapsiblePanel>Accordion Group
Wrap panels in a CollapsiblePanelGroup with accordion to ensure only one panel is open at a time.
Accordion Group
A flexible, accessible component for expanding and collapsing content sections. Supports multiple variants, sizes, icons, and group/accordion behavior.
Yes! Wrap multiple panels in a CollapsiblePanelGroup with the accordion prop. Only one panel can be open at a time.
Use defaultOpenKeys for initial state, or the individual open and onToggle props for full controlled behavior.
Fully ADA-compliant. Headers are focusable, respond to Enter and Space, use proper ARIA attributes (aria-expanded,aria-controls, role="region"), and respect prefers-reduced-motion.
import { CollapsiblePanel, CollapsiblePanelGroup } from 'fluxo-ui';
<CollapsiblePanelGroup accordion variant="bordered">
<CollapsiblePanel id="faq-1" title="What is CollapsiblePanel?">
<p>A flexible panel that expands and collapses.</p>
</CollapsiblePanel>
<CollapsiblePanel id="faq-2" title="Does it support accordion mode?">
<p>Yes! Wrap panels in a Group with accordion prop.</p>
</CollapsiblePanel>
</CollapsiblePanelGroup>Multi-Open Group
Without the accordion prop, any number of panels can be open simultaneously. The group still provides shared variant and size defaults.
Multi-Open Group
Configure your primary and replica database connections. Connection pool size defaults to 10 with a 30-second idle timeout.
Redis cluster mode is enabled by default. In-memory cache uses LRU eviction with a 256 MB cap.
Topics auto-create is disabled in production. Consumer group rebalance strategy is cooperative-sticky.
<CollapsiblePanelGroup variant="separated" defaultOpenKeys={['m-1', 'm-2']}>
<CollapsiblePanel id="m-1" title="Panel A">...</CollapsiblePanel>
<CollapsiblePanel id="m-2" title="Panel B">...</CollapsiblePanel>
<CollapsiblePanel id="m-3" title="Panel C">...</CollapsiblePanel>
</CollapsiblePanelGroup>Header Actions
Place interactive elements (buttons, badges) at the trailing edge of the header. Click events are isolated — they do not toggle the panel.
Header Actions
Header actions sit at the trailing edge of the header, next to the toggle indicator. Clicking them does not toggle the panel — event propagation is stopped automatically.
You can place any interactive element in the header actions slot — buttons, badges, switches, or custom controls.
<CollapsiblePanel
title="Notifications"
headerActions={<Button size="xs" onClick={handleClear}>Clear All</Button>}
>
...
</CollapsiblePanel>Disabled State
Disabled panels cannot be toggled. The header shows a not-allowed cursor and reduced opacity.
Disabled State
This content is not accessible because the panel is disabled and collapsed.
This panel starts open and is disabled — the user can see the content but cannot collapse it. The header cursor changes to not-allowed and the hover effect is suppressed.
<CollapsiblePanel title="Locked Section" disabled>
<p>This content is not accessible.</p>
</CollapsiblePanel>
<CollapsiblePanel title="Locked But Open" disabled defaultOpen>
<p>Content is visible but cannot be collapsed.</p>
</CollapsiblePanel>Controlled Mode
Use open and onToggle for full external control over the panel state.
Controlled Mode
This panel is fully controlled — the open prop determines whether it is expanded, and onToggle reports the requested state change. You can still click the header to toggle, or use the external button above.
const [isOpen, setIsOpen] = useState(false);
<Button onClick={() => setIsOpen(!isOpen)}>
{isOpen ? 'Collapse' : 'Expand'}
</Button>
<CollapsiblePanel
title="Controlled Panel"
open={isOpen}
onToggle={setIsOpen}
>
<p>Externally controlled open state.</p>
</CollapsiblePanel>Custom Header Template
The headerTemplate prop gives you complete control over header rendering with access to isOpen and toggle.
Custom Header Template
headerTemplate prop gives you full control over the header rendering. You receive isOpen andtoggle and can build any custom UI. The toggle indicator, title, subtitle, and icon props are all ignored when a template is provided.<CollapsiblePanel
title="Custom Header"
headerTemplate={({ isOpen, toggle }) => (
<div className="custom-header" onClick={toggle}>
<span>{isOpen ? '▼' : '▶'}</span>
<span>My Custom Header</span>
</div>
)}
>
...
</CollapsiblePanel>Horizontal Collapsible Tabs
Side-by-side collapsible panels that show rotated labels when collapsed. On mobile they stack vertically. At least one tab stays open (configurable via minOpenTabs).
Horizontal Collapsible Tabs
Code Editor
Live Preview
Hello, World!
import { CollapsibleTabs } from 'fluxo-ui';
const tabs = [
{ id: 'editor', label: 'Editor', isOpen: true, render: () => <div>Editor</div> },
{ id: 'preview', label: 'Preview', isOpen: true, render: () => <div>Preview</div> },
{ id: 'console', label: 'Console', isOpen: false, render: () => <div>Console</div> },
];
<CollapsibleTabs tabs={tabs} height={400} />Horizontal Tabs Variants
The horizontal tabs layout supports default, bordered, and elevated visual styles.
Horizontal Tabs Variants
default
Panel A
First panel content with full data view.
Panel B
Second panel content with details.
bordered
Panel A
First panel content with full data view.
Panel B
Second panel content with details.
elevated
Panel A
First panel content with full data view.
Panel B
Second panel content with details.
<CollapsibleTabs tabs={tabs} variant="bordered" />
<CollapsibleTabs tabs={tabs} variant="elevated" />Import
import { CollapsiblePanel, CollapsiblePanelGroup, CollapsibleTabs } from 'fluxo-ui';CollapsiblePanel Props
titlereqReact.ReactNodeHeader text or element displayed in the panel header.
titlereqReact.ReactNodeHeader text or element displayed in the panel header.
childrenreqReact.ReactNodeContent rendered inside the collapsible body.
childrenreqReact.ReactNodeContent rendered inside the collapsible body.
subtitleReact.ReactNodeSecondary text rendered below the title in the header.
subtitleReact.ReactNodeSecondary text rendered below the title in the header.
iconReact.ReactNodeIcon element rendered before the title in the header.
iconReact.ReactNodeIcon element rendered before the title in the header.
variant'default' | 'bordered' | 'elevated' | 'ghost' | 'separated'"'default'"Visual style of the panel. Group-level variant is used as fallback.
variant'default' | 'bordered' | 'elevated' | 'ghost' | 'separated'"'default'"Visual style of the panel. Group-level variant is used as fallback.
size'sm' | 'md' | 'lg'"'md'"Controls header padding, font size, and indicator icon size.
size'sm' | 'md' | 'lg'"'md'"Controls header padding, font size, and indicator icon size.
iconPosition'start' | 'end'"'end'"Position of the toggle chevron — before or after the title.
iconPosition'start' | 'end'"'end'"Position of the toggle chevron — before or after the title.
expandIconReact.ReactNodeCustom icon shown when the panel is collapsed.
expandIconReact.ReactNodeCustom icon shown when the panel is collapsed.
collapseIconReact.ReactNodeCustom icon shown when the panel is expanded. Falls back to expandIcon.
collapseIconReact.ReactNodeCustom icon shown when the panel is expanded. Falls back to expandIcon.
defaultOpenboolean"false"Whether the panel starts open (uncontrolled mode).
defaultOpenboolean"false"Whether the panel starts open (uncontrolled mode).
openbooleanControlled open state. When set, the component is fully controlled.
openbooleanControlled open state. When set, the component is fully controlled.
onToggle(open: boolean) => voidCalled when the user toggles the panel. Receives the new open state.
onToggle(open: boolean) => voidCalled when the user toggles the panel. Receives the new open state.
disabledboolean"false"Prevents toggling. Header shows not-allowed cursor and hover is suppressed.
disabledboolean"false"Prevents toggling. Header shows not-allowed cursor and hover is suppressed.
headerActionsReact.ReactNodeInteractive elements placed at the end of the header. Click events do not propagate.
headerActionsReact.ReactNodeInteractive elements placed at the end of the header. Click events do not propagate.
headerTemplate(props: { isOpen, toggle }) => ReactNodeFully custom header renderer. When set, title/subtitle/icon/indicator are ignored.
headerTemplate(props: { isOpen, toggle }) => ReactNodeFully custom header renderer. When set, title/subtitle/icon/indicator are ignored.
lazyboolean"false"Defers rendering content until the panel is first opened.
lazyboolean"false"Defers rendering content until the panel is first opened.
destroyOnCollapseboolean"false"Unmounts content from the DOM when the panel is collapsed.
destroyOnCollapseboolean"false"Unmounts content from the DOM when the panel is collapsed.
classNamestringAdditional CSS classes for the root element.
classNamestringAdditional CSS classes for the root element.
headerClassNamestringAdditional CSS classes for the header element.
headerClassNamestringAdditional CSS classes for the header element.
contentClassNamestringAdditional CSS classes for the content wrapper.
contentClassNamestringAdditional CSS classes for the content wrapper.
styleReact.CSSPropertiesInline styles for the root element.
styleReact.CSSPropertiesInline styles for the root element.
idstringElement ID. Also used as the group key in CollapsiblePanelGroup.
idstringElement ID. Also used as the group key in CollapsiblePanelGroup.
CollapsiblePanelGroup Props
childrenreqReact.ReactNodeCollapsiblePanel children to manage.
childrenreqReact.ReactNodeCollapsiblePanel children to manage.
accordionboolean"false"When true, only one panel can be open at a time.
accordionboolean"false"When true, only one panel can be open at a time.
defaultOpenKeysstring[]"[]"Array of panel IDs that start open.
defaultOpenKeysstring[]"[]"Array of panel IDs that start open.
variant'default' | 'bordered' | 'elevated' | 'ghost' | 'separated'"'default'"Default variant for all child panels.
variant'default' | 'bordered' | 'elevated' | 'ghost' | 'separated'"'default'"Default variant for all child panels.
size'sm' | 'md' | 'lg'"'md'"Default size for all child panels.
size'sm' | 'md' | 'lg'"'md'"Default size for all child panels.
iconPosition'start' | 'end'"'end'"Default icon position for all child panels.
iconPosition'start' | 'end'"'end'"Default icon position for all child panels.
gapnumberGap in pixels between panels.
gapnumberGap in pixels between panels.
onChange(openKeys: string[]) => voidCalled when the set of open panels changes.
onChange(openKeys: string[]) => voidCalled when the set of open panels changes.
classNamestringAdditional CSS classes for the group container.
classNamestringAdditional CSS classes for the group container.
styleReact.CSSPropertiesInline styles for the group container.
styleReact.CSSPropertiesInline styles for the group container.
CollapsibleTabs Props
tabsreqCollapsibleTabItem[]Array of tab objects with id, label, isOpen, and render function.
tabsreqCollapsibleTabItem[]Array of tab objects with id, label, isOpen, and render function.
heightnumber | stringMinimum height of the tabs container.
heightnumber | stringMinimum height of the tabs container.
minOpenTabsnumber"1"Minimum number of tabs that must stay open at any time.
minOpenTabsnumber"1"Minimum number of tabs that must stay open at any time.
variant'default' | 'bordered' | 'elevated'"'default'"Visual style variant for the tabs layout.
variant'default' | 'bordered' | 'elevated'"'default'"Visual style variant for the tabs layout.
onTabToggle(tabId: string, isOpen: boolean) => voidCalled when a tab is toggled.
onTabToggle(tabId: string, isOpen: boolean) => voidCalled when a tab is toggled.
classNamestringAdditional CSS classes for the container.
classNamestringAdditional CSS classes for the container.
styleReact.CSSPropertiesInline styles for the container.
styleReact.CSSPropertiesInline styles for the container.
Features
5 Variants
default, bordered, elevated, ghost, and separated visual styles
3 Sizes
Small, medium, and large with proportional scaling of padding and fonts
Accordion Mode
Group panels with single-open or multi-open behavior
ADA Accessible
Full ARIA attributes, keyboard navigation, and prefers-reduced-motion support
Smooth Animations
CSS Grid-based height animation with cubic-bezier easing for fluid transitions
Custom Headers
Full header template support for completely custom header rendering
Horizontal Tabs
Side-by-side collapsible panels with rotated labels — IDE-style split panes
Theming
Full dark/light mode and all brand themes via CSS variables — zero extra config