Building a simple Accordion with Alpine.js in Statamic

If you're using Statamic, adding interactive UI components without heavy JavaScript frameworks is easy thanks to Alpine.js.
In this tutorial, we’ll build a simple accordion step by step — with smooth height animation using the Alpine x-collapse plugin.
✅ Step 1: Install Alpine.js
If you're using Vite (Laravel style), install Alpine first:
npm install alpinejsThen in:
import Alpine from 'alpinejs'
window.Alpine = Alpine
Alpine.start()✅ Step 2: Install the x-collapse Plugin
Now install the collapse plugin:
npm install @alpinejs/collapseThen update your site.js:
import Alpine from 'alpinejs'
import collapse from '@alpinejs/collapse'
Alpine.plugin(collapse)
window.Alpine = Alpine
Alpine.start()If you're not bundling, include it via CDN in your layout:
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script defer src="https://unpkg.com/@alpinejs/collapse@3.x.x/dist/cdn.min.js"></script>Make sure this is inside your main layout file (e.g. resources/views/layout.antlers.html).
✅ Step 3: Create Your Accordion Markup
Now create your accordion in a Statamic view.
<div x-data="{ open: null }" class="max-w-4xl mx-auto w-full divide-y divide-gray-200">
<!-- Item 1 -->
<div class="py-4">
<button @click="open === 1 ? open = null : open = 1"
class="flex justify-between gap-4 w-full text-left font-semibold cursor-pointer">
<span>What is Statamic?</span>
<span x-text="open === 1 ? '-' : '+'"></span>
</button>
<div x-show="open === 1" x-collapse class="text-gray-600">
<div class="pt-4">
Statamic is a modern flat-file CMS built on Laravel.
</div>
</div>
</div>
<!-- Item 2 -->
<div class="py-4">
<button @click="open === 2 ? open = null : open = 2"
class="flex justify-between gap-4 w-full text-left font-semibold cursor-pointer">
<span>What is Alpine.js?</span>
<span x-text="open === 2 ? '-' : '+'"></span>
</button>
<div x-show="open === 2" x-collapse class="text-gray-600">
<div class="pt-4">
Alpine.js is a lightweight JavaScript framework for adding interactivity.
</div>
</div>
</div>
</div>
✅ Step 4: Include the Partial in a Page
Inside your page template:
{{ partial:accordion }}That’s it 🎉
You now have a working accordion with smooth height animation.
🧠 How It Works
x-data
Initializes Alpine state:
x-data="{ open: null }"This means no accordion item is open by default.
@click
Toggles the open item:
open === 1 ? open = null : open = 1
If item 1 is open → close it.
If it's closed → open it.
x-show
Controls visibility:
x-show="open === 1"Only shows the content if open equals 1.
x-collapse ✅ (New Addition)
This is the important upgrade.
Instead of using x-transition, we use:
x-collapseThe collapse plugin automatically animates the element’s height from 0px to auto.
✔ No manual transition classes
✔ No height calculations
✔ Smooth open/close animation
✔ Cleaner markup
🔥 Bonus: Make It Reusable with Statamic Data
If your accordion items come from a Bard field or Replicator:
<div x-data="{ open: null }" class="max-w-4xl mx-auto w-full divide-y divide-gray-200">
{{ accordion_items }}
<div class="py-4">
<button
@click="open === {{ index }} ? open = null : open = {{ index }}"
class="flex justify-between gap-4 w-full text-left font-semibold cursor-pointer"
>
<span>{{ title }}</span>
<span x-text="open === {{ index }} ? '-' : '+'"></span>
</button>
<div
x-show="open === {{ index }}"
x-collapse
class="mt-2 text-gray-600"
>
<div class="pt-4">
{{ content }}
</div>
</div>
</div>
{{ /accordion_items }}
</div>
Now it works dynamically with your CMS content.
🎯 Final Result
You now have:
✅ Lightweight accordion
✅ No heavy JS framework
✅ Fully CMS-driven
✅ Smooth height animation with x-collapse
✅ Clean and reusable
