Accordion Simple

Accordion
GSAP
JS
CMS
Last Updated: Nov 7, 2025
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
	document.querySelectorAll(".accordion-1_component").forEach((component, listIndex) => {
		if (component.hasAttribute("data-accordion-1")) return;
		component.setAttribute("data-accordion-1", "");
    
		let previousIndex = null, closeFunctions = [];

		component.querySelectorAll(".accordion-1_item").forEach((card, cardIndex) => {
			const button = card.querySelector(".accordion-1_button");
			const content = card.querySelector(".accordion-1_content");
			if (!button || !content) return;

			const id = `accordion-1-${listIndex}-${cardIndex}`;
			button.id = `${id}-button`;
			button.setAttribute("aria-controls", `${id}-content`);
			button.setAttribute("aria-expanded", "false");
			content.id = `${id}-content`;
			content.style.display = "none";
			content.setAttribute("aria-labelledby", button.id);

			gsap.context(() => {
				const tl = gsap.timeline({
					paused: true,
					defaults: { duration: 0.3, ease: "power1.inOut" },
					onComplete: () => (typeof ScrollTrigger !== "undefined" ? ScrollTrigger.refresh() : null),
					onReverseComplete: () => (typeof ScrollTrigger !== "undefined" ? ScrollTrigger.refresh() : null)
				});
				tl.set(content, { display: "block" });
				tl.fromTo(content, { height: 0 }, { height: "auto" });
				tl.fromTo(".accordion-1_icon", { rotate: 0 }, { rotate: -180 }, "<");

				function close() {
					if (button.ariaExpanded === "false") return;
					button.ariaExpanded = "false";
					previousIndex = null;
					tl.reverse().invalidate();
				}
				closeFunctions[cardIndex] = close;

				function open(instant) {
					if (previousIndex !== null && previousIndex !== cardIndex) closeFunctions[previousIndex]?.();
					previousIndex = cardIndex;
					button.ariaExpanded = "true";
					instant ? tl.progress(1) : tl.play();
				}

				button.addEventListener("click", () => button.ariaExpanded === "true" ? close() : open());
			}, card);
		});
	});
});
</script>