--- type: ai-agent-documentation version: 2.0 component: Accordion status: stable audience: ai-coding-agents-only human-readable: false category: layout framework-support: - vanilla: true - react: true - vue: true - angular: true - svelte: true --- # Component: Accordion DEFINITION: The Accordion component displays a list of collapsible content panels. It is used to organize and hide large amounts of content, revealing it only when needed. ## Installation ```bash npm install @pm7/core ``` ### CSS & JavaScript Import REQUIRED: Import both the CSS and the main JavaScript file. ```javascript // ES modules import '@pm7/core/dist/pm7.css'; import '@pm7/core'; // Imports and initializes all components // HTML ``` ## Required Structure An Accordion consists of a main container (`.pm7-accordion`) with `data-pm7-accordion`, and multiple accordion items. Each item contains a trigger (`.pm7-accordion-trigger`) and a content panel (`.pm7-accordion-content`). ```html

Accordion content goes here.

``` ### Structural Rules - **ALWAYS**: The main container MUST have `data-pm7-accordion`. - **ALWAYS**: Each accordion item MUST contain exactly one `.pm7-accordion-trigger` and one `.pm7-accordion-content`. - **ALWAYS**: The `.pm7-accordion-trigger` MUST have an `aria-controls` attribute matching the `id` of its corresponding `.pm7-accordion-content`. - **ALWAYS**: The `.pm7-accordion-content` MUST contain an inner `div` with class `.pm7-accordion-content-inner`. - **NEVER**: Place content directly inside `.pm7-accordion-content` without the `.pm7-accordion-content-inner` wrapper. ## JavaScript API ### Initialization Initialization is automatic when `@pm7/core` is imported. For dynamically added components, re-initialization is required. ```javascript // For components added after initial page load window.PM7.init(); ``` ### Instance Access ```javascript const element = document.querySelector('[data-pm7-accordion]'); const instance = element.PM7Accordion; ``` ### Methods | Method | Parameters | Return Type | Description | |---|---|---|---| | `open` | `index: number` | `void` | Opens the accordion item at the specified index. | | `close` | `index: number` | `void` | Closes the accordion item at the specified index. | | `toggle` | `index: number` | `void` | Toggles the accordion item at the specified index. | | `openAll` | `(none)` | `void` | Opens all accordion items (only if `multiple` option is true). | | `closeAll` | `(none)` | `void` | Closes all accordion items. | | `destroy` | `(none)` | `void` | Removes all event listeners and cleans up the instance. | ### Options Options can be set via `data-pm7-accordion-options` attribute on the main container or passed during manual initialization. | Option | Type | Default | Description | |---|---|---|---| | `multiple` | `boolean` | `false` | If `true`, allows multiple accordion items to be open simultaneously. | | `initialOpen` | `number[]` | `[]` | An array of indices of items to be open on initialization. | ### Events | Event | When | Detail | Bubbles | |---|---|---|---|---| | `pm7:accordion:open` | After an item opens | `{ index: number, item: HTMLElement }` | YES | | `pm7:accordion:close`| After an item closes | `{ index: number, item: HTMLElement }` | YES | ## Attributes See /docs/ATTRIBUTES.md for cross-component attribute relationships. | Attribute | Component(s) | Values | Required | Effect | |---|---|---|---|---| | `data-pm7-accordion` | Accordion | presence | YES | Initializes Accordion component. | | `data-pm7-accordion-options` | Accordion | JSON string: `{"multiple": boolean, "initialOpen": number[]}` | NO | Configures Accordion behavior. | | `data-state` | Accordion | `open`, `closed` | AUTO | Managed by JS to reflect component's open/closed state. | | `aria-controls` | Accordion | ID of controlled element | YES | Links a control to the element it controls. | | `aria-expanded` | Accordion | `true`, `false` | AUTO | Indicates whether a collapsible element is currently expanded or collapsed. | ## CSS Classes | Class | Required | When | Effect | |---|---|---|---|---| | `.pm7-accordion` | YES | ALWAYS on the main container | Base styling for the accordion. | | `.pm7-accordion-item` | YES | ALWAYS for each collapsible section | Styles an individual accordion section. | | `.pm7-accordion-trigger` | YES | ALWAYS for the button that toggles content | Styles the clickable header of an accordion item. | | `.pm7-accordion-content` | YES | ALWAYS for the collapsible content area | Styles the hidden/shown content panel. | | `.pm7-accordion-content-inner` | YES | ALWAYS inside `.pm7-accordion-content` | Provides inner padding and ensures smooth transitions. | | `.pm7-accordion-icon` | YES | ALWAYS inside `.pm7-accordion-trigger` | Styles the chevron icon, rotates on open/close. | | `.pm7-accordion--flush` | NO | For a borderless, flush appearance | Removes outer borders and shadows. | | `.pm7-accordion--no-separator` | NO | To remove separators between items | Removes the bottom border from accordion items. | ## Patterns ### Pattern: Basic Accordion ```html

