Accordion
Collapses a list of headings so readers can scan first and expand only what they need.
When to Use
Variants
Default
Divider-separated rows. Opening one panel closes the others.
Workshopr is a platform for workshop facilitators featuring a content library and AI Facilitation Coach.
The AI Coach provides real-time guidance during your workshops, helping you adapt to group dynamics and keep sessions on track.
Yes! Workshopr offers a free tier with access to the content library. Premium features are available with Pro and Team plans.
<?= ws_accordion([
['title' => 'Question 1', 'content' => 'Answer 1', 'open' => true],
['title' => 'Question 2', 'content' => 'Answer 2'],
]) ?>Bordered
Each panel becomes a discrete card. Use when the accordion sits directly on a page background rather than inside a container.
Create an account and explore the content library to find exercises and workshops for your next session.
Use the Planner to drag and drop exercises into a timeline, then export your agenda.
The Coach provides real-time support during your workshop with intervention suggestions and timing guidance.
<?= ws_accordion($items, ['variant' => 'bordered']) ?>
Multiple open
Set multiple: true when panels are independent and readers may want to compare them side by side.
This accordion allows multiple panels to be open simultaneously.
Click to open without closing the other panels.
All three can be open at the same time.
<?= ws_accordion($items, ['multiple' => true]) ?>
With icons
A per-item Material icon adds category context. Keep icons consistent across the set — a mix of iconed and plain rows reads as an error.
A 5-day process for answering critical business questions through design, prototyping, and testing.
A meeting for the team to reflect on what went well, what didn’t, and what to improve.
<?= ws_accordion([
['title' => 'Design Sprint', 'content' => '...', 'icon' => 'design_services'],
['title' => 'Retrospective', 'content' => '...', 'icon' => 'history'],
], ['variant' => 'bordered']) ?>States
| State | Behavior |
|---|---|
| Collapsed | Panel carries hidden; trigger reports aria-expanded="false". The content stays in the DOM. |
| Open | Item gains .is-open, hidden is removed, aria-expanded="true". Fires a bubbling ws-accordion-open event. |
| Closing | Fires ws-accordion-close. In single-open mode, closing the siblings happens before the new panel opens. |
| Disabled | Item gains .is-disabled and the trigger's click handler returns early. Set per item, not per accordion. |
Real-World Usage
The pricing FAQ pattern: single-open (so the page length stays stable), bordered (it sits on the page background), first item closed so the reader sees the full question list before committing to one.
Yes. Every plan permits commercial facilitation. Team plans add shared collections so co-facilitators work from the same library.
Nothing is deleted. Plans above the free tier's limit become read-only until you either archive some or upgrade again.
We do — get in touch with your organisation details and we'll sort it out.
<?= ws_accordion($faqItems, [
'id' => 'pricing-faq',
'variant' => 'bordered',
]) ?>Options
Accordion options
| Option | Type | Default | Purpose |
|---|---|---|---|
id | string | 'ws-accordion-' . uniqid() | Container ID. Auto-generated, but set it explicitly if you need to target the accordion from JS. |
variant | string | 'default' | default | bordered | flush |
size | string | 'md' | sm | md | lg — drives trigger padding and title size |
multiple | bool | false | Allow several panels open at once. Emitted as data-multiple and read by the JS at init. |
class | string | '' | Additional CSS classes |
Item options
| Option | Type | Default | Purpose |
|---|---|---|---|
title | string | '' | Trigger text. Write it as the question the reader is actually asking. |
content | string | '' | Panel body. Rendered as HTML, so wrap prose in <p>. |
open | bool | false | Initially expanded. In single-open mode, marking more than one leaves them all open until the first interaction. |
icon | string | null | Material icon name, rendered before the title |
disabled | bool | false | Prevents toggling |
Accessibility
Structurally this follows the WAI-ARIA Accordion pattern. The wiring below is what the component actually ships — see the gap note at the end.
| Concern | Behavior |
|---|---|
| ARIA | Triggers carry aria-expanded (kept in sync by wsAccordionOpen/Close) and aria-controls pointing at their panel. Panels are role="region" with aria-labelledby back to the trigger. |
| Keyboard | Tab moves between triggers; Enter and Space toggle the focused panel. Both come free from using real <button> elements — no JS key handling is involved. |
| Focus | Focus stays on the trigger when a panel opens, so the next Tab enters the revealed content. Collapsed panels use hidden, which removes their contents from the tab order. |
| Screen readers | Collapsed content stays in the DOM under hidden rather than being destroyed, so the accordion's structure is traversable and the expanded/collapsed state is announced. |
| Reduced motion | No JS-driven animation; the panel show/hide is an attribute toggle. Nothing to suppress. |
wsAccordionInit() binds click only. This page previously documented those keys as working; they never were. Tab-based navigation is conformant, so this is an enhancement rather than a WCAG failure.
Tokens
| Token | Used for |
|---|---|
--gray-50 | Trigger hover fill |
--gray-200 | Item dividers and the bordered variant's outline |
--gray-400 | Chevron in its resting state |
--mainsite-primary | Leading icon accent |
--radius-xl | Bordered-variant card corners |
--text-default / --text-dark | Title and body text |
--text-h3 / --text-body / --text-ui / --text-small / --text-meta | Type scale across the size modifiers |
--font-body / --font-semibold | Body face and trigger weight |
--transition-base / --transition-fast | Chevron rotation and hover fill |
CSS Classes
| Class | Purpose |
|---|---|
.ws-accordion | Outer container. Auto-initialised on DOMContentLoaded. |
.ws-accordion--bordered | Card-per-panel variant |
.ws-accordion--flush | Borderless variant |
.ws-accordion--sm / --lg | Size modifiers (md is the default and emits nothing) |
.ws-accordion__item | Panel wrapper |
.ws-accordion__item.is-open | Expanded state — the hook JS toggles |
.ws-accordion__item.is-disabled | Disabled state |
.ws-accordion__trigger | The <button> header |
.ws-accordion__icon | Optional leading icon |
.ws-accordion__title | Heading text |
.ws-accordion__arrow | Expand/collapse chevron |
.ws-accordion__panel | Collapsible role="region" container |
.ws-accordion__content | Padding wrapper inside the panel |
Files
| File | Purpose |
|---|---|
includes/components/helpers.php | ws_accordion() helper function |
includes/components/accordion.php | Template — markup and ARIA wiring |
includes/components/components.css | Styles (.ws-accordion rules) |
includes/components/components.js | wsAccordionInit(), wsAccordionOpen/Close/Toggle() and the auto-init |