The Collapsible component provides a way to show and hide content with a smooth animation. It's commonly used for FAQ sections, settings panels, and any content that needs to be toggled on and off.
import { Collapsible } from '@dashflowx/core'export default function CollapsibleExample() {const [isOpen, setIsOpen] = useState(false);return (<CollapsibleisOpen={isOpen}onOpenChange={setIsOpen}title="Click to expand"collapsibleContent={<div>This content can be toggled</div>}/>)}
Preview:
Click to expand
| Prop | Type | Default | Description |
|---|---|---|---|
isOpen | boolean | false | Whether the collapsible is open |
onOpenChange | function | - | Callback when open state changes |
title | string | 'Collapsible Title' | The title text for the collapsible |
collapsibleContent | JSX.Element | - | The content to show/hide |
className | string | '' | Additional CSS classes for the container |
titleContainerClassName | string | '' | Additional CSS classes for the title container |
titleClassName | string | '' | Additional CSS classes for the title |
contentClassName | string | '' | Additional CSS classes for the content |
const [isOpen, setIsOpen] = useState(false);<CollapsibleisOpen={isOpen}onOpenChange={setIsOpen}title="Basic Collapsible"collapsibleContent={<p>This is the collapsible content.</p>}/>
Preview:
Basic Collapsible
const [openItems, setOpenItems] = useState<string[]>([]);const toggleItem = (id: string) => {setOpenItems(prev =>prev.includes(id)? prev.filter(item => item !== id): [...prev, id]);};const faqItems = [{id: '1',question: 'What is this service?',answer: 'This is a comprehensive service that provides various features and functionality.'},{id: '2',question: 'How do I get started?',answer: 'You can get started by creating an account and following our onboarding process.'}];<div className="space-y-4">{faqItems.map(item => (<Collapsiblekey={item.id}isOpen={openItems.includes(item.id)}onOpenChange={() => toggleItem(item.id)}title={item.question}collapsibleContent={<p>{item.answer}</p>}/>))}</div>
Preview:
What is this service?
const [isOpen, setIsOpen] = useState(false);<CollapsibleisOpen={isOpen}onOpenChange={setIsOpen}title="Advanced Settings"collapsibleContent={<div className="space-y-4"><div><label className="block text-sm font-medium mb-2">Setting 1</label><input type="text" className="w-full border rounded px-3 py-2" /></div><div><label className="block text-sm font-medium mb-2">Setting 2</label><select className="w-full border rounded px-3 py-2"><option>Option 1</option><option>Option 2</option></select></div></div>}/>
Preview:
Advanced Settings
<CollapsibleisOpen={isOpen}onOpenChange={setIsOpen}title="Custom Styled"collapsibleContent={<p>This collapsible has custom styling.</p>}className="border-2 border-blue-500 rounded-xl"titleContainerClassName="bg-blue-50"titleClassName="text-blue-800"contentClassName="bg-blue-25"/>
Preview:
Custom Styled
const faqData = [{id: '1',question: 'How do I reset my password?',answer: 'You can reset your password by clicking the "Forgot Password" link on the login page.'},{id: '2',question: 'Can I change my email address?',answer: 'Yes, you can change your email address in the account settings section.'},{id: '3',question: 'Is there a mobile app?',answer: 'Yes, we have mobile apps available for both iOS and Android devices.'}];<div className="max-w-2xl mx-auto space-y-4"><h2 className="text-2xl font-bold text-center mb-8">Frequently Asked Questions</h2>{faqData.map(item => (<Collapsiblekey={item.id}isOpen={openItems.includes(item.id)}onOpenChange={() => toggleItem(item.id)}title={item.question}collapsibleContent={<p className="text-gray-600">{item.answer}</p>}/>))}</div>
const docSections = [{id: 'installation',title: 'Installation',content: (<div className="space-y-3"><p>Follow these steps to install the package:</p><ol className="list-decimal list-inside space-y-1"><li>Run <code>npm install package-name</code></li><li>Import the component in your file</li><li>Use the component in your JSX</li></ol></div>)},{id: 'usage',title: 'Usage',content: (<div className="space-y-3"><p>Here's how to use the component:</p><pre className="bg-gray-100 p-3 rounded text-sm"><code>{`<Component prop="value" />`}</code></pre></div>)}];<div className="space-y-4">{docSections.map(section => (<Collapsiblekey={section.id}isOpen={openItems.includes(section.id)}onOpenChange={() => toggleItem(section.id)}title={section.title}collapsibleContent={section.content}/>))}</div>
const [filtersOpen, setFiltersOpen] = useState(false);<CollapsibleisOpen={filtersOpen}onOpenChange={setFiltersOpen}title="Filter Options"collapsibleContent={<div className="grid grid-cols-2 gap-4"><div><label className="block text-sm font-medium mb-2">Category</label><select className="w-full border rounded px-3 py-2"><option>All Categories</option><option>Technology</option><option>Design</option></select></div><div><label className="block text-sm font-medium mb-2">Price Range</label><select className="w-full border rounded px-3 py-2"><option>Any Price</option><option>Under $50</option><option>$50 - $100</option></select></div></div>}/>
const helpSections = [{id: 'getting-started',title: 'Getting Started',content: (<div className="space-y-3"><p>Welcome! Here's how to get started:</p><ul className="list-disc list-inside space-y-1"><li>Create your account</li><li>Complete your profile</li><li>Explore the features</li></ul></div>)},{id: 'troubleshooting',title: 'Troubleshooting',content: (<div className="space-y-3"><p>Having issues? Try these solutions:</p><ul className="list-disc list-inside space-y-1"><li>Check your internet connection</li><li>Clear your browser cache</li><li>Contact support if problems persist</li></ul></div>)}];
Use clear and descriptive titles for collapsible sections.
// ✅ Good - Clear title<Collapsibletitle="How do I reset my password?"collapsibleContent={<p>Answer content...</p>}/>// ❌ Avoid - Unclear title<Collapsibletitle="Question 1"collapsibleContent={<p>Answer content...</p>}/>
Use consistent state management patterns for multiple collapsibles.
// ✅ Good - Consistent state managementconst [openItems, setOpenItems] = useState<string[]>([]);const toggleItem = (id: string) => {setOpenItems(prev =>prev.includes(id)? prev.filter(item => item !== id): [...prev, id]);};
Keep collapsible content concise and focused.
// ✅ Good - Concise content<Collapsibletitle="Quick Answer"collapsibleContent={<p>Short, focused answer.</p>}/>// ❌ Avoid - Too much content<Collapsibletitle="Long Answer"collapsibleContent={<div>Very long content that should probably be on its own page...</div>}/>
Ensure collapsibles are accessible to all users.
// ✅ Good - Accessible<Collapsibletitle="Accessible Section"collapsibleContent={<p>Content with proper ARIA attributes</p>}/>
Use collapsibles to create clear visual hierarchy.
// ✅ Good - Clear hierarchy<div className="space-y-4"><h2>Main Section</h2><Collapsible title="Subsection 1" /><Collapsible title="Subsection 2" /></div>
You can customize the collapsible appearance using CSS classes:
<Collapsibletitle="Custom Styled"collapsibleContent={<p>Custom content</p>}className="border-2 border-purple-500 rounded-xl shadow-lg"titleContainerClassName="bg-purple-50"titleClassName="text-purple-800 font-bold"contentClassName="bg-purple-25"/>
Use different themes for different contexts:
// Light theme<Collapsibletitle="Light Theme"collapsibleContent={<p>Light themed content</p>}className="bg-white border-gray-200"/>// Dark theme<Collapsibletitle="Dark Theme"collapsibleContent={<p>Dark themed content</p>}className="bg-gray-900 border-gray-700 text-white"/>
Use different sizes for different emphasis levels:
// Small collapsible<Collapsibletitle="Small"collapsibleContent={<p>Small content</p>}className="w-64"/>// Large collapsible<Collapsibletitle="Large"collapsibleContent={<p>Large content</p>}className="w-full max-w-4xl"/>
Manage multiple collapsibles with shared state:
const [openSections, setOpenSections] = useState<Set<string>>(new Set());const toggleSection = (id: string) => {setOpenSections(prev => {const newSet = new Set(prev);if (newSet.has(id)) {newSet.delete(id);} else {newSet.add(id);}return newSet;});};
Create accordion behavior where only one item can be open:
const [openItem, setOpenItem] = useState<string | null>(null);const toggleItem = (id: string) => {setOpenItem(prev => prev === id ? null : id);};
Use dynamic content in collapsibles:
const [content, setContent] = useState('Initial content');<Collapsibletitle="Dynamic Content"collapsibleContent={<p>{content}</p>}/>
- Accordion: For multiple collapsible sections
- Disclosure: For simple show/hide functionality
- Tabs: For tabbed content
- Modal: For overlay content
- Sheet: For slide-out content
For the complete API reference and advanced usage patterns, see the Collapsible API documentation.
