Issue
I have created an Accordion component in a Vue3 and Nuxt3 project. everything is good except that I can't put an animation on the height of accordion panels. I want a smooth remove when I hide a panel from this accordion.
here are the accordion panels:
const panels = [
{id:1,title:'Test Accordion 1',icon:'',},
{id:2,title:'Test Accordion 2',icon:'',},
{id:3,title:'Test Accordion 3',icon:'',},
]
and where I use that component like:
<accordion :panels="panels">
<template #1>
this is one
</template>
<template #2>
this is two
</template>
<template #3>
this is three
</template>
</accordion>
and this is the SFC file:
<script setup lang="ts">
const props = defineProps({
panels: {type: Array,},
})
const current = ref(1)
function toggleAccardion(index: any) {
if (current.value == index) {
current.value = 0
return
}
current.value = index
}
</script>
<template>
<div v-for="panel in panels" :key="panel.id">
<div class="d-flex flex-row p-4 cursor-pointer bg-gray-200" @click.prevent="toggleAccardion(panel.id)">
<div v-if="panel.icon">
{{ panel.icon }}
</div>
<div class="flex-grow-1">
<h4 class="mb-0">{{ panel.title }}</h4>
</div>
<div>
<i v-if="panel.id === current" class="ki-outline ki-minus fs-4 text-gray-800"></i>
<i v-else class="ki-outline ki-plus fs-4 text-gray-800"></i>
</div>
</div>
<div class="p-4" v-if="panel.id === current">
<slot :name="panel.id"></slot>
</div>
</div>
</template>
Solution
You can use <transition>
component which works as expected in this case. Look here for more info.
First of all, wrap your content (panel) with <Transition>
component like this:
<Transition>
<div class="p-4" v-if="panel.id === current">
<slot :name="panel.id"></slot>
</div>
</Transition>
Set a name attribute for transition component: <Transition name="accordion">
.
Now You can create custom animation with exact same name as name of Transition
.
@keyframes accordion {
0% {
max-height: 0;
}
100% {
max-height: 200px; // max possible value
}
}
.accordion-enter-active {
animation: accordion 0.2s linear;
}
.accordion-leave-active {
animation: accordion 0.2s linear reverse;
}
Set max possible height of panel for max-height
, because we can't animate with height:auto
or percent value
Well, if You try this, it looks glitchy. Because there is also some padding for that panel. So we should add padding to that animation. Update @keyframe
as following:
@keyframes accordion {
0% {
max-height: 0;
padding: 0 16px; // horizontal padding should not be animated
}
100% {
max-height: 200px;
padding: 16px;
}
}
The more accurate max-height
, the more smooth animation.
Answered By - Shahzodjon Jumakulov
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.