Cut the release notes
One page, in the order a new user meets things. No changelog archaeology.
Blocks / Kanban
A three-column board whose cards actually move: drag them between columns and the counts keep up.
One page, in the order a new user meets things. No changelog archaeology.
Move it to the new domain before the announcement, not after.
Three spots still show the grey box. Draw the simple versions.
One take per part, no voiceover — the cursor does the talking.
Every claim on the page must be true on the day it ships.
November entry is written and linked from the footer.
Everyone in, everyone emailed, the form now says so.
Built from: Badge, Avatar — include their CSS alongside this block.
<div class="k-kan" data-kan>
<section class="k-kan-col">
<div class="k-kan-h">Backlog<span class="cnt" data-kan-cnt>0</span></div>
<div class="k-kan-list"><article class="k-kan-card" draggable="true">
<h4>Cut the release notes</h4><p>One page, in the order a new user meets things. No changelog archaeology.</p>
<div class="k-kan-meta"><span class="badge teal">Docs</span><span class="k-avatar" data-size="sm" aria-hidden="true">AR</span></div>
</article><article class="k-kan-card" draggable="true">
<h4>Migrate the status page</h4><p>Move it to the new domain before the announcement, not after.</p>
<div class="k-kan-meta"><span class="badge teal">Ops</span><span class="k-avatar" data-size="sm" aria-hidden="true">MK</span></div>
</article><article class="k-kan-card" draggable="true">
<h4>Empty-state illustrations</h4><p>Three spots still show the grey box. Draw the simple versions.</p>
<div class="k-kan-meta"><span class="badge teal">Design</span><span class="k-avatar" data-size="sm" aria-hidden="true">TS</span></div>
</article></div>
</section>
<section class="k-kan-col">
<div class="k-kan-h">In progress<span class="cnt" data-kan-cnt>0</span></div>
<div class="k-kan-list"><article class="k-kan-card" draggable="true">
<h4>Record the 90-second demo</h4><p>One take per part, no voiceover — the cursor does the talking.</p>
<div class="k-kan-meta"><span class="badge teal">Release</span><span class="k-avatar" data-size="sm" aria-hidden="true">AR</span></div>
</article><article class="k-kan-card" draggable="true">
<h4>Review the pricing copy</h4><p>Every claim on the page must be true on the day it ships.</p>
<div class="k-kan-meta"><span class="badge teal">Docs</span><span class="k-avatar" data-size="sm" aria-hidden="true">MK</span></div>
</article></div>
</section>
<section class="k-kan-col">
<div class="k-kan-h">Done<span class="cnt" data-kan-cnt>0</span></div>
<div class="k-kan-list"><article class="k-kan-card" draggable="true">
<h4>Ship the changelog</h4><p>November entry is written and linked from the footer.</p>
<div class="k-kan-meta"><span class="badge teal">Release</span><span class="k-avatar" data-size="sm" aria-hidden="true">TS</span></div>
</article><article class="k-kan-card" draggable="true">
<h4>Close the beta list</h4><p>Everyone in, everyone emailed, the form now says so.</p>
<div class="k-kan-meta"><span class="badge teal">Ops</span><span class="k-avatar" data-size="sm" aria-hidden="true">AR</span></div>
</article></div>
</section>
</div>/* KATA Kanban (Block) — columns, cards, and honest counts. */
.k-kan{display:grid;grid-template-columns:repeat(3,minmax(225px,1fr));gap:13px;font-family:var(--k-font);color:var(--k-ink);align-items:start}
.k-kan-col{background:var(--k-bg-soft);border:1px solid var(--k-line);border-radius:14px;padding:10px;min-height:180px}
.k-kan-col.over{outline:2px dashed var(--k-accent-line);outline-offset:-6px}
.k-kan-h{display:flex;align-items:center;gap:8px;padding:3px 6px 10px;font-size:12.5px;font-weight:650;letter-spacing:.02em}
.k-kan-h .cnt{margin-inline-start:auto;font-size:11.5px;font-weight:600;color:var(--k-ink-3);background:var(--k-bg);border:1px solid var(--k-line);border-radius:99px;padding:1px 8px}
.k-kan-list{display:flex;flex-direction:column;gap:9px;min-height:60px}
.k-kan-card{background:var(--k-bg);border:1px solid var(--k-line);border-radius:11px;padding:11px 12px;box-shadow:0 1px 2px rgba(16,24,40,.05);cursor:grab}
.k-kan-card:active{cursor:grabbing}
.k-kan-card.drag{opacity:.45}
.k-kan-card h4{font-size:13.5px;font-weight:600;line-height:1.5}
.k-kan-card p{font-size:12.5px;color:var(--k-ink-2);line-height:1.65;margin-top:4px}
.k-kan-meta{display:flex;align-items:center;gap:8px;margin-top:10px}
.k-kan-meta .k-avatar{margin-inline-start:auto}
@media (max-width:760px){.k-kan{grid-template-columns:1fr}}
// KATA Kanban (Block) — HTML5 drag between columns; counts recount.
document.querySelectorAll('[data-kan]').forEach(function (board) {
var dragged = null;
function recount() {
board.querySelectorAll('.k-kan-col').forEach(function (col) {
col.querySelector('[data-kan-cnt]').textContent = col.querySelectorAll('.k-kan-card').length;
});
}
board.querySelectorAll('.k-kan-card').forEach(function (card) {
card.addEventListener('dragstart', function () { dragged = card; card.classList.add('drag'); });
card.addEventListener('dragend', function () {
card.classList.remove('drag');
board.querySelectorAll('.k-kan-col').forEach(function (c) { c.classList.remove('over'); });
recount();
});
});
board.querySelectorAll('.k-kan-col').forEach(function (col) {
col.addEventListener('dragover', function (e) { e.preventDefault(); col.classList.add('over'); });
col.addEventListener('dragleave', function () { col.classList.remove('over'); });
col.addEventListener('drop', function (e) {
e.preventDefault();
if (dragged) col.querySelector('.k-kan-list').appendChild(dragged);
col.classList.remove('over');
recount();
});
});
recount();
});
node kata-ui.mjs add kanban
Writes the block’s CSS and JS into your project. Everything it is built from comes with it. New to the CLI? See the CLI doc.
tokens.css once, before any part.Columns are lists; cards are articles with draggable="true". The script moves the card in the DOM and recounts — persisting the order (and wiring real drag handles for touch) is the app’s layer.