Asynchronous task is not reactive in vuejs view - vue.js

Default the loading image is true after complete the upload loading image is false, but after update the loading object no effect in view, always show the loading bar.
Where is my mistake, please help anyone,
Note: also try by this.$nextTick() function, same output;
in console the update we got, but no effect in view
Vue.config.devtools=false;
Vue.config.productionTip = false;
new Vue({
el:"#app",
data: {
isloadingImage: [],
property:{
images:[]
}
},
methods: {
addFiles() {
this.$refs.files.click();
},
handleFilesUpload() {
let uploadedFiles = this.$refs.files.files;
let maxLength = uploadedFiles.length <= 4 ? uploadedFiles.length : 4;
for (let i = 0; i < maxLength; i++) {
uploadedFiles[i].url = URL.createObjectURL(uploadedFiles[i]);
this.property.images.push(uploadedFiles[i]);
}
this.uploadImages();
},
removeFile(key) {
this.property.images.splice(key, 1);
delete this.isloadingImage[key];
},
async uploadImages(){
this.property.images.forEach((value, key) => {
if (!this.isloadingImage[key]) {
this.isloadingImage[key] = true;
let myFormData = new FormData();
myFormData.append('title', value);
axios.post('http://localhost:800/uploadimage',
myFormData).then(response => {
this.isloadingImage[key] = false;
}).catch(error=> {
this.isloadingImage[key] = false;
console.log(this.isloadingImage);
})
}
});
}
}
});
.small-image {
max-height: 200px;
max-width: 200px;
}
.post-image button {
padding: 0 5px;
}
.post-image-preview {
max-height: 105px;
}
.post-image .caption {
max-width: 198px;
height: 27px;
}
.lds-facebook {
display: inline-block;
position: relative;
width: 64px;
height: 50px;
}
.lds-facebook div {
display: inline-block;
position: absolute;
left: 6px;
width: 10px;
background: #bfbebe;
animation: lds-facebook 1.2s cubic-bezier(0, 0.5, 0.5, 1) infinite;
}
.lds-facebook div:nth-child(1) {
left: 6px;
animation-delay: -0.24s;
}
.lds-facebook div:nth-child(2) {
left: 26px;
animation-delay: -0.12s;
}
.lds-facebook div:nth-child(3) {
left: 45px;
animation-delay: 0s;
}
#keyframes lds-facebook {
0% {
top: 6px;
height: 51px;
}
50%, 100% {
top: 19px;
height: 26px;
}
}
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<div class="field-title"><h5>Pictures</h5></div>
<div class="form-group post-image">
<div class="col-md-12">
<div class="upload-btn-wrapper">
<button class="add-photo" v-on:click="addFiles()"><i
class="fas fa-camera"></i></button>
<input type="file" multiple id="file" ref="files"
v-on:change="handleFilesUpload()">
</div>
<div class="brows-image-text"><p>You can upload up to<br>4 pictures per
listing</p></div>
</div>
<div class="row">
<div v-for="(file, key) in property.images" class="col-md-3">
<div class="lds-facebook" v-if="isloadingImage[key]">
<div></div>
<div></div>
<div></div>
</div>
<div v-else>
<button v-on:click="removeFile( key )" type="button">
<i class="fas fa-times text-danger"></i>
</button>
<img :src="file.url" class="small-image post-image-preview">
</div>
</div>
</div>
</div>
</div>

See rule #2 here https://vuejs.org/2016/02/06/common-gotchas/#Why-isn%E2%80%99t-the-DOM-updating
You update isloadingImage array's values using its keys. In such a case for the change to be reactive, you need to replace your whole array after the fact.
Example:
axios.post('http://localhost:800/uploadimage', myFormData)
.then(response => {
this.isloadingImage[key] = false;
this.isloadingImage = this.isloadingImage.slice(0);
// ^^^ this line
}).catch(error=> {
console.log('error', key, error)
this.isloadingImage[key] = false;
this.isloadingImage = this.isloadingImage.slice(0);
// ^^^ and line
});

