Skip to content

Accordion

Accordion.astro

---
const { faqsList } = Astro.props;
interface Faq {
question: string;
answer: string;
}
---
<div class="faq-accordion max-w-4xl mx-auto">
<dl class="space-y-4">
{ faqsList.map((faq: Faq, index: number) => (
<div
class="py-8 px-5 rounded-md border bg-white focus-within:border-secondary"
>
<dt class="text-lg">
<button
class="text-left w-full flex justify-between items-start focus:outline-none"
aria-controls="{`faq-${index}`}"
aria-expanded="false"
id="{`faq-button-${index}`}"
>
<span class="font-medium text-[22px]"> {faq.question} </span>
<span class="ml-6 h-7 flex items-center">
<svg
class="h-6 w-6 transform transition-transform duration-300 ease-in-out"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 9l-7 7-7-7"
/>
</svg>
</span>
</button>
</dt>
<dd
class="mt-2 overflow-hidden transition-all duration-300 ease-in-out max-h-0"
id="{`faq-${index}`}"
aria-labelledby="{`faq-button-${index}`}"
>
<p class="text-base pt-3" set:html="{faq.answer}" />
</dd>
</div>
)) }
</dl>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
const faqButtons = document.querySelectorAll(
".faq-accordion dt button",
);
let currentlyOpenContent: HTMLElement | null = null;
faqButtons.forEach((button) => {
button.addEventListener("click", () => {
const content = button.parentElement!
.nextElementSibling as HTMLElement;
const isExpanded =
button.getAttribute("aria-expanded") === "true"; // Close the currently open item if it's not the one being clicked
if (currentlyOpenContent && currentlyOpenContent !== content) {
const openButton =
currentlyOpenContent.previousElementSibling!.querySelector(
"button",
)!;
openButton.setAttribute("aria-expanded", "false");
openButton
.querySelector("svg")!
.classList.remove("rotate-180");
currentlyOpenContent.style.maxHeight = "0";
} // Toggle the clicked item
if (!isExpanded) {
button.setAttribute("aria-expanded", "true");
content.style.maxHeight = content.scrollHeight + "px";
currentlyOpenContent = content;
} else {
button.setAttribute("aria-expanded", "false");
content.style.maxHeight = "0";
currentlyOpenContent = null;
}
button.querySelector("svg")!.classList.toggle("rotate-180");
});
});
});
</script>