Accordions let users expand and collapse sections of content. They help users navigate material quickly and allow the UI designer to include large amounts of information in limited space.


About this component:

  • uses <button> element to make it more accessible (works with keyboard)
  • uses Alpine JS template tag
  • accordion elements autoclose

Example client projects using accordions:

  • Handle: @accordion--default
  • Tags: alpine
  • Preview:
  • Filesystem Path: components/02-components/accordion/accordion.hbs
<div class="mx-8 mt-8" x-data="{
    faqs: [
        {
        question: 'Question 1',
        answer: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores iure quas laudantium dicta impedit, est id delectus molestiae deleniti enim nobis rem et nihil.',
        isOpen: false,
        },
        {
        question: 'Question 2',
        answer: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eligendi cumque, nulla harum aspernatur veniam ullam provident neque temporibus autem itaque odit.',
        isOpen: false,
        },
        {
        question: 'Question 3',
        answer: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eligendi cumque, nulla harum aspernatur veniam ullam provident neque temporibus autem itaque odit.',
        isOpen: false,
        },
    ]
    }">

    <h2 class="text-2xl font-bold">FAQs</h2>

    <template x-for="faq in faqs" :key="faq.question">

        <div class="mt-6 text-lg leading-loose">

            <button class="flex items-center justify-between w-full border-b border-gray-400 cursor-pointer" @click="faq.isOpen = !faq.isOpen">

                <h2 class="text-xl font-bold text-gray-800" x-text="faq.question"></h2>

                <svg x-show="!faq.isOpen" class="fill-current" viewBox="0 0 24 24" width="24" height="24">
                    <path class="heroicon-ui" d="M12 22a10 10 0 110-20 10 10 0 010 20zm0-2a8 8 0 100-16 8 8 0 000 16zm1-9h2a1 1 0 010 2h-2v2a1 1 0 01-2 0v-2H9a1 1 0 010-2h2V9a1 1 0 012 0v2z" />
                </svg>
                <svg x-show="faq.isOpen" class="fill-current" viewBox="0 0 24 24" width="24" height="24">
                    <path class="heroicon-ui" d="M12 22a10 10 0 110-20 10 10 0 010 20zm0-2a8 8 0 100-16 8 8 0 000 16zm4-8a1 1 0 01-1 1H9a1 1 0 010-2h6a1 1 0 011 1z" />
                </svg>

            </button>

            <div class="mt-2 text-sm text-gray-700" x-show.transition.in.duration.100ms="faq.isOpen" @click.away="faq.isOpen = false">
                <p x-text="faq.answer"></p>
            </div>
        </div>

    </template>

</div>

<script type="module" src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js"></script>
<script nomodule src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine-ie11.min.js" defer></script>
<div class="mx-8 mt-8" x-data="{
    faqs: [
        {
        question: 'Question 1',
        answer: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores iure quas laudantium dicta impedit, est id delectus molestiae deleniti enim nobis rem et nihil.',
        isOpen: false,
        },
        {
        question: 'Question 2',
        answer: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eligendi cumque, nulla harum aspernatur veniam ullam provident neque temporibus autem itaque odit.',
        isOpen: false,
        },
        {
        question: 'Question 3',
        answer: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eligendi cumque, nulla harum aspernatur veniam ullam provident neque temporibus autem itaque odit.',
        isOpen: false,
        },
    ]
    }">

    <h2 class="text-2xl font-bold">FAQs</h2>

    <template x-for="faq in faqs" :key="faq.question">

        <div class="mt-6 text-lg leading-loose">
            
            <button class="flex items-center justify-between w-full border-b border-gray-400 cursor-pointer"
                @click="faq.isOpen = !faq.isOpen">

                <h2 class="text-xl font-bold text-gray-800" x-text="faq.question"></h2>

                <svg x-show="!faq.isOpen" class="fill-current" viewBox="0 0 24 24" width="24" height="24">
                    <path class="heroicon-ui"
                        d="M12 22a10 10 0 110-20 10 10 0 010 20zm0-2a8 8 0 100-16 8 8 0 000 16zm1-9h2a1 1 0 010 2h-2v2a1 1 0 01-2 0v-2H9a1 1 0 010-2h2V9a1 1 0 012 0v2z" />
                </svg>
                <svg x-show="faq.isOpen" class="fill-current" viewBox="0 0 24 24" width="24" height="24">
                    <path class="heroicon-ui"
                        d="M12 22a10 10 0 110-20 10 10 0 010 20zm0-2a8 8 0 100-16 8 8 0 000 16zm4-8a1 1 0 01-1 1H9a1 1 0 010-2h6a1 1 0 011 1z" />
                </svg>

                {{!-- <svg x-show.transition.in.duration.200ms="!faq.isOpen" class="w-8 h-8 fill-current"
                    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="M12 6v6m0 0v6m0-6h6m-6 0H6" />
                </svg>
                
                <svg x-show.transition.in.duration.200ms="faq.isOpen" class="w-8 h-8 fill-current"
                    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="M18 12H6" />
                </svg> --}}

            </button>

            <div class="mt-2 text-sm text-gray-700" x-show.transition.in.duration.100ms="faq.isOpen" @click.away="faq.isOpen = false">
                <p x-text="faq.answer"></p>
            </div>
        </div>

    </template>

</div>

<script type="module" src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js"></script>
<script nomodule src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine-ie11.min.js" defer></script>
/* No context defined. */