Accordion
A standalone, reusable accordion component for creating individual collapsible content sections. Perfect for single expandable items, custom layouts, and building complex accordion interfaces with full control over each item.
Features
- Individual Control: Each accordion is a self-contained, independent component
- Required Label: Clean API with required label prop for the header
- Flexible Content: Accept any content through AccordionContent wrapper
- Smooth Animations: CSS-based transitions for expand/collapse
- Visual Variants: Default, bordered, and minimal styles
- Keyboard Accessible: Full keyboard navigation support
- Responsive Design: Adapts to all screen sizes
- Independent State: Each accordion manages its own open/closed state
Basic Usage
import Accordion from "@/components/block/Accordion.astro"
import AccordionContent from "@/components/block/AccordionContent.astro"
<Accordion label="What is this accordion?">
<AccordionContent>
<p>This is a reusable accordion component that creates individual collapsible content sections.</p>
</AccordionContent>
</Accordion>
Examples
Basic Accordion
An accordion is a UI component that allows users to expand and collapse content sections. It’s perfect for organizing information in a compact, scannable format while keeping the interface clean.
With Rich Content
Accordion content can include rich formatting and multiple elements:
- Lists and bullet points
- Links: Jump to examples
- Inline code:
const example = true;
You can also include code blocks:
function toggleAccordion() {
console.log("Accordion toggled!");
}
Bordered Variant
This accordion uses the bordered variant, which provides a clean design with borders but no background fill.
Perfect for secondary content areas or when you want a more subtle visual presence.
Minimal Variant
The minimal variant uses ultra-clean design with just bottom borders.
Ideal for text-heavy content where maximum focus should be on the content itself.
Default Expanded
This accordion starts in an expanded state by default. Users can still collapse it by clicking the header.
Useful for highlighting important information or the most commonly accessed content.
Multiple Accordions
Answer to the first question. Each accordion operates independently.
Answer to the second question. You can mix different variants.
Answer to the third question. Each has its own state management.
Props
Accordion Props
Prop | Type | Default | Description |
---|---|---|---|
label | string | Required | The accordion header text |
variant | 'default' | 'bordered' | 'minimal' | 'default' | Visual style variant |
className | string | '' | Additional CSS classes |
id | string | Auto-generated | Unique identifier |
defaultExpanded | boolean | false | Whether to start expanded |
AccordionContent Props
Prop | Type | Default | Description |
---|---|---|---|
className | string | '' | Additional CSS classes |
Component Architecture
The new Accordion architecture consists of two components:
Accordion Component
- Purpose: Provides the header/trigger and container structure
- Required Props:
label
(the header text) - Behavior: Manages expand/collapse state and animations
- Content: Uses
<slot />
to accept child content
AccordionContent Component
- Purpose: Wraps and styles the accordion content
- Content: Uses
<slot />
to accept any content type - Styling: Provides consistent padding, typography, and spacing
- Rich Content: Supports text, lists, links, code blocks, and more
Visual Variants
Default Variant
Clean card-based design with subtle shadows and backgrounds:
<Accordion label="Default Style" variant="default">
<AccordionContent>
<p>Card-style design with background colors and subtle borders.</p>
</AccordionContent>
</Accordion>
Bordered Variant
Minimal design with borders but no background fill:
<Accordion label="Bordered Style" variant="bordered">
<AccordionContent>
<p>Clean borders without background colors for a subtle presence.</p>
</AccordionContent>
</Accordion>
Minimal Variant
Ultra-clean design with just bottom borders:
<Accordion label="Minimal Style" variant="minimal">
<AccordionContent>
<p>Simple divider lines for maximum content focus.</p>
</AccordionContent>
</Accordion>
Advanced Usage
Custom Styling
<Accordion
label="Custom Styled Accordion"
className="custom-accordion"
variant="default"
>
<AccordionContent className="custom-content">
<p>Content with custom styling applied.</p>
</AccordionContent>
</Accordion>
Complex Content Layouts
<Accordion label="Complex Content Example">
<AccordionContent>
<div class="content-grid">
<div class="content-section">
<h4>Section 1</h4>
<p>Detailed information here...</p>
</div>
<div class="content-section">
<h4>Section 2</h4>
<ul>
<li>Feature A</li>
<li>Feature B</li>
</ul>
</div>
</div>
</AccordionContent>
</Accordion>
Dynamic Content
---
// Fetch from API or CMS
const dynamicContent = await fetch('/api/content/123')
.then(res => res.text());
---
<Accordion label="Dynamic Content">
<AccordionContent>
<div set:html={dynamicContent} />
</AccordionContent>
</Accordion>
With Custom IDs
<Accordion
label="Getting Started Guide"
id="getting-started"
defaultExpanded
>
<AccordionContent>
<p>This accordion has a custom ID for direct linking and analytics.</p>
</AccordionContent>
</Accordion>
Building Accordion Groups
Since each accordion is independent, you can create custom groups:
Simple Group
<div class="accordion-group">
<Accordion label="Question 1">
<AccordionContent>
<p>Answer 1</p>
</AccordionContent>
</Accordion>
<Accordion label="Question 2">
<AccordionContent>
<p>Answer 2</p>
</AccordionContent>
</Accordion>
</div>
Mixed Variants Group
<div class="mixed-accordion-group">
<Accordion label="Important Info" variant="default" defaultExpanded>
<AccordionContent>
<p>Highlighted important information.</p>
</AccordionContent>
</Accordion>
<Accordion label="Additional Details" variant="bordered">
<AccordionContent>
<p>Secondary information with bordered style.</p>
</AccordionContent>
</Accordion>
<Accordion label="Technical Notes" variant="minimal">
<AccordionContent>
<p>Technical details with minimal styling.</p>
</AccordionContent>
</Accordion>
</div>
Accessibility Features
- Keyboard Navigation: Full keyboard support with Tab and Enter keys
- ARIA Attributes: Proper
aria-expanded
andaria-controls
attributes - Screen Reader Support: Semantic HTML structure for assistive technologies
- Focus Management: Clear focus indicators and logical tab order
- Unique IDs: Automatic generation of unique IDs for proper ARIA relationships
Interactive Behavior
Each accordion includes built-in JavaScript for:
- Smooth Animations: Expand/collapse transitions with proper height calculations
- Keyboard Navigation: Full keyboard support with Tab and Enter keys
- Independent State: Each accordion manages its own open/closed state
- Hover Effects: Visual feedback on hover and focus states
- Event Handling: Proper event management for accessibility
Responsive Design
- Desktop: Full layout with optimal spacing and typography
- Tablet: Adjusted spacing and font sizes for medium screens
- Mobile: Optimized padding and touch-friendly interactions
- Touch Friendly: Larger touch targets and proper spacing for mobile devices
Content Guidelines
AccordionContent Styling
The AccordionContent component provides consistent styling for:
- Typography: Proper line heights and font sizes
- Lists: Styled
<ul>
,<ol>
, and<li>
elements - Links: Consistent link styling with hover effects
- Code: Inline
<code>
and block<pre>
styling - Spacing: Consistent margins and padding for all content types
Rich Content Support
<Accordion label="Rich Content Example">
<AccordionContent>
<h4>Subheading</h4>
<p>Regular paragraph with <strong>bold text</strong> and <em>italic text</em>.</p>
<ul>
<li>List item one</li>
<li>List item two with <a href="#link">a link</a></li>
</ul>
<blockquote>
<p>A quoted section for emphasis.</p>
</blockquote>
<pre><code>// Code block example
const accordion = new Accordion();
accordion.toggle();</code></pre>
</AccordionContent>
</Accordion>
Performance Considerations
- CSS Animations: Uses CSS transitions instead of JavaScript animations
- Individual State: Each accordion manages only its own state
- Lazy Height Calculation: Height calculated only when needed
- Minimal JavaScript: Lightweight script with no external dependencies
- Independent Loading: Each accordion can be rendered independently
Common Use Cases
Documentation Sections
<div class="docs-section">
<Accordion label="Installation">
<AccordionContent>
<p>Install the package using your preferred package manager:</p>
<pre><code>npm install your-package
# or
yarn add your-package</code></pre>
</AccordionContent>
</Accordion>
<Accordion label="Configuration">
<AccordionContent>
<p>Add the following to your configuration file:</p>
<pre><code>// config.js
export default {
// your configuration
};</code></pre>
</AccordionContent>
</Accordion>
</div>
Feature Showcase
<div class="feature-showcase">
<Accordion label="🚀 Performance" variant="default">
<AccordionContent>
<p>Lightning-fast performance with optimized rendering and minimal JavaScript.</p>
<ul>
<li>CSS-based animations</li>
<li>Lazy loading support</li>
<li>Minimal bundle size</li>
</ul>
</AccordionContent>
</Accordion>
<Accordion label="🎨 Customization" variant="bordered">
<AccordionContent>
<p>Extensive customization options for any design system.</p>
</AccordionContent>
</Accordion>
</div>
Settings Panel
<div class="settings-panel">
<Accordion label="Account Settings" defaultExpanded>
<AccordionContent>
<p>Manage your profile, password, and account preferences.</p>
</AccordionContent>
</Accordion>
<Accordion label="Privacy Settings">
<AccordionContent>
<p>Control who can see your information and how it's used.</p>
</AccordionContent>
</Accordion>
</div>
Best Practices
- Label Writing: Use clear, specific labels that describe the content
- Content Structure: Organize content logically within AccordionContent
- Visual Hierarchy: Use consistent styling and spacing
- Performance: Avoid heavy content in accordions that start expanded
- Accessibility: Test keyboard navigation and screen reader compatibility
Migration from Old Accordion
If you’re migrating from the old multi-item accordion:
Old Usage (No longer supported)
// ❌ Old way - no longer works
<Accordion items={[
{ question: "Q1", answer: "A1" },
{ question: "Q2", answer: "A2" }
]} />
New Usage
// ✅ New way - individual accordions
<div class="accordion-group">
<Accordion label="Q1">
<AccordionContent>
<p>A1</p>
</AccordionContent>
</Accordion>
<Accordion label="Q2">
<AccordionContent>
<p>A2</p>
</AccordionContent>
</Accordion>
</div>
For FAQ Use Cases
Use the FAQSection component instead:
// ✅ For FAQ pages, use FAQSection
import FAQSection from "@/components/block/FAQSection.astro"
<FAQSection faqs={[
{ question: "Q1", answer: "A1" },
{ question: "Q2", answer: "A2" }
]} />
Comparison with FAQ Section
Feature | Accordion | FAQ Section |
---|---|---|
Purpose | Individual collapsible items | Complete FAQ page section |
Usage | Single accordion per component | Multiple FAQs in one component |
Header | Just the accordion label | Includes title, tagline, description |
Content | Flexible content via AccordionContent | Text-based FAQ answers |
Layout | Individual item control | Managed group layout |
Use Cases | Custom layouts, mixed content | FAQ pages, help sections |
Choose Accordion when you need individual control over collapsible items, and FAQ Section when you need a complete FAQ implementation with multiple questions.