Build a fully functional Kanban board with drag-and-drop between columns — a great project for mastering Vue 3 component composition and state management.
npm create vue@latest kanban-board
npm install pinia sortablejs vue-draggable-plus
// stores/board.js
export const useBoardStore = defineStore('board', () => {
const columns = ref([
{ id: 'todo', title: 'To Do', cards: [] },
{ id: 'inprogress', title: 'In Progress', cards: [] },
{ id: 'done', title: 'Done', cards: [] },
])
function addCard(columnId, { title, label = 'feature' }) {
const col = columns.value.find(c => c.id === columnId)
col?.cards.push({ id: crypto.randomUUID(), title, label, createdAt: Date.now() })
}
function moveCard(fromColId, toColId, cardId, toIndex) {
const from = columns.value.find(c => c.id === fromColId)
const to = columns.value.find(c => c.id === toColId)
const card = from?.cards.find(c => c.id === cardId)
if (!from || !to || !card) return
from.cards = from.cards.filter(c => c.id !== cardId)
to.cards.splice(toIndex, 0, card)
}
function deleteCard(columnId, cardId) {
const col = columns.value.find(c => c.id === columnId)
if (col) col.cards = col.cards.filter(c => c.id !== cardId)
}
return { columns, addCard, moveCard, deleteCard }
}, { persist: true })
<!-- KanbanColumn.vue -->
<script setup>
import { VueDraggable } from 'vue-draggable-plus'
import KanbanCard from './KanbanCard.vue'
const props = defineProps(['column'])
const emit = defineEmits(['add'])
</script>
<template>
<div class="column">
<h3>{{ column.title }} <span>{{ column.cards.length }}</span></h3>
<VueDraggable
v-model="column.cards"
group="cards"
:animation="150"
class="card-list"
>
<KanbanCard
v-for="card in column.cards"
:key="card.id"
:card="card"
:column-id="column.id"
/>
</VueDraggable>
<button class="add-btn" @click="emit('add', column.id)">+ Add Card</button>
</div>
</template>
All Comments