[Vuejs]-Vue js bootstrap add animation while collapse

5👍

You can use Vue’s List Transitions (the <transition-group> tag).

Change the sublist ul to:

<ul :id="x.id" class="collapse list-unstyled show">
  <transition-group name="list">
    <li v-for="y in (activeItemId === itemIndex  && isActive ? x.children : [])" :key="y.name">
      <a>{{y.name}}</a>
    </li>
  </transition-group>
</ul>

Mainly instead of hiding the <ul> we are changing the v-for array to/from empty. Notice I also changed the il‘s keys, as you were using an invalid prop.

And add the following CSS for the transitions:

.list-enter {
  opacity: 0;
}
.list-enter-active {
  animation: slide-in .5s ease-out forwards;
}
.list-leave-to, .list-leave-active {
  opacity: 0;
  animation: slide-out .5s ease-out forwards;
}
@keyframes slide-in {
  from { height: 0; } to { height: 40px; }
}
@keyframes slide-out {
  from { height: 40px; } to { height: 0; }
}

Updated JSFiddle here. Demo below.

new Vue({
  el: '#app',
  methods: {
    setActiveItemId(itemIndex) {
      if (itemIndex === this.activeItemId) {
        this.activeItemId = ''
        return
      }
      this.activeItemId = itemIndex
    }
  },
  data() {
    return {
      message: 'Hello Vue.js!',
      activeItemId: '',
      sideBar: [{
          name: "Dashboard",
          url: "/dashboard",
          icon: "ti-world",
          children: [{
              name: "Buttons",
              url: "/components/buttons",
              icon: "fa-book",
            },
            {
              name: "Social Buttons",
              url: "/components/social-buttons",
              icon: "icon-puzzle",
            }
          ]
        },
        {
          name: "Components",
          url: "/components",
          icon: "ti-pencil-alt",
          children: [{
              name: "Buttons",
              url: "/components/buttons",
              icon: "fa-book",
            },
            {
              name: "Social Buttons",
              url: "/components/social-buttons",
              icon: "icon-puzzle",
            }
          ]
        },
        {
          name: "Validation",
          url: "/components",
          icon: "ti-pencil-alt",
          children: [{
              name: "Buttons",
              url: "/components/buttons",
              icon: "fa-book",
            },
            {
              name: "Social Buttons",
              url: "/components/social-buttons",
              icon: "icon-puzzle",
            }
          ]
        }
      ]
    }
  },
  computed: {
    isActive() {
      return this.activeItemId !== ''
    }
  }
})
.collapse.show {
  display: block;
}

.collapse {
  display: none;
}

.list-unstyled {
  padding-left: 0;
  list-style: none;
}

.collapse.list-unstyled {
  padding-left: 15px;
}

nav.side-navbar {
  background: #fff;
  min-width: 250px;
  max-width: 250px;
  color: #000;
  -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
  box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
  z-index: 999;
}

nav.side-navbar ul a:hover {
  background: orange;
  color: #fff !important;
}

nav.side-navbar ul a {
  padding: 10px 15px;
  text-decoration: none;
  display: block;
  font-weight: 300;
  border-left: 4px solid transparent;
}

.list-enter {
  opacity: 0;
}
.list-enter-active {
  animation: slide-in .5s ease-out forwards;
}
.list-leave-to, .list-leave-active {
  opacity: 0;
  animation: slide-out .5s ease-out forwards;
}
@keyframes slide-in {
  from { height: 0; } to { height: 40px; }
}
@keyframes slide-out {
  from { height: 40px; } to { height: 0; }
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />

<script src="https://unpkg.com/vue"></script>

<div id="app">
  <nav class="side-navbar">
    <ul class="list-unstyled">
      <li>
        <a>
          <i class="ti-home"></i>Home</a>
      </li>
      <li v-for="(x, itemIndex) in sideBar" :key="itemIndex">
        <a @click="setActiveItemId(itemIndex)">
          <i class="fa" :class="x.icon"></i>{{x.name}}
        </a>
        <ul :id="x.id" class="collapse list-unstyled show">
          <transition-group name="list">
            <li v-for="y in (activeItemId === itemIndex  && isActive ? x.children : [])" :key="y.name">
              <a>{{y.name}}</a>
            </li>
          </transition-group>
        </ul>
      </li>
    </ul>
  </nav>
</div>

-1👍

There’s easier solution, try adding this piece of css to your styles.

.show {
  transition: width 0.5s, height 0.5s, transform 0.5s;
}

Leave a comment