@preline/accordion
v4.2.0
Published
Preline UI is an open-source set of prebuilt UI components based on the utility-first Tailwind CSS framework.
Downloads
22,047
Readme
Accordion
Build vertically collapsing accordions in combination with Accordion JavaScript plugin.
Contents
Overview
The Accordion component allows you to create collapsible content sections that can be expanded or collapsed by clicking on toggle buttons. It supports multiple accordion items within a group, with options for keeping items open, ensuring at least one item stays open, and treeview mode for hierarchical structures.
Key Features:
- Multiple accordion items in a single group
- Programmatic control via JavaScript API
- Event system for lifecycle hooks
- Treeview mode support
- Accessibility attributes (ARIA) built-in
Installation
To get started, install Accordion plugin via npm, else you can skip this step if you are already using Preline UI as a package.
npm i @preline/accordionCSS
Use @source to register the plugin's JavaScript path for Tailwind CSS scanning, then @import the plugin's CSS files into your Tailwind CSS file.
@import "tailwindcss";
/* @preline/accordion */
@source "../node_modules/@preline/accordion/*.js";
@import "./node_modules/@preline/accordion/variants.css";
@import "./node_modules/@preline/accordion/theme.css";JavaScript
Include the JavaScript that powers the interactive elements near the end of your </body> tag:
<script src="./node_modules/@preline/accordion/index.js"></script>Manual Initialization
Use the non-auto entry if you need manual initialization. In this mode, automatic initialization on page load is not included, so the component should be initialized explicitly.
<script type="module">
import HSAccordion from "@preline/accordion/non-auto.mjs";
new HSAccordion(document.querySelector("#accordion"));
</script>Via Bundler
When using a bundler (Vite, webpack, etc.), import the plugin directly as an ES module.
@preline/accordion is the auto-init entry: it scans the DOM and initializes matching elements automatically.
import "@preline/accordion";@preline/accordion/non-auto is the manual entry: use it when you want explicit control over when initialization happens, either via autoInit() or by creating a specific instance yourself.
import HSAccordion from "@preline/accordion/non-auto";
HSAccordion.autoInit();
// Or initialize a specific element manually
const el = document.querySelector("#accordion");
if (el) new HSAccordion(el);TypeScript
This package ships with TypeScript type definitions. No additional @types/ package is needed.
Basic usage
The following example demonstrates the minimal HTML structure required for an accordion component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. The example shows three accordion items within a group, with the first item open by default.
<div class="hs-accordion-group">
<div class="hs-accordion active" id="hs-unstyled-heading-one">
<button class="hs-accordion-toggle" aria-expanded="true" aria-controls="hs-unstyled-collapse-one">
Accordion #1
</button>
<div id="hs-unstyled-collapse-one" class="hs-accordion-content overflow-hidden transition-[height] duration-300" role="region" aria-labelledby="hs-unstyled-heading-one">
Accordion content that expands and collapses when the toggle button is clicked.
</div>
</div>
<div class="hs-accordion" id="hs-unstyled-heading-two">
<button class="hs-accordion-toggle" aria-expanded="false" aria-controls="hs-unstyled-collapse-two">
Accordion #2
</button>
<div id="hs-unstyled-collapse-two" class="hs-accordion-content hidden overflow-hidden transition-[height] duration-300" role="region" aria-labelledby="hs-unstyled-heading-two">
Accordion content that expands and collapses when the toggle button is clicked.
</div>
</div>
<div class="hs-accordion" id="hs-unstyled-heading-three">
<button class="hs-accordion-toggle" aria-expanded="false" aria-controls="hs-unstyled-collapse-three">
Accordion #3
</button>
<div id="hs-unstyled-collapse-three" class="hs-accordion-content hidden overflow-hidden transition-[height] duration-300" role="region" aria-labelledby="hs-unstyled-heading-three">
Accordion content that expands and collapses when the toggle button is clicked.
</div>
</div>
</div>Structure Requirements:
hs-accordion-group: Required wrapper container for all accordion itemshs-accordion: Required container for each accordion itemhs-accordion-toggle: Required button element that triggers expand/collapsehs-accordion-content: Required container for collapsible content- Unique
idattributes for each accordion item and its content - Proper ARIA attributes (
aria-expanded,aria-controls,aria-labelledby,role="region")
Initial State:
- To have an accordion item open by default, add the
activeclass to thehs-accordionelement - For closed items, add the
hiddenclass to thehs-accordion-contentelement
Configuration Options
Data Attributes
Data attributes are added directly to HTML elements to configure accordion behavior.
| Attribute | Target Element | Type | Default | Description |
| --- | --- | --- | --- | --- |
| data-hs-accordion-always-open | hs-accordion-group | boolean attribute | false (absent) | When present (boolean attribute), accordion items stay open when another item is opened. By default, opening one item closes others. Presence of attribute = true, absence = false. |
Example:
<!-- Boolean attribute: presence = true, absence = false -->
<div class="hs-accordion-group" data-hs-accordion-always-open>
<!-- Multiple items can be open simultaneously -->
</div>CSS Classes (Modifiers)
CSS class modifiers use Tailwind-style syntax with -- prefix to control behavior.
| Class Modifier | Target Element | Values | Default | Description |
| --- | --- | --- | --- | --- |
| --stop-propagation:* | hs-accordion-toggle | "true" | "false" | "false" | When "true", interrupts event propagation when toggle button is clicked. Useful when accordion is nested inside clickable elements. |
| --keep-one-open:* | hs-accordion-group | "true" | "false" | "false" | When "true", ensures at least one accordion item remains open at all times. Prevents closing the last open item. |
Example:
<div class="hs-accordion-group --keep-one-open:true">
<!-- At least one item will always be open -->
</div>
<button class="hs-accordion-toggle --stop-propagation:true">
<!-- Click event won't bubble up -->
</button>Required CSS Classes
These classes define the structure and must be present for the accordion to function.
| Class | Required On | Purpose |
| --- | --- | --- |
| hs-accordion-group | Container wrapper | Groups multiple accordion items together |
| hs-accordion | Each accordion item container | Identifies an individual accordion item |
| hs-accordion-toggle | Button element | The clickable element that expands/collapses content |
| hs-accordion-content | Content container | The collapsible content area |
Optional CSS Classes
| Class | Required On | Purpose |
| --- | --- | --- |
| hs-accordion-treeview-root | Parent container | When present, activates treeview mode for hierarchical accordion structures |
| hs-accordion-selectable | Elements inside treeview | When treeview mode is active, elements with this class become selectable |
Treeview Mode Example:
<div class="hs-accordion-treeview-root">
<div class="hs-accordion-group">
<div class="hs-accordion">
<button class="hs-accordion-toggle">Parent</button>
<div class="hs-accordion-content">
<div class="hs-accordion-selectable">Selectable item</div>
</div>
</div>
</div>
</div>JavaScript API
The HSAccordion object is available in the global window object after the plugin is loaded.
Instance Methods
These methods are called on an accordion instance.
| Method | Parameters | Return Type | Description |
| --- | --- | --- | --- |
| show() | None | boolean | Opens the collapsed accordion item. Returns false if item is already open, true otherwise. If other items are open and always-open is not set, they will be closed. |
| hide() | None | boolean | Collapses the currently open accordion item. Returns false if item is already closed or if keep-one-open is enabled and this is the last open item, true otherwise. |
| destroy() | None | void | Destroys the accordion instance, removes all generated markup, classes, and event listeners. Use when removing accordion from DOM. |
Static Methods
These methods are called directly on the HSAccordion class.
| Method | Parameters | Return Type | Description |
| --- | --- | --- | --- |
| HSAccordion.getInstance(target, isInstance) | target: HTMLElement \| string (CSS selector)isInstance: boolean (optional) | { id: string \| number, element: HSAccordion } \| HTMLElement \| null | Returns the accordion instance or element associated with the target. If isInstance is true, returns collection item object { id, element } where element is the HSAccordion instance. If isInstance is false or omitted, returns the DOM element (HTMLElement). Returns null if accordion instance is not found. |
| HSAccordion.show(target) | target: HSAccordion \| HTMLElement \| string (CSS selector) | void | Opens the accordion item identified by target. Accepts an accordion instance, DOM element, or CSS selector string. Static alternative to instance show() method. Only opens if item is not already open. |
| HSAccordion.hide(target) | target: HSAccordion \| HTMLElement \| string (CSS selector) | void | Closes the accordion item identified by target. Accepts an accordion instance, DOM element, or CSS selector string. Static alternative to instance hide() method. Only closes if item is open and keep-one-open allows it. |
Usage Examples
Example 1: Using instance methods (public API)
// Create a new accordion instance
const accordion = new HSAccordion(document.querySelector('#hs-accordion'));
const showBtn = document.querySelector('#hs-show-btn');
const hideBtn = document.querySelector('#hs-hide-btn');
// Open accordion programmatically
showBtn.addEventListener('click', () => {
accordion.show();
});
// Close accordion programmatically
hideBtn.addEventListener('click', () => {
accordion.hide();
});Example 2: Using static methods
const showBtn = document.querySelector('#hs-show-btn');
const hideBtn = document.querySelector('#hs-hide-btn');
// Open accordion using static method (no instance needed)
showBtn.addEventListener('click', () => {
HSAccordion.show('#hs-accordion');
});
// Close accordion using static method
hideBtn.addEventListener('click', () => {
HSAccordion.hide('#hs-accordion');
});Example 3: Getting instance and using methods (recommended pattern)
// Get the accordion instance
const instance = HSAccordion.getInstance('#hs-accordion', true);
if (instance) {
const { element } = instance; // element is the HSAccordion instance
const showBtn = document.querySelector('#hs-show-btn');
// Use instance methods
showBtn.addEventListener('click', () => {
element.show();
});
// Clean up when removing from DOM
function removeAccordion() {
element.destroy();
}
}Example 4: Destroying accordion instance
const instance = HSAccordion.getInstance('#hs-accordion', true);
if (instance) {
const { element } = instance;
const removeBtn = document.querySelector('#hs-remove-btn');
removeBtn.addEventListener('click', () => {
// Clean up before removing from DOM
element.destroy();
// Now safe to remove the element
document.querySelector('#hs-accordion').remove();
});
}Events
Accordion instances emit events that can be listened to for lifecycle hooks and custom behavior.
| Event Name | When Fired | Callback Parameter | Description |
| --- | --- | --- | --- |
| on:beforeOpen | Before accordion item opens | HTMLElement (current accordion element) | Fires immediately before the accordion item starts opening. Can be used to cancel or modify behavior. |
| on:open | After accordion item opens | HTMLElement (current accordion element) | Fires after the accordion item has fully opened. Use for post-open actions like loading content. |
| on:beforeClose | Before accordion item closes | HTMLElement (current accordion element) | Fires immediately before the accordion item starts closing. Can be used to cancel or modify behavior. |
| on:close | After accordion item closes | HTMLElement (current accordion element) | Fires after the accordion item has fully closed. Use for cleanup or state updates. |
Event Usage Example
// Get accordion instance
const instance = HSAccordion.getInstance('#hs-accordion', true);
if (instance) {
const { element } = instance;
// Listen to open event
element.on('open', (accordionElement) => {
console.log('Accordion opened:', accordionElement);
// Perform actions after accordion opens
// e.g., load content, update UI, track analytics
});
// Listen to close event
element.on('close', (accordionElement) => {
console.log('Accordion closed:', accordionElement);
// Perform cleanup or state updates
});
// Listen to beforeOpen event (can be used to cancel)
element.on('beforeOpen', (accordionElement) => {
console.log('About to open:', accordionElement);
// Can add conditional logic here
});
// Listen to beforeClose event (can be used to cancel)
element.on('beforeClose', (accordionElement) => {
console.log('About to close:', accordionElement);
// Can add conditional logic here
});
}Common Patterns
Pattern 1: Multiple Open Items
Allow multiple accordion items to be open simultaneously.
<div class="hs-accordion-group" data-hs-accordion-always-open>
<div class="hs-accordion" id="hs-item-first">
<button class="hs-accordion-toggle">Item 1</button>
<div class="hs-accordion-content hidden">Content 1</div>
</div>
<div class="hs-accordion" id="hs-item-second">
<button class="hs-accordion-toggle">Item 2</button>
<div class="hs-accordion-content hidden">Content 2</div>
</div>
</div>Pattern 2: Always Keep One Open
Ensure at least one item is always open.
<div class="hs-accordion-group --keep-one-open:true">
<div class="hs-accordion active" id="hs-item-first">
<button class="hs-accordion-toggle">Item 1</button>
<div class="hs-accordion-content">Content 1</div>
</div>
<div class="hs-accordion" id="hs-item-second">
<button class="hs-accordion-toggle">Item 2</button>
<div class="hs-accordion-content hidden">Content 2</div>
</div>
</div>Pattern 3: Programmatic Control
Control accordion from external buttons.
<div class="hs-accordion-group">
<div class="hs-accordion" id="hs-accordion-first">
<button class="hs-accordion-toggle">Content</button>
<div class="hs-accordion-content hidden">Content here</div>
</div>
</div>
<button id="hs-open-all">Open All</button>
<button id="hs-close-all">Close All</button>
<script>
const instance = HSAccordion.getInstance('#hs-accordion-first', true);
if (instance) {
const { element } = instance;
document.querySelector('#hs-open-all').addEventListener('click', () => {
element.show();
});
document.querySelector('#hs-close-all').addEventListener('click', () => {
element.hide();
});
}
</script>License
Copyright (c) 2026 Preline Labs.
Licensed under the MIT License.
