Membuat Accordion di Vue 3 dan Bootstrap 5

Published 18 Agustus 2022

Komponen Accordion sangat berguna dan dapat ditemukan di banyak library seperti Bootstrap, Tailwind, Foundation atau yang lainnya. Accordion biasanya di gunakan untuk FAQ Content, Feature Comapartions, atau content yang kompleks tapi bisa di sederhanakan. Untuk kasus kali ini kita akan membuat accordion menggunakan Vue JS 3 dengan Bootstrap 5.

Let’s build it!

Pertama kita buat terlebih dahulu accordion wrapper nya untuk menampung semua kebutuhannya seperti accordion title dan accordion content.

Accordion Wrapper

<template>
  <div class="as-accordion">
    <slot />
  </div>
</template>
<script setup>
import { inject, onMounted, ref, provide } from "vue";
let AccordionIndex = ref(false);
const AccordionStatus = inject("AccordionStatus");
const visible = () => {
  return AccordionIndex == AccordionStatus.active;
};
provide("visible", visible);
const toggleAccordion = () => {
  if (visible()) {
    AccordionStatus.active = null;
  } else {
    AccordionStatus.active = AccordionIndex;
  }
};
provide("toggleAccordion", toggleAccordion);
onMounted(() => {
  AccordionIndex = AccordionStatus.count++;
});
</script>
<style lang="scss">
@use '@/scss/components/accordion';
</style>

Kemudian kita buat accordion title untuk menampilkan accordion content yang kita sembunyikan. Untuk mempercantik nya kita menggunakan font icon custom. Jika belum tertarik untuk membuat font icon sendiri bisa dilihat disini.

Accordion Title

<template>
  <div
    @click="toggleAccordion"
    class="as-accordion__header"
    :class="{ 'as-accordion__header--open': visible() }"
  >
    <slot />
    <i
      class="as-icon-blue"
      :class="{
        'as-icon-arrow-top': visible(),
        'as-icon-arrow-down': !visible(),
      }"
    ></i>
  </div>
</template>
<script setup>
  import {inject} from "vue"; const visible = inject("visible"); const
  toggleAccordion = inject("toggleAccordion");
</script>

Setelah menambahkan accordion wrapper dan accordion title kemudian kita akan membuat accordion content.

Accordion Content

<template>
  <div class="as-accordion__body" v-if="visible()">
    <div class="as-accordion__content">
      <slot />
    </div>
  </div>
</template>
<script setup>
  import {inject} from "vue"; const visible = inject("visible");
</script>

Struktur accordion sudah mulai selesai, untuk lebih menarik kita tambahkan styling berikut.

:root {
  --as-color-white: #fff;
  --as-color-divider: #d9dde3;
  --as-color-gray-soft: #f3f4f6;
}

.as-accordion {
  margin-bottom: 0.875rem;

  &__header {
    align-items: center;
    background: var(--as-color-white);
    border-bottom: 1px solid var(--as-color-divider);
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    padding: 1.5rem;

    &--open {
      background: var(--as-color-gray-soft);
      border-radius: 1rem 1rem 0 0;
      border-bottom: none;
    }
  }

  &__body {
    background: var(--as-color-white);
    border: 2px solid var(--as-color-gray-soft);
    border-top: 0;
    border-radius: 0 0 1rem 1rem;
    padding-left: 1.5rem;
    padding-right: 1.5rem;
  }

  &__content {
    padding-top: 1.5rem;
    padding-bottom: 1.5rem;
  }
}

Ketika semuanya sudah selesai bagaimana cara implemntasi accordion yang sudah kita buat tadi. Mari kita lihat hasilnya seperti ini

<template>
  <div class="container">
    <div class="row align-items-center">
      <AsAccordion>
        <AsAccordionTitle>
          <h3 class="as-text-16-bold">
            Lorem ipsum dolor sit amet consectetur.
          </h3>
        </AsAccordionTitle>
        <AsAccordionContent>
          <p class="as-text-14 as-color-secondary">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime
            mollitia fugit accusantium earum temporibus! Incidunt blanditiis
            cumque quisquam eius ipsa magnam optio, nulla inventore maxime sunt,
            reprehenderit est quia laudantium!
          </p>
        </AsAccordionContent>
      </AsAccordion>

      <AsAccordion>
        <AsAccordionTitle>
          <h3 class="as-text-16-bold">
            Lorem ipsum dolor sit amet consectetur adipisicing.
          </h3>
        </AsAccordionTitle>
        <AsAccordionContent>
          <p class="as-text-14 as-color-secondary">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime
            mollitia fugit accusantium earum temporibus! Incidunt blanditiis
            cumque quisquam eius ipsa magnam optio, nulla inventore maxime sunt,
            reprehenderit est quia laudantium!
          </p>
        </AsAccordionContent>
      </AsAccordion>

      <AsAccordion>
        <AsAccordionTitle>
          <h3 class="as-text-16-bold">Lorem ipsum dolor sit amet.</h3>
        </AsAccordionTitle>
        <AsAccordionContent>
          <p class="as-text-14 as-color-secondary">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime
            mollitia fugit accusantium earum temporibus! Incidunt blanditiis
            cumque quisquam eius ipsa magnam optio, nulla inventore maxime sunt,
            reprehenderit est quia laudantium!
          </p>
        </AsAccordionContent>
      </AsAccordion>
    </div>
  </div>
</template>

<script setup>
import AsAccordion from "./AsAccordion.vue";
import AsAccordionTitle from "./AsAccordionTitle.vue";
import AsAccordionContent from "./AsAccordionContent.vue";
import { provide, reactive, ref, watch } from "vue";
let AccordionStatus = reactive({
  count: 0,
  active: null,
});
provide("AccordionStatus", AccordionStatus);
</script>

Oke akhirnya pembuatan accordion menggunakan Vue 3 dan Bootstrap 5 sudah selesai. Bisa kalian gunakan untuk FAQ Content atau kebutuhan content lainnya.

Terimakasih!