Vue Transitions

Example of a dynamic transition component that has dynamic components within.

by Travis Almand

HTML

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<div id="app">
	<div id="panel">
		<select v-model="selected">
			<option disabled value="">Please select one</option>
			<option>fade</option>
			<option>slide</option>
			<option>rotate</option>
			<option>spin</option>
			<option>shake</option>
			<option>fall</option>
		</select>
		<button @click="clickHandler">toggle components</button>
	</div>
	
	<p>Select a type of transition and then toggle the components.</p>
	
	<transition-switcher :selected="selected">
		<component :is="currentComponent"></component>
	</transition-switcher>
</div>

SCSS

body,
html {
	margin: 0;
	overflow: hidden;
	padding: 0;
}

#app {
	align-items: center;
	display: flex;
	flex-direction: column;
	height: 100vh;
	justify-content: center;
	width: 100vw;
	
	.card {
		align-items: center;
		background-color: #fff;
		border: 2px solid black;
		border-radius: 10px;
		display: flex;
		height: 200px;
		justify-content: center;
		width: 200px;
	}
}

#panel {
	display: flex;
	justify-content: center;
	left: 0;
	padding: 10px;
	position: absolute;
	top: 0;
	width: 100%;
}

.fade-enter, .fade-leave-to { opacity: 0; }
.fade-enter-active, .fade-leave-active { transition: 0.5s; }

.slide-enter { opacity: 0; transform: translate3d(50px, 0, 0); }
.slide-enter-active,
.slide-leave-active { transition: 0.5s; }
.slide-leave-to { opacity: 0; transform: translate3d(-50px, 0, 0); }

.rotate-enter { transform: perspective(500px) rotate3d(0, 1, 0, 90deg); }
.rotate-enter-active, .rotate-leave-active { transition: 0.5s; }
.rotate-leave-to { transform: perspective(500px) rotate3d(0, 1, 0, -90deg); }

.spin-enter { transform: perspective(500px) rotate3d(0, 0, 1, 180deg); }
.spin-enter-active, .spin-leave-active { transition: 0.5s; }
.spin-leave-to { transform: perspective(500px) rotate3d(0, 0, 1, -180deg); }

.shake-enter-active { animation: shake 1s; }

.fall-enter-active {
	animation: fall-in 0.25s;
	transform-origin: bottom center;
}
.fall-leave-active {
	animation: fall-out 1s;
	transform-origin: top left;
}

@keyframes shake {
	0% {
		transform: rotate3d(0, 0, 0, 0deg);
		transform-origin: top left;
	}
	25% {
		transform: rotate3d(0, 0, 1, 90deg);
	}
}

@keyframes fall-out {
	0% {
		transform: rotate3d(0, 0, 0, 0deg);
	}
	25% {
		transform: rotate3d(0, 0, 1, 110deg);
	}
	50% {
		transform: rotate3d(0, 0, 1, 30deg);
	}
	75% {
		opacity: 1;
		transform: rotate3d(0, 0, 1, 70deg);
	}
	100% {
		opacity: 0;
		transform: translate3d(-200px, 200px, 0);
	}
}
@keyframes fall-in {
	0% {
		opacity: 0;
		transform: translate3d(0, -200px, 0);
	}
	50% {
		opacity:...

Vue

console.clear();

Vue.component('component1', {
	name: 'component1',
	template: '<div class="card"><p>This is the first component.</p></div>'
});

Vue.component('component2', {
	name: 'component2',
	template: '<div class="card"><p>This is the second component.</p></div>'
});

Vue.component('transition-switcher', {
	name: 'transition-switcher',
	props: {
		selected: String
	},
	template: '<transition :name="selected" mode="out-in"><slot></slot></transition>'
});

new Vue({
  el: "#app",
	
	data: function () {
		return {
			currentComponent: 'component1',
			selected: ''
		}
	},
	
	methods: {
		clickHandler: function () {
			this.currentComponent = this.currentComponent === 'component1' ? 'component2' : 'component1';
		}
	},
})