Vuejs - 一次一个项目的过渡组轮播动画
Vuejs - transition-group carousel animation one item at a time
我正在尝试使用 Vue transition-group 实现这个 carousel/slide 效果:
如您所见,他们在上一个步骤上升和当前步骤上升的同时对一个列表项(步骤)进行动画处理,其内容遵循时间线。
我不确定使用 transition-group
是否可以实现我想要完成的目标,因为整个父块都会动画,而不是子节点。如果是这样的话,如果我至少可以为父块设置动画我会很高兴。
另一个警告是,由于我使用的 transition-group
没有 v-if
,或者没有过滤列表,所有步骤都默认呈现,这并不好。
这是我的 HTML 结构:
<transition-group class="steps-viewport" name="steps" tag="div">
<div v-for="step in currentStep" :key="step.order" class="step-wrapper">
<h3 class="is-size-5 mb-6 has-text-grey-light">
Passo {{ step.order }}
</h3>
<h1 class="is-size-3">{{ step.title }}</h1>
<h2 class="is-size-4 mt-2 has-text-grey">{{ step.headline }}</h2>
<component
class="mt-5"
v-bind:is="step.component"
@status-changed="handleStatusChange($event)"
></component>
</div>
</transition-group>
这是我的 CSS:
.component-wrapper {
width: 100%;
.steps-viewport {
height: calc(100vh - 10rem);
overflow: hidden;
display: flex;
flex-direction: column;
.step-wrapper {
flex: 0 0 calc(100vh - 10rem);
display: flex;
justify-content: center;
flex-direction: column;
}
}
}
最后但同样重要的是,我的组件的脚本:
import ProductInfo from "./ProductInfo";
export default {
components: {
ProductInfo
},
props: {
defaultActiveStep: {
type: Number,
default: 1
}
},
watch: {
activeStep() {
this.$emit("step-changed", this.activeStep);
}
},
computed: {
currentStep() {
return this.steps.filter(s => s.order === this.activeStep);
}
},
data: () => {
return {
activeStep: 1,
steps: [
{
order: 1,
title: "Title 1?",
headline:
"Headline 1",
component: "product-info"
},
{
order: 2,
title: "Title 2",
headline:
"Headline 2.",
component: "product-info"
},
{
order: 3,
title: "Title 3",
headline:
"Headline 3.",
component: "product-info"
},
{
order: 4,
title: "Title 4!",
headline:
"Headline 4",
component: "product-info"
}
]
};
},
methods: {
handleStatusChange(status) {
const first = this.steps.shift();
this.steps = this.steps.concat(first);
}
}
};
您需要定义特殊的 classes 以针对不同的过渡阶段,在本例中为 .steps-enter-active
(中间过渡状态)和 .steps-enter-to
(结束状态)。
要使其在页面加载时发生,您还需要传递 appear
属性。
如果你想要整个 order
块进行转换,你可以这样做:
new Vue({
el: '#app',
computed: {
currentStep() {
return this.steps.filter(s => s.order === this.activeStep);
}
},
data: () => {
return {
activeStep: 1,
steps: [{
order: 1,
title: "Title 1?",
headline: "Headline 1",
component: "product-info"
},
{
order: 2,
title: "Title 2",
headline: "Headline 2.",
component: "product-info"
},
{
order: 3,
title: "Title 3",
headline: "Headline 3.",
component: "product-info"
},
{
order: 4,
title: "Title 4!",
headline: "Headline 4",
component: "product-info"
}
]
};
},
});
Vue.config.productionTip = false;
Vue.config.devtools = false;
.component-wrapper {
width: 100%;
}
.steps-viewport {
height: calc(100vh - 10rem);
/* overflow: hidden */
display: flex;
flex-direction: column;
}
.step-wrapper {
flex: 0 0 calc(100vh - 10rem);
display: flex;
justify-content: center;
flex-direction: column;
}
.steps-enter-active {
opacity: 0;
transform: translateY(100%);
transition: all 0.4s;
}
.steps-enter-to {
opacity: 1;
transform: translateY(0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<transition-group class="steps-viewport" name="steps" tag="div" appear>
<div v-for="step in currentStep" :key="step.order" class="step-wrapper">
<h3 class="is-size-5 mb-6 has-text-grey-light">
Passo {{ step.order }}
</h3>
<h1 class="is-size-3">{{ step.title }}</h1>
<h2 class="is-size-4 mt-2 has-text-grey">{{ step.headline }}</h2>
</div>
</transition-group>
</div>
如果你想让里面的每个元素都过渡,你可以这样做,添加一个transition-delay
:
new Vue({
el: '#app',
computed: {
currentStep() {
return this.steps.filter(s => s.order === this.activeStep);
}
},
data: () => {
return {
activeStep: 1,
steps: [{
order: 1,
title: "Title 1?",
headline: "Headline 1",
component: "product-info"
},
{
order: 2,
title: "Title 2",
headline: "Headline 2.",
component: "product-info"
},
{
order: 3,
title: "Title 3",
headline: "Headline 3.",
component: "product-info"
},
{
order: 4,
title: "Title 4!",
headline: "Headline 4",
component: "product-info"
}
]
};
},
});
Vue.config.productionTip = false;
Vue.config.devtools = false;
.component-wrapper {
width: 100%;
}
.steps-viewport {
height: calc(100vh - 10rem);
/* overflow: hidden */
display: flex;
flex-direction: column;
}
.step-wrapper {
flex: 0 0 calc(100vh - 10rem);
display: flex;
justify-content: center;
flex-direction: column;
}
.steps-enter-active {
opacity: 0;
transform: translateY(100%);
transition: all 0.4s;
}
.steps-enter-to {
opacity: 1;
transform: translateY(0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="step in currentStep" :key="step.order" class="step-wrapper">
<transition-group class="steps-viewport" name="steps" tag="div" appear>
<h3 class="is-size-5 mb-6 has-text-grey-light" key="1">
Passo {{ step.order }}
</h3>
<h1 class="is-size-3" style="transition-delay: 0.1s" key="2">{{ step.title }}</h1>
<h2 class="is-size-4 mt-2 has-text-grey" style="transition-delay: 0.2s" key="3">{{ step.headline }}</h2>
</transition-group>
</div>
</div>
要同时转出,您需要使用 transition
,这样您就可以使用 mode="out-in"
,它允许元素在下一个元素进入之前先转出。
您还需要使用 .steps-enter-active > *
定位 CSS 中过渡元素的子元素。然后,只需添加一个 .steps-leave-to
class 来定义要离开的状态:
new Vue({
el: '#app',
computed: {
currentStep() {
return this.steps.filter(s => s.order === this.activeStep);
}
},
methods: {
nextStep() {
if (this.activeStep !== this.steps.length) {
this.activeStep++;
} else {
this.activeStep = 1;
}
}
},
data: () => {
return {
activeStep: 1,
steps: [{
order: 1,
title: "Title 1?",
headline: "Headline 1",
component: "product-info"
},
{
order: 2,
title: "Title 2",
headline: "Headline 2.",
component: "product-info"
},
{
order: 3,
title: "Title 3",
headline: "Headline 3.",
component: "product-info"
},
{
order: 4,
title: "Title 4!",
headline: "Headline 4",
component: "product-info"
}
]
};
},
});
Vue.config.productionTip = false;
Vue.config.devtools = false;
.component-wrapper {
width: 100%;
}
.steps-viewport {
height: calc(100vh - 10rem);
/* overflow: hidden */
display: flex;
flex-direction: column;
}
.step-wrapper {
flex: 0 0 calc(100vh - 10rem);
display: flex;
justify-content: center;
flex-direction: column;
}
.step-wrapper,
.step-wrapper>* {
transition: all 0.4s;
}
.step-wrapper>h1 {
transition-delay: 0.1s;
}
.step-wrapper>h2 {
transition-delay: 0.2s;
}
.steps-enter-active>* {
opacity: 0;
transform: translateY(100%);
}
.steps-leave-to>* {
opacity: 0;
transform: translateY(-100%);
}
.steps-enter-to>* {
opacity: 1;
transform: translateY(0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<transition name="steps" mode="out-in" duration="600" appear>
<div v-for="step in currentStep" :key="step.order" class="step-wrapper">
<h3 class="is-size-5 mb-6 has-text-grey-light">
Passo {{ step.order }}
</h3>
<h1 class="is-size-3">{{ step.title }}</h1>
<h2 class="is-size-4 mt-2 has-text-grey">{{ step.headline }}</h2>
</div>
</transition>
<button @click="nextStep()">Next</button>
</div>
最后,要在添加新元素后让一切顺利向上移动,您可以将初始字段包装在 div 中,将新元素包装在过渡中并降低第一个 div 乘以新元素的高度。
您还需要转换高度并配置时间(转换延迟和持续时间属性)以正确匹配:
new Vue({
el: '#app',
computed: {
currentStep() {
return this.steps.filter(s => s.order === this.activeStep);
}
},
methods: {
nextStep() {
this.$refs.addStep.disabled = false;
this.extraStep = false;
this.$refs.addAnotherStep.disabled = false;
this.anotherExtraStep = false;
if (this.activeStep !== this.steps.length) {
this.activeStep++;
} else {
this.activeStep = 1;
}
},
addStep() {
const initial = document.querySelector('.step-initial');
const input = document.querySelector('.step-input');
// 52px = input height + margin + border
initial.style.maxHeight = initial.offsetHeight - 52 + 'px';
if (!this.extraStep) {
this.$refs.addStep.disabled = true;
this.extraStep = true;
} else {
this.$refs.addAnotherStep.disabled = true;
this.anotherExtraStep = true;
}
}
},
data: () => {
return {
extraStep: false,
anotherExtraStep: false,
activeStep: 1,
steps: [{
order: 1,
title: "Title 1?",
headline: "Headline 1",
component: "product-info"
},
{
order: 2,
title: "Title 2",
headline: "Headline 2.",
component: "product-info"
},
{
order: 3,
title: "Title 3",
headline: "Headline 3.",
component: "product-info"
},
{
order: 4,
title: "Title 4!",
headline: "Headline 4",
component: "product-info"
}
]
};
},
});
Vue.config.productionTip = false;
Vue.config.devtools = false;
#app {
position: relative;
height: calc(300px + 52px);
}
.component-wrapper {
width: 100%;
}
.steps-viewport {
/* height: calc(100vh - 10rem); */
/* overflow: hidden */
display: flex;
flex-direction: column;
}
.step-wrapper,
.step-wrapper * {
transition: all 0.2s;
}
.step-wrapper * {
margin: 0;
}
.step-initial {
display: flex;
justify-content: space-evenly;
flex-direction: column;
height: 300px;
max-height: 300px;
}
.step-initial *:nth-child(2) {
transition-delay: 0.05s;
}
.step-initial *:nth-child(3) {
transition-delay: 0.1s;
}
.steps-enter-active .step-initial * {
opacity: 0;
transform: translateY(100%);
}
.steps-leave-to .step-initial *,
.steps-leave-to .step-input {
opacity: 0;
transform: translateY(-100%);
}
.steps-leave-to .step-input:nth-of-type(2) {
transition-delay: 0.2s;
}
.steps-leave-to .step-input:nth-of-type(3) {
transition-delay: 0.3s;
}
.steps-enter-to .step-initial * {
opacity: 1;
transform: translateY(0);
}
.step-input {
margin: 20px 0;
height: 30px;
}
.steps-input-enter-active {
opacity: 0;
transform: translateY(100%);
}
.steps-input-leave-to {
opacity: 0;
transform: translateY(-100%);
}
.steps-input-enter-to {
opacity: 1;
transform: translateY(0);
}
.step-btns {
position: absolute;
bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<transition name="steps" mode="out-in" duration="350" appear>
<div v-for="step in currentStep" :key="step.order" class="step-wrapper">
<div class="step-initial">
<h3 class="is-size-5 mb-6 has-text-grey-light">
Passo {{ step.order }}
</h3>
<h1 class="is-size-3">{{ step.title }}</h1>
<h2 class="is-size-4 mt-2 has-text-grey">{{ step.headline }}</h2>
</div>
<transition name="steps-input">
<div v-if="extraStep" class="step-input">
<input />
</div>
</transition>
<transition name="steps-input">
<div v-if="anotherExtraStep" class="step-input">
<input />
</div>
</transition>
</div>
</transition>
<div class="step-btns">
<button @click="nextStep()">Next</button>
<button @click="addStep()" ref="addStep">Add Step</button>
<button @click="addStep()" ref="addAnotherStep">Add Another Step</button>
</div>
</div>
我正在尝试使用 Vue transition-group 实现这个 carousel/slide 效果:
如您所见,他们在上一个步骤上升和当前步骤上升的同时对一个列表项(步骤)进行动画处理,其内容遵循时间线。
我不确定使用 transition-group
是否可以实现我想要完成的目标,因为整个父块都会动画,而不是子节点。如果是这样的话,如果我至少可以为父块设置动画我会很高兴。
另一个警告是,由于我使用的 transition-group
没有 v-if
,或者没有过滤列表,所有步骤都默认呈现,这并不好。
这是我的 HTML 结构:
<transition-group class="steps-viewport" name="steps" tag="div">
<div v-for="step in currentStep" :key="step.order" class="step-wrapper">
<h3 class="is-size-5 mb-6 has-text-grey-light">
Passo {{ step.order }}
</h3>
<h1 class="is-size-3">{{ step.title }}</h1>
<h2 class="is-size-4 mt-2 has-text-grey">{{ step.headline }}</h2>
<component
class="mt-5"
v-bind:is="step.component"
@status-changed="handleStatusChange($event)"
></component>
</div>
</transition-group>
这是我的 CSS:
.component-wrapper {
width: 100%;
.steps-viewport {
height: calc(100vh - 10rem);
overflow: hidden;
display: flex;
flex-direction: column;
.step-wrapper {
flex: 0 0 calc(100vh - 10rem);
display: flex;
justify-content: center;
flex-direction: column;
}
}
}
最后但同样重要的是,我的组件的脚本:
import ProductInfo from "./ProductInfo";
export default {
components: {
ProductInfo
},
props: {
defaultActiveStep: {
type: Number,
default: 1
}
},
watch: {
activeStep() {
this.$emit("step-changed", this.activeStep);
}
},
computed: {
currentStep() {
return this.steps.filter(s => s.order === this.activeStep);
}
},
data: () => {
return {
activeStep: 1,
steps: [
{
order: 1,
title: "Title 1?",
headline:
"Headline 1",
component: "product-info"
},
{
order: 2,
title: "Title 2",
headline:
"Headline 2.",
component: "product-info"
},
{
order: 3,
title: "Title 3",
headline:
"Headline 3.",
component: "product-info"
},
{
order: 4,
title: "Title 4!",
headline:
"Headline 4",
component: "product-info"
}
]
};
},
methods: {
handleStatusChange(status) {
const first = this.steps.shift();
this.steps = this.steps.concat(first);
}
}
};
您需要定义特殊的 classes 以针对不同的过渡阶段,在本例中为 .steps-enter-active
(中间过渡状态)和 .steps-enter-to
(结束状态)。
要使其在页面加载时发生,您还需要传递 appear
属性。
如果你想要整个 order
块进行转换,你可以这样做:
new Vue({
el: '#app',
computed: {
currentStep() {
return this.steps.filter(s => s.order === this.activeStep);
}
},
data: () => {
return {
activeStep: 1,
steps: [{
order: 1,
title: "Title 1?",
headline: "Headline 1",
component: "product-info"
},
{
order: 2,
title: "Title 2",
headline: "Headline 2.",
component: "product-info"
},
{
order: 3,
title: "Title 3",
headline: "Headline 3.",
component: "product-info"
},
{
order: 4,
title: "Title 4!",
headline: "Headline 4",
component: "product-info"
}
]
};
},
});
Vue.config.productionTip = false;
Vue.config.devtools = false;
.component-wrapper {
width: 100%;
}
.steps-viewport {
height: calc(100vh - 10rem);
/* overflow: hidden */
display: flex;
flex-direction: column;
}
.step-wrapper {
flex: 0 0 calc(100vh - 10rem);
display: flex;
justify-content: center;
flex-direction: column;
}
.steps-enter-active {
opacity: 0;
transform: translateY(100%);
transition: all 0.4s;
}
.steps-enter-to {
opacity: 1;
transform: translateY(0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<transition-group class="steps-viewport" name="steps" tag="div" appear>
<div v-for="step in currentStep" :key="step.order" class="step-wrapper">
<h3 class="is-size-5 mb-6 has-text-grey-light">
Passo {{ step.order }}
</h3>
<h1 class="is-size-3">{{ step.title }}</h1>
<h2 class="is-size-4 mt-2 has-text-grey">{{ step.headline }}</h2>
</div>
</transition-group>
</div>
如果你想让里面的每个元素都过渡,你可以这样做,添加一个transition-delay
:
new Vue({
el: '#app',
computed: {
currentStep() {
return this.steps.filter(s => s.order === this.activeStep);
}
},
data: () => {
return {
activeStep: 1,
steps: [{
order: 1,
title: "Title 1?",
headline: "Headline 1",
component: "product-info"
},
{
order: 2,
title: "Title 2",
headline: "Headline 2.",
component: "product-info"
},
{
order: 3,
title: "Title 3",
headline: "Headline 3.",
component: "product-info"
},
{
order: 4,
title: "Title 4!",
headline: "Headline 4",
component: "product-info"
}
]
};
},
});
Vue.config.productionTip = false;
Vue.config.devtools = false;
.component-wrapper {
width: 100%;
}
.steps-viewport {
height: calc(100vh - 10rem);
/* overflow: hidden */
display: flex;
flex-direction: column;
}
.step-wrapper {
flex: 0 0 calc(100vh - 10rem);
display: flex;
justify-content: center;
flex-direction: column;
}
.steps-enter-active {
opacity: 0;
transform: translateY(100%);
transition: all 0.4s;
}
.steps-enter-to {
opacity: 1;
transform: translateY(0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="step in currentStep" :key="step.order" class="step-wrapper">
<transition-group class="steps-viewport" name="steps" tag="div" appear>
<h3 class="is-size-5 mb-6 has-text-grey-light" key="1">
Passo {{ step.order }}
</h3>
<h1 class="is-size-3" style="transition-delay: 0.1s" key="2">{{ step.title }}</h1>
<h2 class="is-size-4 mt-2 has-text-grey" style="transition-delay: 0.2s" key="3">{{ step.headline }}</h2>
</transition-group>
</div>
</div>
要同时转出,您需要使用 transition
,这样您就可以使用 mode="out-in"
,它允许元素在下一个元素进入之前先转出。
您还需要使用 .steps-enter-active > *
定位 CSS 中过渡元素的子元素。然后,只需添加一个 .steps-leave-to
class 来定义要离开的状态:
new Vue({
el: '#app',
computed: {
currentStep() {
return this.steps.filter(s => s.order === this.activeStep);
}
},
methods: {
nextStep() {
if (this.activeStep !== this.steps.length) {
this.activeStep++;
} else {
this.activeStep = 1;
}
}
},
data: () => {
return {
activeStep: 1,
steps: [{
order: 1,
title: "Title 1?",
headline: "Headline 1",
component: "product-info"
},
{
order: 2,
title: "Title 2",
headline: "Headline 2.",
component: "product-info"
},
{
order: 3,
title: "Title 3",
headline: "Headline 3.",
component: "product-info"
},
{
order: 4,
title: "Title 4!",
headline: "Headline 4",
component: "product-info"
}
]
};
},
});
Vue.config.productionTip = false;
Vue.config.devtools = false;
.component-wrapper {
width: 100%;
}
.steps-viewport {
height: calc(100vh - 10rem);
/* overflow: hidden */
display: flex;
flex-direction: column;
}
.step-wrapper {
flex: 0 0 calc(100vh - 10rem);
display: flex;
justify-content: center;
flex-direction: column;
}
.step-wrapper,
.step-wrapper>* {
transition: all 0.4s;
}
.step-wrapper>h1 {
transition-delay: 0.1s;
}
.step-wrapper>h2 {
transition-delay: 0.2s;
}
.steps-enter-active>* {
opacity: 0;
transform: translateY(100%);
}
.steps-leave-to>* {
opacity: 0;
transform: translateY(-100%);
}
.steps-enter-to>* {
opacity: 1;
transform: translateY(0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<transition name="steps" mode="out-in" duration="600" appear>
<div v-for="step in currentStep" :key="step.order" class="step-wrapper">
<h3 class="is-size-5 mb-6 has-text-grey-light">
Passo {{ step.order }}
</h3>
<h1 class="is-size-3">{{ step.title }}</h1>
<h2 class="is-size-4 mt-2 has-text-grey">{{ step.headline }}</h2>
</div>
</transition>
<button @click="nextStep()">Next</button>
</div>
最后,要在添加新元素后让一切顺利向上移动,您可以将初始字段包装在 div 中,将新元素包装在过渡中并降低第一个 div 乘以新元素的高度。
您还需要转换高度并配置时间(转换延迟和持续时间属性)以正确匹配:
new Vue({
el: '#app',
computed: {
currentStep() {
return this.steps.filter(s => s.order === this.activeStep);
}
},
methods: {
nextStep() {
this.$refs.addStep.disabled = false;
this.extraStep = false;
this.$refs.addAnotherStep.disabled = false;
this.anotherExtraStep = false;
if (this.activeStep !== this.steps.length) {
this.activeStep++;
} else {
this.activeStep = 1;
}
},
addStep() {
const initial = document.querySelector('.step-initial');
const input = document.querySelector('.step-input');
// 52px = input height + margin + border
initial.style.maxHeight = initial.offsetHeight - 52 + 'px';
if (!this.extraStep) {
this.$refs.addStep.disabled = true;
this.extraStep = true;
} else {
this.$refs.addAnotherStep.disabled = true;
this.anotherExtraStep = true;
}
}
},
data: () => {
return {
extraStep: false,
anotherExtraStep: false,
activeStep: 1,
steps: [{
order: 1,
title: "Title 1?",
headline: "Headline 1",
component: "product-info"
},
{
order: 2,
title: "Title 2",
headline: "Headline 2.",
component: "product-info"
},
{
order: 3,
title: "Title 3",
headline: "Headline 3.",
component: "product-info"
},
{
order: 4,
title: "Title 4!",
headline: "Headline 4",
component: "product-info"
}
]
};
},
});
Vue.config.productionTip = false;
Vue.config.devtools = false;
#app {
position: relative;
height: calc(300px + 52px);
}
.component-wrapper {
width: 100%;
}
.steps-viewport {
/* height: calc(100vh - 10rem); */
/* overflow: hidden */
display: flex;
flex-direction: column;
}
.step-wrapper,
.step-wrapper * {
transition: all 0.2s;
}
.step-wrapper * {
margin: 0;
}
.step-initial {
display: flex;
justify-content: space-evenly;
flex-direction: column;
height: 300px;
max-height: 300px;
}
.step-initial *:nth-child(2) {
transition-delay: 0.05s;
}
.step-initial *:nth-child(3) {
transition-delay: 0.1s;
}
.steps-enter-active .step-initial * {
opacity: 0;
transform: translateY(100%);
}
.steps-leave-to .step-initial *,
.steps-leave-to .step-input {
opacity: 0;
transform: translateY(-100%);
}
.steps-leave-to .step-input:nth-of-type(2) {
transition-delay: 0.2s;
}
.steps-leave-to .step-input:nth-of-type(3) {
transition-delay: 0.3s;
}
.steps-enter-to .step-initial * {
opacity: 1;
transform: translateY(0);
}
.step-input {
margin: 20px 0;
height: 30px;
}
.steps-input-enter-active {
opacity: 0;
transform: translateY(100%);
}
.steps-input-leave-to {
opacity: 0;
transform: translateY(-100%);
}
.steps-input-enter-to {
opacity: 1;
transform: translateY(0);
}
.step-btns {
position: absolute;
bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<transition name="steps" mode="out-in" duration="350" appear>
<div v-for="step in currentStep" :key="step.order" class="step-wrapper">
<div class="step-initial">
<h3 class="is-size-5 mb-6 has-text-grey-light">
Passo {{ step.order }}
</h3>
<h1 class="is-size-3">{{ step.title }}</h1>
<h2 class="is-size-4 mt-2 has-text-grey">{{ step.headline }}</h2>
</div>
<transition name="steps-input">
<div v-if="extraStep" class="step-input">
<input />
</div>
</transition>
<transition name="steps-input">
<div v-if="anotherExtraStep" class="step-input">
<input />
</div>
</transition>
</div>
</transition>
<div class="step-btns">
<button @click="nextStep()">Next</button>
<button @click="addStep()" ref="addStep">Add Step</button>
<button @click="addStep()" ref="addAnotherStep">Add Another Step</button>
</div>
</div>