# Accordion Component Usage
## Overview
The accordion component displays collapsible content panels for presenting information in a limited space. It uses native HTML `<details>` and `<summary>` elements for maximum accessibility and no JavaScript dependency for basic functionality. Optional JavaScript enables enhanced features like single-panel mode.
## JavaScript Requirements
### Required Scripts (Optional for Enhanced Features)
```html
<!-- Include for enhanced accordion features -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/basecoat-css@latest/dist/basecoat.cdn.min.css">
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@latest/dist/js/basecoat.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/basecoat-css@latest/dist/js/accordion.min.js" defer></script>
```
## HTML Structure
### Basic Accordion
```html
<div class="accordion divide-y">
<details>
<summary>Is it accessible?</summary>
<div class="accordion-content">
<p>Yes. It adheres to the WAI-ARIA design pattern.</p>
</div>
</details>
<details>
<summary>Is it styled?</summary>
<div class="accordion-content">
<p>Yes. It comes with default styles that match the other components' aesthetics.</p>
</div>
</details>
<details>
<summary>Is it animated?</summary>
<div class="accordion-content">
<p>Yes. It's animated by default, but you can disable it if you prefer.</p>
</div>
</details>
</div>
```
### Pre-opened Item
```html
<div class="accordion divide-y">
<details open>
<summary>This panel is open by default</summary>
<div class="accordion-content">
<p>This content is visible when the page loads.</p>
</div>
</details>
<details>
<summary>This panel starts closed</summary>
<div class="accordion-content">
<p>Click to reveal this content.</p>
</div>
</details>
</div>
```
## Implementation Examples
### FAQ Section
```html
<section class="max-w-2xl mx-auto">
<h2 class="text-2xl font-bold mb-6">Frequently Asked Questions</h2>
<div class="accordion divide-y border rounded-lg">
<details>
<summary>What payment methods do you accept?</summary>
<div class="accordion-content">
<p>We accept all major credit cards (Visa, MasterCard, American Express), PayPal, and bank transfers for enterprise customers.</p>
</div>
</details>
<details>
<summary>Can I cancel my subscription anytime?</summary>
<div class="accordion-content">
<p>Yes, you can cancel your subscription at any time. Your access will continue until the end of your current billing period.</p>
</div>
</details>
<details>
<summary>Do you offer refunds?</summary>
<div class="accordion-content">
<p>We offer a 30-day money-back guarantee for all new subscriptions. Contact our support team to request a refund.</p>
</div>
</details>
<details>
<summary>How do I contact support?</summary>
<div class="accordion-content">
<p>You can reach our support team through:</p>
<ul class="list-disc list-inside mt-2">
<li>Email: support@example.com</li>
<li>Live chat: Available 24/7</li>
<li>Phone: 1-800-EXAMPLE</li>
</ul>
</div>
</details>
</div>
</section>
```
### Settings Accordion
```html
<div class="accordion divide-y">
<details>
<summary class="flex items-center gap-3">
<svg class="size-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
Profile Settings
</summary>
<div class="accordion-content space-y-4">
<div class="grid gap-3">
<label for="display-name" class="label">Display Name</label>
<input type="text" id="display-name" class="input" value="John Doe">
</div>
<div class="grid gap-3">
<label for="bio" class="label">Bio</label>
<textarea id="bio" class="textarea" rows="3">Software developer</textarea>
</div>
<button class="btn">Save Changes</button>
</div>
</details>
<details>
<summary class="flex items-center gap-3">
<svg class="size-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect width="20" height="14" x="2" y="5" rx="2"></rect>
<path d="M2 10h20"></path>
</svg>
Notification Preferences
</summary>
<div class="accordion-content space-y-4">
<div class="flex items-center justify-between">
<span>Email Notifications</span>
<input type="checkbox" role="switch" class="input" checked>
</div>
<div class="flex items-center justify-between">
<span>Push Notifications</span>
<input type="checkbox" role="switch" class="input">
</div>
<div class="flex items-center justify-between">
<span>SMS Alerts</span>
<input type="checkbox" role="switch" class="input">
</div>
</div>
</details>
<details>
<summary class="flex items-center gap-3">
<svg class="size-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect width="18" height="11" x="3" y="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
Security
</summary>
<div class="accordion-content space-y-4">
<div class="flex items-center justify-between">
<div>
<p class="font-medium">Two-Factor Authentication</p>
<p class="text-sm text-muted-foreground">Add an extra layer of security</p>
</div>
<button class="btn-outline">Enable</button>
</div>
<div class="flex items-center justify-between">
<div>
<p class="font-medium">Change Password</p>
<p class="text-sm text-muted-foreground">Last changed 30 days ago</p>
</div>
<button class="btn-outline">Update</button>
</div>
</div>
</details>
</div>
```
### Single-Expand Mode (JavaScript Required)
```html
<div class="accordion divide-y" data-single-expand="true" id="single-accordion">
<details>
<summary>Panel 1</summary>
<div class="accordion-content">
<p>When one panel opens, others close automatically.</p>
</div>
</details>
<details>
<summary>Panel 2</summary>
<div class="accordion-content">
<p>This ensures only one panel is visible at a time.</p>
</div>
</details>
<details>
<summary>Panel 3</summary>
<div class="accordion-content">
<p>Useful when content is lengthy or for cleaner UX.</p>
</div>
</details>
</div>
<script>
// Single-expand accordion behavior
const accordion = document.getElementById('single-accordion');
accordion.addEventListener('click', function(e) {
const summary = e.target.closest('summary');
if (!summary) return;
const details = summary.parentElement;
const allDetails = accordion.querySelectorAll('details');
// Close other panels when opening a new one
allDetails.forEach(item => {
if (item !== details && item.open) {
item.open = false;
}
});
});
</script>
```
### Nested Accordion
```html
<div class="accordion divide-y border rounded-lg">
<details>
<summary>Getting Started</summary>
<div class="accordion-content">
<div class="accordion divide-y ml-4">
<details>
<summary>Installation</summary>
<div class="accordion-content">
<p>Run <code>npm install basecoat-css</code></p>
</div>
</details>
<details>
<summary>Configuration</summary>
<div class="accordion-content">
<p>Add the CSS to your project and configure Tailwind.</p>
</div>
</details>
</div>
</div>
</details>
<details>
<summary>Components</summary>
<div class="accordion-content">
<div class="accordion divide-y ml-4">
<details>
<summary>Buttons</summary>
<div class="accordion-content">
<p>Various button styles and variants.</p>
</div>
</details>
<details>
<summary>Forms</summary>
<div class="accordion-content">
<p>Input, select, checkbox, and more.</p>
</div>
</details>
</div>
</div>
</details>
</div>
```
## JavaScript Events
### Toggle Event Handling
```javascript
const accordion = document.querySelector('.accordion');
accordion.addEventListener('toggle', function(e) {
const details = e.target;
if (details.open) {
console.log('Panel opened:', details.querySelector('summary').textContent);
} else {
console.log('Panel closed:', details.querySelector('summary').textContent);
}
}, true);
```
### Programmatic Control
```javascript
// Open a specific panel
function openPanel(index) {
const panels = document.querySelectorAll('.accordion details');
if (panels[index]) {
panels[index].open = true;
}
}
// Close all panels
function closeAllPanels() {
const panels = document.querySelectorAll('.accordion details');
panels.forEach(panel => panel.open = false);
}
// Open all panels
function openAllPanels() {
const panels = document.querySelectorAll('.accordion details');
panels.forEach(panel => panel.open = true);
}
```
### Animation with JavaScript
```javascript
// Smooth closing animation
document.querySelectorAll('.accordion details').forEach(details => {
const content = details.querySelector('.accordion-content');
details.addEventListener('click', function(e) {
if (e.target.closest('summary')) {
e.preventDefault();
if (this.open) {
// Closing
content.style.maxHeight = content.scrollHeight + 'px';
requestAnimationFrame(() => {
content.style.maxHeight = '0';
});
setTimeout(() => {
this.open = false;
content.style.maxHeight = '';
}, 300);
} else {
// Opening
this.open = true;
content.style.maxHeight = '0';
requestAnimationFrame(() => {
content.style.maxHeight = content.scrollHeight + 'px';
});
setTimeout(() => {
content.style.maxHeight = '';
}, 300);
}
}
});
});
```
## Accessibility Guidelines
### Built-in Accessibility
The `<details>` and `<summary>` elements provide built-in accessibility:
- Screen readers announce the expanded/collapsed state
- Keyboard navigation works automatically
- Focus management is handled by the browser
### Keyboard Navigation
- **Enter/Space**: Toggle the focused panel
- **Tab**: Move focus between panels
### Enhanced Accessibility
```html
<div class="accordion divide-y" role="region" aria-label="Frequently Asked Questions">
<details>
<summary id="faq-1">What is Basecoat?</summary>
<div class="accordion-content" aria-labelledby="faq-1">
<p>Basecoat is a CSS component library built with Tailwind CSS.</p>
</div>
</details>
</div>
```
## Best Practices
### When to Use Accordions
- FAQ sections
- Settings panels with multiple categories
- Navigation menus with submenus
- Product feature lists
- Long content that can be chunked
### When to Avoid Accordions
- Critical content that shouldn't be hidden
- Very short content (use tabs instead)
- Sequential content (use steps/stepper)
- Single item (just show the content)
### Content Guidelines
- Keep summary text concise and descriptive
- Front-load important words in summaries
- Use consistent grammar across all summaries
- Consider the expanded state content length
### Visual Guidelines
- Use clear visual indicators for expand/collapse state
- Maintain consistent spacing
- Consider adding icons to summaries
- Ensure adequate touch targets on mobile
## Styling Variants
### Bordered Accordion
```html
<div class="accordion divide-y border rounded-lg">
<details class="px-4">
<summary>Panel with border</summary>
<div class="accordion-content">Content here</div>
</details>
</div>
```
### Card-Style Accordion
```html
<div class="space-y-4">
<details class="border rounded-lg">
<summary class="p-4 bg-muted/50 rounded-t-lg">Card Panel 1</summary>
<div class="accordion-content p-4">Content for panel 1</div>
</details>
<details class="border rounded-lg">
<summary class="p-4 bg-muted/50 rounded-t-lg">Card Panel 2</summary>
<div class="accordion-content p-4">Content for panel 2</div>
</details>
</div>
```
### Flush Accordion (No Borders)
```html
<div class="accordion">
<details>
<summary class="py-4 border-b">Flush Panel 1</summary>
<div class="accordion-content py-4">Content here</div>
</details>
<details>
<summary class="py-4 border-b">Flush Panel 2</summary>
<div class="accordion-content py-4">Content here</div>
</details>
</div>
```