JAVASCRIPT
Animate List Item Transitions with Vue 3 `TransitionGroup`
Add smooth, interactive animations to list items as they are added, removed, or reordered in Vue 3 applications using the built-in `<TransitionGroup>` component.
// App.vue
<template>
<div>
<h1>My Todo List</h1>
<input type="text" v-model="newItemText" @keyup.enter="addItem" placeholder="Add a new todo" />
<button @click="addItem">Add Todo</button>
<button @click="shuffleItems">Shuffle</button>
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.text }}
<button @click="removeItem(item.id)">X</button>
</li>
</TransitionGroup>
</div>
</template>
<script setup>
import { ref } from 'vue';
const newItemText = ref('');
const items = ref([
{ id: 1, text: 'Learn Vue 3' },
{ id: 2, text: 'Build a project' },
{ id: 3, text: 'Deploy to Netlify' }
]);
let nextId = items.value.length + 1;
const addItem = () => {
if (newItemText.value.trim() !== '') {
items.value.push({ id: nextId++, text: newItemText.value.trim() });
newItemText.value = '';
}
};
const removeItem = (id) => {
items.value = items.value.filter(item => item.id !== id);
};
const shuffleItems = () => {
items.value = items.value.sort(() => Math.random() - 0.5);
};
</script>
<style>
/* REQUIRED: provide a transition name like 'list' */
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* Ensure leaving items don't affect layout during transition */
.list-leave-active {
position: absolute;
}
.list-move {
transition: transform 0.5s ease;
}
</style>
How it works: This snippet showcases `<TransitionGroup>` in Vue 3 to animate list item additions, removals, and reordering. By wrapping a list (`ul`) with `TransitionGroup` and applying CSS transitions, items smoothly fade and slide in/out. The `list-move` class handles position changes for items that are reordered, creating a fluid user experience. Each item *must* have a unique `:key` for `TransitionGroup` to work correctly.