Vue js bootstrap add animation while collapse
Posted By: Anonymous
I am making a side bar menu with collapse show/hide. With my current css the collapse is not smooth and it seems force full or looks some weird.
I wanted a slide with smooth transition when the item is being closed. But here in my case what’s happening is when some item is already open and next item is clicked(for open). There it looks like toggle is being forcefully and it does not seems smooth collapsing of the list.
What could be the better approach for this please suggest some better ways.
I don’t know whether my approach is correct or I am missing something here?
new Vue({_x000D_
el: '#app',_x000D_
methods: {_x000D_
setActiveItemId(itemIndex) {_x000D_
if (itemIndex === this.activeItemId) {_x000D_
this.activeItemId = ''_x000D_
return_x000D_
}_x000D_
this.activeItemId = itemIndex_x000D_
}_x000D_
},_x000D_
data() {_x000D_
return {_x000D_
message: 'Hello Vue.js!',_x000D_
activeItemId: '',_x000D_
sideBar: [{_x000D_
name: "Dashboard",_x000D_
url: "/dashboard",_x000D_
icon: "ti-world",_x000D_
children: [{_x000D_
name: "Buttons",_x000D_
url: "/components/buttons",_x000D_
icon: "fa-book",_x000D_
},_x000D_
{_x000D_
name: "Social Buttons",_x000D_
url: "/components/social-buttons",_x000D_
icon: "icon-puzzle",_x000D_
}_x000D_
]_x000D_
},_x000D_
{_x000D_
name: "Components",_x000D_
url: "/components",_x000D_
icon: "ti-pencil-alt",_x000D_
children: [{_x000D_
name: "Buttons",_x000D_
url: "/components/buttons",_x000D_
icon: "fa-book",_x000D_
},_x000D_
{_x000D_
name: "Social Buttons",_x000D_
url: "/components/social-buttons",_x000D_
icon: "icon-puzzle",_x000D_
}_x000D_
]_x000D_
},_x000D_
{_x000D_
name: "Validation",_x000D_
url: "/components",_x000D_
icon: "ti-pencil-alt",_x000D_
children: [{_x000D_
name: "Buttons",_x000D_
url: "/components/buttons",_x000D_
icon: "fa-book",_x000D_
},_x000D_
{_x000D_
name: "Social Buttons",_x000D_
url: "/components/social-buttons",_x000D_
icon: "icon-puzzle",_x000D_
}_x000D_
]_x000D_
}_x000D_
]_x000D_
}_x000D_
},_x000D_
computed: {_x000D_
isActive() {_x000D_
return this.activeItemId !== ''_x000D_
}_x000D_
}_x000D_
})
_x000D_
.collapse.show {_x000D_
display: block;_x000D_
}_x000D_
_x000D_
.collapse {_x000D_
display: none;_x000D_
}_x000D_
_x000D_
.list-unstyled {_x000D_
padding-left: 0;_x000D_
list-style: none;_x000D_
}_x000D_
_x000D_
.collapse.list-unstyled {_x000D_
padding-left: 15px;_x000D_
}_x000D_
_x000D_
nav.side-navbar {_x000D_
background: #fff;_x000D_
min-width: 250px;_x000D_
max-width: 250px;_x000D_
color: #000;_x000D_
-webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);_x000D_
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);_x000D_
z-index: 999;_x000D_
}_x000D_
_x000D_
nav.side-navbar ul a:hover {_x000D_
background: orange;_x000D_
color: #fff !important;_x000D_
}_x000D_
_x000D_
nav.side-navbar ul a {_x000D_
padding: 10px 15px;_x000D_
text-decoration: none;_x000D_
display: block;_x000D_
font-weight: 300;_x000D_
border-left: 4px solid transparent;_x000D_
}
_x000D_
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>_x000D_
_x000D_
<script src="https://unpkg.com/vue"></script>_x000D_
_x000D_
<div id="app">_x000D_
<nav class="side-navbar">_x000D_
<ul class="list-unstyled">_x000D_
<li>_x000D_
<a>_x000D_
<i class="ti-home"></i>Home</a>_x000D_
</li>_x000D_
<li v-for="(x, itemIndex) in sideBar" :key="itemIndex">_x000D_
<a @click="setActiveItemId(itemIndex)">_x000D_
<i class="fa" :class="x.icon"></i>{{x.name}}_x000D_
</a>_x000D_
<ul :id="x.id" class="collapse list-unstyled" :class="{'show':activeItemId === itemIndex && isActive}">_x000D_
<li v-for="y in x.children" :key="y.id">_x000D_
<a>{{y.name}}</a>_x000D_
</li>_x000D_
</ul>_x000D_
</li>_x000D_
</ul>_x000D_
</nav>_x000D_
</div>
_x000D_
_x000D_
_x000D_
Solution
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({_x000D_
el: '#app',_x000D_
methods: {_x000D_
setActiveItemId(itemIndex) {_x000D_
if (itemIndex === this.activeItemId) {_x000D_
this.activeItemId = ''_x000D_
return_x000D_
}_x000D_
this.activeItemId = itemIndex_x000D_
}_x000D_
},_x000D_
data() {_x000D_
return {_x000D_
message: 'Hello Vue.js!',_x000D_
activeItemId: '',_x000D_
sideBar: [{_x000D_
name: "Dashboard",_x000D_
url: "/dashboard",_x000D_
icon: "ti-world",_x000D_
children: [{_x000D_
name: "Buttons",_x000D_
url: "/components/buttons",_x000D_
icon: "fa-book",_x000D_
},_x000D_
{_x000D_
name: "Social Buttons",_x000D_
url: "/components/social-buttons",_x000D_
icon: "icon-puzzle",_x000D_
}_x000D_
]_x000D_
},_x000D_
{_x000D_
name: "Components",_x000D_
url: "/components",_x000D_
icon: "ti-pencil-alt",_x000D_
children: [{_x000D_
name: "Buttons",_x000D_
url: "/components/buttons",_x000D_
icon: "fa-book",_x000D_
},_x000D_
{_x000D_
name: "Social Buttons",_x000D_
url: "/components/social-buttons",_x000D_
icon: "icon-puzzle",_x000D_
}_x000D_
]_x000D_
},_x000D_
{_x000D_
name: "Validation",_x000D_
url: "/components",_x000D_
icon: "ti-pencil-alt",_x000D_
children: [{_x000D_
name: "Buttons",_x000D_
url: "/components/buttons",_x000D_
icon: "fa-book",_x000D_
},_x000D_
{_x000D_
name: "Social Buttons",_x000D_
url: "/components/social-buttons",_x000D_
icon: "icon-puzzle",_x000D_
}_x000D_
]_x000D_
}_x000D_
]_x000D_
}_x000D_
},_x000D_
computed: {_x000D_
isActive() {_x000D_
return this.activeItemId !== ''_x000D_
}_x000D_
}_x000D_
})
_x000D_
.collapse.show {_x000D_
display: block;_x000D_
}_x000D_
_x000D_
.collapse {_x000D_
display: none;_x000D_
}_x000D_
_x000D_
.list-unstyled {_x000D_
padding-left: 0;_x000D_
list-style: none;_x000D_
}_x000D_
_x000D_
.collapse.list-unstyled {_x000D_
padding-left: 15px;_x000D_
}_x000D_
_x000D_
nav.side-navbar {_x000D_
background: #fff;_x000D_
min-width: 250px;_x000D_
max-width: 250px;_x000D_
color: #000;_x000D_
-webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);_x000D_
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);_x000D_
z-index: 999;_x000D_
}_x000D_
_x000D_
nav.side-navbar ul a:hover {_x000D_
background: orange;_x000D_
color: #fff !important;_x000D_
}_x000D_
_x000D_
nav.side-navbar ul a {_x000D_
padding: 10px 15px;_x000D_
text-decoration: none;_x000D_
display: block;_x000D_
font-weight: 300;_x000D_
border-left: 4px solid transparent;_x000D_
}_x000D_
_x000D_
.list-enter {_x000D_
opacity: 0;_x000D_
}_x000D_
.list-enter-active {_x000D_
animation: slide-in .5s ease-out forwards;_x000D_
}_x000D_
.list-leave-to, .list-leave-active {_x000D_
opacity: 0;_x000D_
animation: slide-out .5s ease-out forwards;_x000D_
}_x000D_
@keyframes slide-in {_x000D_
from { height: 0; } to { height: 40px; }_x000D_
}_x000D_
@keyframes slide-out {_x000D_
from { height: 40px; } to { height: 0; }_x000D_
}
_x000D_
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />_x000D_
_x000D_
<script src="https://unpkg.com/vue"></script>_x000D_
_x000D_
<div id="app">_x000D_
<nav class="side-navbar">_x000D_
<ul class="list-unstyled">_x000D_
<li>_x000D_
<a>_x000D_
<i class="ti-home"></i>Home</a>_x000D_
</li>_x000D_
<li v-for="(x, itemIndex) in sideBar" :key="itemIndex">_x000D_
<a @click="setActiveItemId(itemIndex)">_x000D_
<i class="fa" :class="x.icon"></i>{{x.name}}_x000D_
</a>_x000D_
<ul :id="x.id" class="collapse list-unstyled show">_x000D_
<transition-group name="list">_x000D_
<li v-for="y in (activeItemId === itemIndex && isActive ? x.children : [])" :key="y.name">_x000D_
<a>{{y.name}}</a>_x000D_
</li>_x000D_
</transition-group>_x000D_
</ul>_x000D_
</li>_x000D_
</ul>_x000D_
</nav>_x000D_
</div>
_x000D_
_x000D_
_x000D_
Answered By: Anonymous
Disclaimer: This content is shared under creative common license cc-by-sa 3.0. It is generated from StackExchange Website Network.