<div id="app">
  <accordion>
    <div slot="title">タイトル</div>
    <div class="content" slot="content">
      <p>ここに内容</p>
    </div>
  </accordion>
  <accordion>
    <div slot="title">タイトル</div>
    <div class="content" slot="content">
      <p>ここに内容</p>
    </div>
  </accordion>
  <accordion>
    <div slot="title">タイトル</div>
    <div class="content" slot="content">
      <p>ここに内容</p>
    </div>
  </accordion>
</div>
.accordion {
  max-width: 70%;
  margin: 10px auto;
}

.title:hover {
  cursor: pointer;
  opacity: 0.8;
}

.title {
  padding: 15px;
  margin-bottom: 10px;
  background-color: #eee;
  border-radius: 5px;
}

.title > div {
  display: inline-block;
  font-weight: bold;
}

.title i {
  float: right;
  line-height: 1.3;
}

.content {
  padding: 0 15px;
  margin-bottom: 10px;
}

.open-enter-active {
    animation: open 0.2s;
}

.open-leave-active {
    animation: open 0.2s linear reverse;
}

@keyframes open {
  0% {
    opacity: 0;
    transform: translateY(-5px);
  }

  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.rotate-enter-active {
    animation: rotate 0.2s linear;
}

@keyframes rotate {
    0% {
        transform: rotate(180deg);
    }
}
Vue.component("accordion", {
  template: `
    <div class="accordion">
      <div class="title" @click="open()">
        <slot name="title"></slot>
        <transition name="rotate" mode="out-in">
          <i class="fas fa-chevron-up" v-if="isOpen" key="rotate1"></i>
          <i class="fas fa-chevron-down" v-else key="rotate2"></i>
        </transition>
      </div>
      <transition name="open">
        <div class="accordion-content" v-if="isOpen">
          <slot name="content"></slot>
        </div>
      </transition>
    </div>`,
  data: function () {
    return {
      isOpen: false
    }
  },
  methods: {
    open: function () {
      this.isOpen = !this.isOpen;
    }
  }
});
new Vue({
  el: "#app"
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.8/vue.min.js