A working kanban (Trello-lite) instantly reads as "this person can build real UI". The native DnD API does the heavy lifting.
The mechanics
<div class="column" data-col="todo"> <h3>To Do</h3> <div class="card" draggable="true" id="c1">Finish CN record</div> </div> <div class="column" data-col="doing">...</div> <div class="column" data-col="done">...</div>
// card side
document.addEventListener("dragstart", (e) => {
if (!e.target.matches(".card")) return;
e.dataTransfer.setData("text/plain", e.target.id);
e.target.classList.add("dragging");
});
document.addEventListener("dragend", (e) => e.target.classList?.remove("dragging"));
// column side
document.querySelectorAll(".column").forEach((col) => {
col.addEventListener("dragover", (e) => {
e.preventDefault(); // REQUIRED to allow dropping
col.classList.add("over");
});
col.addEventListener("dragleave", () => col.classList.remove("over"));
col.addEventListener("drop", (e) => {
e.preventDefault();
col.classList.remove("over");
const card = document.getElementById(e.dataTransfer.getData("text/plain"));
col.append(card);
saveState();
});
});Persistence
function saveState() {
const state = {};
document.querySelectorAll(".column").forEach((col) => {
state[col.dataset.col] = [...col.querySelectorAll(".card")].map(c => c.textContent);
});
localStorage.setItem("kanban", JSON.stringify(state));
}Add card creation, delete on double-click, and column counts. Mobile note: native DnD ignores touch โ mention it honestly or add a pointer-events fallback; knowing the limitation is itself a good interview beat.