Content for section 1.

Content for section 2.

``` ### Pattern: Multiple Open Items Add `data-pm7-accordion-options='{"multiple": true}'` to the main container. ```html
``` ### Pattern: Initial Open Items Add `data-pm7-accordion-options='{"initialOpen": [0, 2]}' ` to the main container to open the first and third items. ```html
``` ### Pattern: Programmatic Control ```javascript const accordionElement = document.querySelector('[data-pm7-accordion]'); const accordionInstance = accordionElement.PM7Accordion; // Open the first item accordionInstance.open(0); // Close the second item accordionInstance.close(1); // Toggle the third item accordionInstance.toggle(2); // Listen for open event accordionElement.addEventListener('pm7:accordion:open', (e) => { console.log(`Item at index ${e.detail.index} opened.`); }); ``` ## Anti-Patterns ### NEVER: Omit `aria-controls` or `id` ```html
Content
The trigger cannot be programmatically linked to its content, breaking functionality and accessibility.
Content
``` ### NEVER: Manually control `display` or `height` ```css /* NEVER */ .pm7-accordion-content { display: block !important; } /* BECAUSE */ PM7 manages the visibility and height transitions via JavaScript and `data-state` attributes. Manual control will break animations and state. /* INSTEAD */ // Let the component handle it. ``` ### NEVER: Nest Accordions directly ```html
This can lead to conflicting event listeners, keyboard navigation issues, and unexpected visual behavior. // Consider using a single accordion with more detailed content, or a different component for nested information. ``` ## React Integration > **📚 Framework Integration Guide**: For Vue, Angular, and other framework integrations, see the comprehensive [Framework Integration Guide](https://raw.githubusercontent.com/patrickmast/pm7-ui/main/README-Framework-Integration.md) ### ⚠️ State Management in React PM7-UI accordions have their own internal state management. When using with React, you need to synchronize states properly: 1. **Controlled vs Uncontrolled**: PM7 accordions manage their own open/closed state internally 2. **Event Listeners**: Use PM7 events to sync with React state when needed 3. **ARIA Attributes**: Let PM7 handle `aria-expanded` and `data-state` updates ### Basic React Implementation ```jsx function AccordionExample() { // PM7 will manage the open/closed state internally useEffect(() => { window.PM7?.initFramework(); }, []); return (

Content for section 1.

); } ``` ### Syncing with React State If you need to track which items are open in React state: ```jsx function ControlledAccordion() { const [openItems, setOpenItems] = useState([]); useEffect(() => { window.PM7?.initFramework(); // Listen for PM7 accordion events const handleOpen = (e) => { const index = e.detail.index; setOpenItems(prev => [...prev, index]); }; const handleClose = (e) => { const index = e.detail.index; setOpenItems(prev => prev.filter(i => i !== index)); }; document.addEventListener('pm7:accordion:open', handleOpen); document.addEventListener('pm7:accordion:close', handleClose); return () => { document.removeEventListener('pm7:accordion:open', handleOpen); document.removeEventListener('pm7:accordion:close', handleClose); }; }, []); return (

Open items: {openItems.join(', ')}

{/* Accordion items */}
); } ``` ### Dynamic Accordion Items When rendering accordion items dynamically: ```jsx function DynamicAccordion({ items }) { useEffect(() => { // Re-initialize when items change window.PM7?.init(); }, [items]); return (
{items.map((item, index) => (
{item.content}
))}
); } ``` ### Programmatic Control from React ```jsx function AccordionWithControls() { const accordionRef = useRef(null); const openAll = () => { const accordion = accordionRef.current?.PM7Accordion; if (accordion) { // Get all items and open them const itemCount = accordionRef.current.querySelectorAll('.pm7-accordion-item').length; for (let i = 0; i < itemCount; i++) { accordion.open(i); } } }; return ( <>
{/* Accordion items */}
); } ``` ### Key Points for React: - Let PM7 manage the accordion state internally - Use event listeners to sync with React state when needed - Don't manually update `aria-expanded` or `data-state` attributes - Call `PM7.init()` when dynamically adding new accordion items - Use the PM7Accordion API for programmatic control ## Rules ### ALWAYS - **ALWAYS**: Ensure each `.pm7-accordion-trigger` is a `

PM7-UI is a framework-agnostic UI component library built with pure CSS and vanilla JavaScript. It provides a complete set of UI components that work with any JavaScript framework without requiring framework-specific wrappers.

You can install PM7-UI via npm: npm install @pm7/core. Then, import the CSS and JavaScript files into your project.

Yes, PM7-UI is framework-agnostic. You can use it with any JavaScript framework by simply including the CSS and JavaScript files. The components auto-initialize based on their data attributes.

```