Use data as function, not as object like you do.
new Vue({
el:"#app",
data () {
return {
imageIsLoading: ...

Related

How to hide next and prev btn in carousel using vue 2 / nuxt js?

I have created a multi items carousel in which i slide one item at a time.
Initially i want to hide prev btn , but when clicked on next btn and one or more item is moved/slide to left in want the prev btn to be visible and when i am at end of the caorusel items i want to hide next button
template
<div class="main-container">
<div class="carousel-container position-relative" ref="container">
<div class="carousel-inner overflow-hidden">
<div class="carousel-track" >
<nuxt-link to="" class="card-container" v-for="(index, i) in 9" :key="i">
<div class="card"></div>
</nuxt-link>
</div>
</div>
<div class="btns-container">
<button class="prevBtn" #click="prev" >
prev
</button>
<button class="nextBtn" #click="next" >
next
</button>
</div>
</div>
</div>
script
methods: {
next() {
const track = document.querySelector('.carousel-track')
const item = document.querySelector('.card-container')
track.scrollLeft += item.clientWidth
},
prev() {
const track = document.querySelector('.carousel-track')
const item = document.querySelector('.card-container')
track.scrollLeft -= item.clientWidth
},
}
styles
.carousel-track{
display: flex;
overflow: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
scrollbar-width: none;
}
.carousel-track::-webkit-scrollbar {
display: none;
}
.card-container{
flex-shrink: 0;
scroll-snap-align: start;
}
.btns-container button{
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.prevBtn{
left: -1rem;
}
.nextBtn{
right: -1rem;
}
You should not use querySelectors but rather state since you're working with Vue.
Sorry, I didn't had a carousel example so I did something a bit different.
<template>
<div class="main-container">
<div ref="container" class="carousel-container position-relative">
<div class="carousel-inner overflow-hidden">
<div class="carousel-track">
<nuxt-link
v-for="(city, index) in cities"
:key="city.id"
to=""
class="card-container"
>
<div
class="card"
:class="index === currentCityIndex && 'active-city'"
>
{{ city.name }}
</div>
</nuxt-link>
</div>
</div>
<br />
<p>Current city index: {{ currentCityIndex }}</p>
<div class="btns-container">
<button v-show="currentCityIndex !== 0" class="prevBtn" #click="prev">
prev
</button>
<button
v-show="currentCityIndex !== cities.length - 1"
class="nextBtn"
#click="next"
>
next
</button>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
currentCityIndex: 0,
cities: [
{ name: 'New york', id: '1' },
{ name: 'Los Angeles', id: '2' },
{ name: 'Chicago', id: '3' },
{ name: 'Houston', id: '4' },
{ name: 'Philadelphia', id: '5' },
{ name: 'Phoenix', id: '6' },
{ name: 'San Antonio', id: '7' },
{ name: 'San Diego', id: '8' },
{ name: 'Dallas', id: '9' },
{ name: 'San Jose', id: '10' },
],
}
},
methods: {
next() {
this.currentCityIndex++
},
prev() {
this.currentCityIndex--
},
},
}
</script>
<style scoped>
.active-city {
border: 2px solid red;
}
</style>
The idea is mainly to do a check on the button with v-show="currentCityIndex !== 0" and display it depending on the current index you're on. You can of course also use visibility or any kind of cool CSS approach to avoid any shift regarding the location of the buttons.
v-show="currentCityIndex !== cities.length - 1" is checking if we are on the last element of your collection.
This is a basic carrousel I sometimes use and modify if I need it. It is originally an infinite carrousel but I added that function you are looking for.
You can copy the code and check how it works and sure I can be improve a lot. But so far it works.
Template
<template>
<div class="main-container">
<div class="carrousel-container">
<span ref="nextArrow" #click="nextSlide" class="slider-btn next">
<svg
width="25"
height="43"
viewBox="0 0 25 43"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M23.5858 20.0623L4.39859 0.875151C3.13866 -0.384778 0.984375 0.507553 0.984375 2.28936V40.6638C0.984375 42.4456 3.13866 43.3379 4.39859 42.078L23.5858 22.8908C24.3668 22.1097 24.3668 20.8434 23.5858 20.0623Z"
/>
</svg>
</span>
<span ref="prevArrow" #click="prevSlide" class="slider-btn prev">
<svg
width="25"
height="43"
viewBox="0 0 25 43"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1.41421 20.0623L20.6014 0.875151C21.8613 -0.384778 24.0156 0.507553 24.0156 2.28936V40.6638C24.0156 42.4456 21.8613 43.3379 20.6014 42.078L1.41421 22.8908C0.633165 22.1097 0.633165 20.8434 1.41421 20.0623Z"
/>
</svg>
</span>
<!-- carousel -->
<div
:id="activeSlideIndex"
v-if="showSlides"
class="carousel-container"
>
<div
class="slide"
ref="slide"
v-for="(slide, idx) in slides"
:class="slide.position"
:key="slide.id"
>
{{ idx }}
</div>
</div>
<!-- carousel -->
</div>
</div>
</template>
Script and Styles
<script>
export default {
props: {
slides: {
type: Array,
default: () => [
{ id: 1, name: "sliderOne" },
{ id: 2, name: "slider Two" },
{ id: 3, name: "slider Three" },
],
},
},
mounted() {
this.orderSlides(this.slides, this.activeSlideIndex);
},
data() {
return {
activeSlideIndex: 0,
showSlides: false,
};
},
methods: {
nextSlide() {
++this.activeSlideIndex;
this.displayOrder(this.activeSlideIndex);
},
prevSlide() {
--this.activeSlideIndex;
this.displayOrder();
},
displayOrder() {
if (this.activeSlideIndex === this.slides.length) {
console.log(this.activeSlideIndex);
this.activeSlideIndex = 0;
} else if (this.activeSlideIndex < 0) {
this.activeSlideIndex = this.slides.length - 1;
}
this.orderSlides(this.slides, this.activeSlideIndex);
},
orderSlides(array, activeIndex) {
array.forEach((element, idx) => {
element.position = "nextSlide";
if (idx === activeIndex) {
element.position = "activeSlide";
} else if (
idx === activeIndex - 1 ||
(activeIndex === 0 && idx === array.length - 1)
) {
element.position = "lastSlide";
}
});
if (!this.showSlides) {
this.showSlides = true;
}
// toggle arrows
if (activeIndex === array.length - 1) {
this.$refs.nextArrow.style.display = "none";
} else if (activeIndex === 0) {
this.$refs.prevArrow.style.display = "none";
} else {
this.$refs.nextArrow.style.display = "block";
this.$refs.prevArrow.style.display = "block";
}
},
},
};
</script>
<style scoped>
.main-container {
height: 100vh;
width: 100%;
background: rgba(0, 0, 0, 0.6);
overflow: hidden;
display: grid;
place-content: center;
}
.carrousel-container {
width: 769px;
height: 631px;
position: relative;
padding-top: 37px;
padding-bottom: 20px;
}
.slider-btn {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.slider-btn svg {
fill: red;
}
.next {
right: 25px;
}
.prev {
left: 25px;
}
.carousel-container {
width: 600px;
height: 631px;
overflow: hidden;
position: relative;
display: flex;
background: white;
justify-content: center;
align-items: center;
flex-direction: column;
margin: 0 auto;
}
.slide {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
transition: 0.3s all linear;
background: var(--primary-light);
border-radius: var(--border-radius-1);
}
.slide.activeSlide {
opacity: 1;
transform: translateX(0);
}
.slide.lastSlide {
transform: translateX(-100%);
}
.slide.nextSlide {
transform: translate(100%);
}
img {
width: 100%;
}
</style>

Unwanted animation bug in Vue.js

This is an unwanted animation bug that seems to be normal, but I want the element to be animationed which is in <input v-model="todo"/>. The problem is each time I press on add button to add the todo name (<input v-model="todo"/>), the last element 'last' runs the animation.
P.s. I tried to keep the code as simple as possible.
Vue.createApp({
data() {
return {
todo: "",
todo_list: ['last'],
};
},
methods: {
add() {
this.todo_list.unshift(this.todo);
console.log(this.todo_list);
},
remove(index) {
this.todo_list.splice(index, 1);
},
},
}).mount('#app');
.list-enter-active,
.list-leave-active {
transition: all 200ms ease-out;
}
.list-enter-from {
transform: translateY(-20px);
}
.list-leave-to {
opacity: 0;
transform: translateX(20px);
}
article {
width: 50%;
padding: 10px;
background-color: #dddddd;
border: 1px solid #cfcfcf;
border-radius: 5px;
margin-block: 10px
}
<script src="https://unpkg.com/vue#next"></script>
<div id="app">
<input type="text" v-model="todo" /> <button #click="add">add</button>
<transition-group name="list" tag="section">
<article v-for="(todo, index) in todo_list" :key="index" #click="remove(index)">
<span>{{ todo }}</span>
</article>
</transition-group>
</div>
The reason you're experiencing this issue, is because you're using the index as a key.
If you added the elements to the end of the list, this would be fine.
But since you're adding it to the start, it will cause the issue you're seeing.
I'd suggest you make each todo an object, and add a unique identifier to each object. This can be a simple integer that you increment. Then you can use that property as the key.
Example
let id = 1;
Vue.createApp({
data() {
return {
todo: "",
todo_list: [{
id: id++,
value: 'last'
}],
};
},
methods: {
add() {
const todo = {
id: id++,
value: this.todo
}
this.todo_list.unshift(todo);
},
remove(index) {
this.todo_list.splice(index, 1);
},
},
}).mount('#app');
.list-enter-active,
.list-leave-active {
transition: all 200ms ease-out;
}
.list-enter-from {
transform: translateY(-20px);
}
.list-leave-to {
opacity: 0;
transform: translateX(20px);
}
article {
width: 50%;
padding: 10px;
background-color: #dddddd;
border: 1px solid #cfcfcf;
border-radius: 5px;
margin-block: 10px
}
<script src="https://unpkg.com/vue#next"></script>
<div id="app">
<input type="text" v-model="todo" /> <button #click="add">add</button>
<transition-group name="list" tag="section">
<article v-for="(todo, index) in todo_list" :key="todo.id" #click="remove(index)">
<span>{{ todo.value }}</span>
</article>
</transition-group>
</div>

Why does transition-group animate opacity but not animate height?

the code below animates the element you click on, but I want it to smoothly decrease the height to zero as well. Unfortunately, the height does not change, but everything works with opacity.
height: 0 !improtant; //does not help to solve the problem
<template>
<transition-group name="msgAnimation" tag="div">
<div v-for="(obj, i) in messages" :key="obj.key" class="wrapper">
<div class="wrapper__block" #click="messages.splice(i, 1)">
{{ obj.msg }}
</div>
</div>
</transition-group>
</template>
<style lang="css">
.msgAnimation-enter-active,
.msgAnimation-leave-active {
transition: all 5s;
}
.msgAnimation-enter,
.msgAnimation-leave-to {
height: 0;
opacity: 0;
}
.wrapper {
width: 100%;
height: 9vmin;
}
.wrapper__block {
background: green;
height: 9vmin;
width: 100%;
}
</style>
<script>
export default {
name: "HelloWorld",
data() {
return {
totalAmount: 0,
messages: [{ key: 0, msg: "Are u hacker" }],
};
},
};
</script>
Your CSS rules was declared after your animation
const example = {
data() {
return {
totalAmount: 0,
messages: [{
key: 0,
msg: "Are u hacker"
},
{
key: 1,
msg: "Are u hacker"
}
],
};
},
};
const app = new Vue(example);
app.$mount("#app");
.msgAnimation-enter-active,
.msgAnimation-leave-active {
transition: all 5s;
}
.wrapper {
width: 100%;
height: 9vmin;
overflow:hidden;
}
.wrapper__block {
background: green;
width: 100%;
}
.msgAnimation-enter,
.msgAnimation-leave-to {
opacity: 0;
height: 0;
}
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<div id="app">
<transition-group name="msgAnimation" tag="div">
<div v-for="(obj, i) in messages" :key="obj.key" class="wrapper">
<div class="wrapper__block" #click="messages.splice(i, 1)">
{{ obj.msg }}
</div>
</div>
</transition-group>
</div>
You're not limiting overflow of .wrapper, and you have a height specified in .wrapper__block. Thus, even if .wrapper goes smoothly to 0, its child will not.
Setting height: 100%; on .wrapper__block, or setting overflow: hidden on .wrapper should do the trick.
<template>
<transition-group name="msgAnimation" tag="div">
<div v-for="(obj, i) in messages" :key="obj.key" class="wrapper">
<div class="wrapper__block" #click="messages.splice(i, 1)">
{{ obj.msg }}
</div>
</div>
</transition-group>
</template>
<style lang="css">
.msgAnimation-enter-active,
.msgAnimation-leave-active {
transition: all 5s;
}
.msgAnimation-enter,
.msgAnimation-leave-to {
height: 0;
opacity: 0;
}
.wrapper {
width: 100%;
height: 9vmin;
}
.wrapper__block {
background: green;
height: 100%;
width: 100%;
}
</style>
<script>
export default {
name: "HelloWorld",
data() {
return {
totalAmount: 0,
messages: [{ key: 0, msg: "Are u hacker" }],
};
},
};
</script>
Alternatively, if you don't mind distortion during the animation, it's a lot more performant to animate transform: scaleY(0), as transform and opacity are applied at the Composition step in CSS, you prevent a lot of in-between style calculations, making your app noticeably faster whn you have several thousand messages.

Fix animated images on slide

I'm trying to make an animation when changing a slide. The old slide disappears with the animation, and the new one shows up with the animation. My animation is alternating. Help. Thank you all !!
var app = new Vue({
el: '#app',
data() {
return {
selectedIndex: 0,
message: "Test work vue",
isOpenSlide: true,
startVal: 0,
decimals: 0,
duration: 2.5,
options: {
useEasing: true,
useGrouping: true,
separator: ',',
decimal: '.',
prefix: '',
suffix: ''
},
items: [
{
title: 'Center of osteopatia and rehabilitation',
url_img: 'https://i.imgur.com/gQp3VSW.jpg',
info_block: [
{
incremental: '800',
description: 'Increasing the number of transactions from organic search results'
},
{
incremental: '240',
description: 'Raising your revenue'
}
]
},
{
title: 'SLide 2',
url_img: 'https://newevolutiondesigns.com/images/freebies/space-wallpaper-5.jpg',
info_block: [
{
incremental: '140',
description: 'Increasing the numb organic search results'
},
{
incremental: '790',
description: 'Raising your revenue'
}
]
},
{
title: ' SLIDE 3',
url_img: 'https://www.planwallpaper.com/static/images/4433836-space-wallpapers.jpg',
info_block: [
{
incremental: '110',
description: 'Increasing the number of trans'
},
{
incremental: '99',
description: 'Raising your revenue'
}
]
}
]
}
},
methods: {
select(index) {
this.selectedIndex = index
},
index_dotnav: function (index) {
this.selectedIndex = index
},
open() {
this.isOpenSlide = true;
},
close() {
this.isOpenSlide = false;
},
toggle() {
if (this.isOpenSlide) {
this.close();
} else {
this.open();
}
},
ChangeSlider() {
setTimeout(() => {
if (++this.selectedIndex === this.items.length) {
this.selectedIndex = 0;
}
this.toggle();
this.ChangeSlider()
}, 5000)
},
callback(instance) {
instance.start();
}
},
mounted() {
this.ChangeSlider();
}
})
.slide-leave-active,
.slide-enter-active {
transition: 1s;
}
.slide-enter {
transform: translate(100%, 0);
}
.slide-leave-to {
transform: translate(-100%, 0);
}
ul {
padding-left: 0;
margin: 0;
}
.img-block,
section > *,
.uk-slideshow,
.uk-slideshow > ul {
height: 100vh !important;
}
.information-slide .uk-container {
position: absolute;
z-index: 1;
top: 0;
bottom: 0;
right: 0;
left: 0;
margin: auto 0;
display: flex;
flex-direction: column;
justify-content: center;
color: #fff;
}
.slideshow > div.dotnav-block {
top: 50%;
left: 95%;
z-index: 2;
}
.slideshow > div.dotnav-block li a {
background: #fff;
}
.slideshow > div.dotnav-block li.active a {
width: 13px;
height: 13px;
}
.slideshow > div.dotnav-block ul {
align-items: center;
}
.slideshow .slideshow-items > li {
display: none;
}
.slideshow .slideshow-items > li.active {
display: block;
position: relative;
}
.slideshow .slideshow-items > li img {
height: 100%;
width: auto;
object-fit: cover;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-rc.14/css/uikit.min.css"/>
<body>
<div id="app">
<section>
<div class="uk-child-width-1-2" uk-grid>
<div>
<h1>{{ message }}</h1>
</div>
<div>
<div id="slideshow">
<div class="slideshow">
<ul class="slideshow-items">
<li v-for="(item,index) in items" :class="{'active':index===selectedIndex}"
v-on:click="select(index)">
<div class="information-slide">
<transition name="slide">
<div class="img-block" v-show="isOpenSlide">
<img v-bind:src="item.url_img" alt="">
</div>
</transition>
<div class="uk-container">
<div class="title title-1">{{item.title}}</div>
<div class="info-block">
<div class="info" v-for="(iblock,ind) in item.info_block">
<div class="incremental">
<span>+</span>
<!--<app-count-up-->
<!--:startVal="startVal"-->
<!--:endVal="iblock.incremental"-->
<!--:decimals="decimals"-->
<!--:duration="duration"-->
<!--:options="options"-->
<!--:callback="onReady"></app-count-up>-->
<span>%</span>
</div>
<div class="description descr-1">{{iblock.description}}</div>
</div>
</div>
</div>
</div>
</li>
</ul>
<div class="dotnav-block uk-position-bottom-center uk-position-small">
<ul class="uk-dotnav uk-dotnav-vertical">
<li :class="{'active':index===selectedIndex}" v-for="(item,index) in items"
v-on:click="index_dotnav(index)">
Item {{index}}</li>
</ul>
</div>
</div>
</div>
</template>
</div>
</div>
</section>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.17/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-rc.14/js/uikit.min.js"></script>

Vue Accordion with transition

I'm trying to integrate the Accordion component with a body transition, but without success :( . All is working as well except the animation.
template:
<div class="accordion">
<div class="accordion-title" #click="isOpen = !isOpen" :class="{'is-open': isOpen}">
<span>{{title}}</span>
<i class="ic ic-next"></i>
</div>
<div class="accordion-body" :class="{'is-open': isOpen}">
<div class="card">
<slot name="body"></slot>
</div>
</div>
</div>
component:
props: {
title: {
type: String,
default: 'Title'
}
},
data() {
return {
isOpen: false
}
}
And styles:
.accordion-body {
font-size: 1.3rem;
padding: 0 16px;
transition: .3s cubic-bezier(.25,.8,.5,1);
&:not(.is-open) {
display: none;
height: 0;
overflow: hidden;
}
&.is-open {
height: auto;
// display: block;
padding: 16px;
}
}
.card {
height: auto;
}
I tried to use <transition> but it doesn't work with height or display properties.
Help please!
display:none will remove your content and avoid the animation, you should trick with opacity, overflow:hidden and height, but you ll be forced to do a method for that.
For example (not tested, but inspiring):
in template:
<div class="accordion" #click="switchAccordion" :class="{'is-open': isOpen}">
<div class="accordion-title">
<span>{{title}}</span>
<i class="ic ic-next"></i>
</div>
<div class="accordion-body">
<p></p>
</div>
</div>
in component (add a method):
methods: {
switchAccordion: function (event) {
let el = event.target
this.isOpen = !this.isOpen // switch data isOpen
if(this.isOpen) {
let childEl1 = el.childNodes[1]
el.style.height = childEl1.style.height
} else {
let childEl2 = el.childNodes[2]
el.style.height = childE2.style.height // or .clientHeight + "px"
}
}
}
in style:
.accordion {
transition: all .3s cubic-bezier(.25,.8,.5,1);
}
.accordion-body {
font-size: 1.3rem;
padding: 0 16px;
opacity:0
}
.is-open .accordion-body {
opacity:0
}
In this case, your transition should work as you want.
The javascript will change the height value and transition transition: all .3s cubic-bezier(.25,.8,.5,1); will do the animation