Delivery — Warehouse / Picking
A warehouse picking console for a fictional fulfillment floor, pairing a prioritized pick-list queue with an active list that shows item rows, bin locations, quantities and scan-to-pick check-off. A big picked counter and progress rail track completion, a low-stock inventory table flags SKUs below reorder point, and a schematic Zone B map teaser animates a driver marker along the route to the next bin as picks are confirmed and lists completed.
MCP
Code
:root {
--brand: #ff5a2c;
--brand-d: #e0461d;
--ink: #16181d;
--ink-2: #3b3f4a;
--muted: #71757f;
--bg: #f4f5f7;
--surface: #ffffff;
--line: rgba(22, 24, 29, 0.1);
--ok: #1f9d62;
--warn: #e89422;
--danger: #d4493e;
--track: #5b8def;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 20px;
--shadow-sm: 0 1px 2px rgba(22, 24, 29, 0.06), 0 1px 3px rgba(22, 24, 29, 0.05);
--shadow-md: 0 6px 18px rgba(22, 24, 29, 0.08), 0 2px 6px rgba(22, 24, 29, 0.05);
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
margin: 0;
font-family: "Inter", system-ui, -apple-system, sans-serif;
background: var(--bg);
color: var(--ink);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1, h2 { margin: 0; line-height: 1.2; letter-spacing: -0.01em; }
.shell {
max-width: 1180px;
margin: 0 auto;
padding: 18px;
}
/* ---------- topbar ---------- */
.topbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 14px;
padding: 14px 18px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
box-shadow: var(--shadow-sm);
margin-bottom: 16px;
}
.brand { display: flex; align-items: center; gap: 12px; }
.brand-mark {
width: 40px; height: 40px;
display: grid; place-items: center;
border-radius: var(--r-md);
background: linear-gradient(150deg, var(--brand), var(--brand-d));
color: #fff;
font-size: 20px;
box-shadow: 0 4px 12px rgba(255, 90, 44, 0.35);
}
.brand strong { display: block; font-size: 15px; font-weight: 800; }
.brand-sub { font-size: 12px; color: var(--muted); font-weight: 500; }
.picker-chip {
display: flex; align-items: center; gap: 10px;
padding: 6px 12px 6px 6px;
border: 1px solid var(--line);
border-radius: 999px;
background: var(--bg);
}
.avatar {
width: 34px; height: 34px;
display: grid; place-items: center;
border-radius: 50%;
background: var(--ink);
color: #fff;
font-size: 12px; font-weight: 700;
}
.picker-meta { display: flex; flex-direction: column; }
.picker-name { font-size: 13px; font-weight: 700; }
.picker-id { font-size: 11px; color: var(--muted); }
/* ---------- layout ---------- */
.layout {
display: grid;
grid-template-columns: 1.5fr 1fr;
gap: 16px;
align-items: start;
}
.panel {
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
box-shadow: var(--shadow-sm);
padding: 18px;
}
.panel-head {
display: flex; align-items: center; justify-content: space-between;
gap: 10px;
margin-bottom: 14px;
}
.panel-head.tight { margin-bottom: 12px; }
.panel-head h1 { font-size: 19px; font-weight: 800; }
.panel-head h2 { font-size: 15px; font-weight: 700; }
.queue-count {
font-size: 12px; font-weight: 600;
color: var(--brand-d);
background: rgba(255, 90, 44, 0.1);
padding: 4px 10px;
border-radius: 999px;
}
/* ---------- queue ---------- */
.queue { list-style: none; margin: 0 0 18px; padding: 0; display: grid; gap: 8px; }
.queue-item {
display: flex; align-items: center; gap: 12px;
width: 100%;
text-align: left;
padding: 10px 12px;
border: 1px solid var(--line);
border-radius: var(--r-md);
background: var(--surface);
cursor: pointer;
font: inherit; color: inherit;
transition: border-color .15s, box-shadow .15s, transform .05s;
}
.queue-item:hover { border-color: rgba(91, 141, 239, 0.5); box-shadow: var(--shadow-sm); }
.queue-item:active { transform: translateY(1px); }
.queue-item:focus-visible { outline: 2px solid var(--track); outline-offset: 2px; }
.queue-item.is-active { border-color: var(--brand); background: rgba(255, 90, 44, 0.05); }
.queue-item.is-done { opacity: 0.6; }
.qi-rank {
width: 28px; height: 28px; flex: 0 0 28px;
display: grid; place-items: center;
border-radius: var(--r-sm);
background: var(--bg);
font-size: 12px; font-weight: 700; color: var(--ink-2);
}
.queue-item.is-active .qi-rank { background: var(--brand); color: #fff; }
.qi-body { flex: 1; min-width: 0; }
.qi-title { font-size: 13px; font-weight: 700; }
.qi-meta { font-size: 11px; color: var(--muted); }
.pill {
font-size: 11px; font-weight: 700;
padding: 3px 9px; border-radius: 999px;
white-space: nowrap;
}
.pill.priority { color: var(--brand-d); background: rgba(255, 90, 44, 0.12); }
.pill.standard { color: var(--ink-2); background: var(--bg); }
.pill.done { color: var(--ok); background: rgba(31, 157, 98, 0.12); }
/* ---------- active pick ---------- */
.active-pick {
border: 1px solid var(--line);
border-radius: var(--r-md);
padding: 16px;
background: linear-gradient(180deg, #fbfbfc, var(--surface));
}
.active-head { display: flex; justify-content: space-between; gap: 14px; align-items: flex-start; }
.eyebrow {
font-size: 11px; font-weight: 700; text-transform: uppercase;
letter-spacing: 0.06em; color: var(--brand-d);
}
.active-head h2 { font-size: 18px; font-weight: 800; margin: 2px 0; }
.active-sub { margin: 0; font-size: 12px; color: var(--muted); }
.big-progress {
flex: 0 0 auto; text-align: right;
display: flex; align-items: baseline; gap: 2px; flex-wrap: wrap;
justify-content: flex-end;
}
.bp-num { font-size: 32px; font-weight: 800; color: var(--ink); line-height: 1; }
.bp-den { font-size: 18px; font-weight: 700; color: var(--muted); }
.bp-label { width: 100%; font-size: 10px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.progress-rail {
height: 8px; border-radius: 999px;
background: var(--bg);
overflow: hidden;
margin: 14px 0 16px;
}
.progress-fill {
display: block; height: 100%; width: 0%;
background: linear-gradient(90deg, var(--brand), var(--brand-d));
border-radius: 999px;
transition: width .35s cubic-bezier(.4, 0, .2, 1);
}
/* ---------- picks ---------- */
.picks { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 8px; }
.pick {
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 12px;
padding: 11px 12px;
border: 1px solid var(--line);
border-radius: var(--r-md);
background: var(--surface);
transition: border-color .15s, background .15s;
}
.pick.checked { background: rgba(31, 157, 98, 0.06); border-color: rgba(31, 157, 98, 0.4); }
.pick-check {
width: 26px; height: 26px;
border: 2px solid var(--line);
border-radius: 7px;
background: var(--surface);
cursor: pointer;
display: grid; place-items: center;
color: transparent;
transition: background .15s, border-color .15s, color .15s;
padding: 0;
}
.pick-check:hover { border-color: var(--ok); }
.pick-check:focus-visible { outline: 2px solid var(--track); outline-offset: 2px; }
.pick.checked .pick-check { background: var(--ok); border-color: var(--ok); color: #fff; }
.pick-check svg { width: 14px; height: 14px; }
.pick-info { min-width: 0; }
.pick-name { font-size: 13px; font-weight: 600; }
.pick.checked .pick-name { text-decoration: line-through; color: var(--muted); }
.pick-sub { font-size: 11px; color: var(--muted); display: flex; gap: 8px; flex-wrap: wrap; }
.pick-sku { font-variant-numeric: tabular-nums; }
.pick-right { display: flex; align-items: center; gap: 8px; }
.bin-tag {
font-size: 12px; font-weight: 700;
font-variant-numeric: tabular-nums;
color: var(--track);
background: rgba(91, 141, 239, 0.12);
padding: 4px 9px; border-radius: var(--r-sm);
white-space: nowrap;
}
.qty-tag {
font-size: 12px; font-weight: 700;
color: var(--ink-2);
background: var(--bg);
padding: 4px 9px; border-radius: var(--r-sm);
white-space: nowrap;
}
.active-foot { display: flex; gap: 10px; justify-content: flex-end; }
.btn {
font: inherit; font-weight: 700; font-size: 13px;
padding: 10px 16px;
border-radius: var(--r-md);
border: 1px solid transparent;
cursor: pointer;
transition: background .15s, border-color .15s, transform .05s, opacity .15s;
}
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 2px solid var(--track); outline-offset: 2px; }
.btn.ghost { background: var(--surface); border-color: var(--line); color: var(--ink-2); }
.btn.ghost:hover { background: var(--bg); }
.btn.primary { background: var(--brand); color: #fff; box-shadow: 0 4px 12px rgba(255, 90, 44, 0.3); }
.btn.primary:hover:not(:disabled) { background: var(--brand-d); }
.btn.primary:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
/* ---------- side / zone map ---------- */
.side { display: grid; gap: 16px; }
.zone-card, .inv-card { display: block; }
.zone-card + .inv-card { border-top: 1px solid var(--line); padding-top: 16px; }
.legend { font-size: 11px; color: var(--muted); display: inline-flex; align-items: center; gap: 6px; }
.dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.dot-active { background: var(--track); }
.dot-low { background: var(--warn); margin-left: 6px; }
.zone-map {
position: relative;
height: 180px;
border-radius: var(--r-md);
border: 1px solid var(--line);
background-color: #fafbfc;
background-image:
linear-gradient(var(--line) 1px, transparent 1px),
linear-gradient(90deg, var(--line) 1px, transparent 1px);
background-size: 30px 30px;
overflow: hidden;
}
.route { position: absolute; inset: 0; width: 100%; height: 100%; }
#marker { transition: cx .8s ease, cy .8s ease; filter: drop-shadow(0 1px 3px rgba(0,0,0,.3)); }
.zone-note { font-size: 12px; color: var(--muted); margin: 10px 0 0; }
.zone-note strong { color: var(--track); font-variant-numeric: tabular-nums; }
/* ---------- inventory ---------- */
.lowfilter { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; cursor: pointer; }
.lowfilter input { accent-color: var(--brand); width: 15px; height: 15px; }
.table-wrap { overflow-x: auto; }
.inv { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.inv th {
text-align: left; font-weight: 600; font-size: 11px;
text-transform: uppercase; letter-spacing: .04em; color: var(--muted);
padding: 8px 8px; border-bottom: 1px solid var(--line);
}
.inv th.num, .inv td.num { text-align: right; font-variant-numeric: tabular-nums; }
.inv td { padding: 9px 8px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.inv tbody tr:last-child td { border-bottom: none; }
.inv tbody tr.is-low { background: rgba(232, 148, 34, 0.06); }
.inv tbody tr:hover { background: var(--bg); }
.sku-name { font-weight: 600; color: var(--ink); }
.sku-id { font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.bin-cell { font-variant-numeric: tabular-nums; color: var(--ink-2); }
.stat {
font-size: 11px; font-weight: 700;
padding: 3px 8px; border-radius: 999px;
white-space: nowrap;
}
.stat.ok { color: var(--ok); background: rgba(31, 157, 98, 0.12); }
.stat.low { color: var(--warn); background: rgba(232, 148, 34, 0.15); }
.stat.out { color: var(--danger); background: rgba(212, 73, 62, 0.12); }
.inv-foot { font-size: 11.5px; color: var(--muted); margin: 12px 0 0; }
.empty-row td { text-align: center; color: var(--muted); padding: 22px 8px; font-style: italic; }
/* ---------- toast ---------- */
.toast-wrap {
position: fixed; left: 50%; bottom: 22px;
transform: translateX(-50%);
display: grid; gap: 8px; z-index: 50;
width: max-content; max-width: 92vw;
}
.toast {
background: var(--ink); color: #fff;
font-size: 13px; font-weight: 600;
padding: 11px 16px;
border-radius: var(--r-md);
box-shadow: var(--shadow-md);
display: flex; align-items: center; gap: 9px;
animation: toast-in .25s ease;
}
.toast.ok { background: var(--ok); }
.toast.warn { background: var(--warn); }
.toast .t-ico { font-size: 15px; }
@keyframes toast-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
/* ---------- responsive ---------- */
@media (max-width: 880px) {
.layout { grid-template-columns: 1fr; }
}
@media (max-width: 520px) {
.shell { padding: 12px; }
.topbar { border-radius: var(--r-md); padding: 12px; }
.picker-id { display: none; }
.panel { padding: 14px; border-radius: var(--r-md); }
.active-head { flex-direction: column; gap: 6px; }
.big-progress { justify-content: flex-start; text-align: left; }
.bp-label { width: auto; }
.active-foot { flex-direction: column-reverse; }
.active-foot .btn { width: 100%; }
.pick { grid-template-columns: auto 1fr; }
.pick-right { grid-column: 1 / -1; justify-content: flex-start; padding-left: 38px; }
}(function () {
"use strict";
/* ---------- data (fictional) ---------- */
var lists = [
{
id: "PL-2291",
order: "Order #88204",
sub: "Wave 3 · Priority · Carrier cutoff 14:30",
priority: "priority",
done: false,
picks: [
{ sku: "TRL-0042", name: "Trail Runner Sock 3-pack", bin: "B-12-A", qty: 2, route: [30, 150] },
{ sku: "HYD-0118", name: "Hydro Flask 32oz Slate", bin: "B-12-C", qty: 1, route: [90, 150] },
{ sku: "LMP-0905", name: "Folding Camp Lantern", bin: "B-07-B", qty: 1, route: [90, 60] },
{ sku: "TNT-2210", name: "2-Person Ridge Tent", bin: "B-04-A", qty: 1, route: [180, 60] },
{ sku: "GLV-0331", name: "Insulated Work Gloves L", bin: "B-09-D", qty: 3, route: [180, 120] },
{ sku: "BTL-0077", name: "Stainless Bottle 18oz", bin: "B-15-A", qty: 2, route: [260, 120] },
{ sku: "MAP-0451", name: "Topo Trail Map Set", bin: "B-21-C", qty: 1, route: [260, 30] },
{ sku: "BAR-1290", name: "Oat Energy Bar Box", bin: "B-22-A", qty: 4, route: [260, 30] }
]
},
{
id: "PL-2294",
order: "Order #88219",
sub: "Wave 3 · Standard · Carrier cutoff 16:00",
priority: "standard",
done: false,
picks: []
},
{
id: "PL-2298",
order: "Order #88231",
sub: "Wave 4 · Standard · Carrier cutoff 16:00",
priority: "standard",
done: false,
picks: []
}
];
var inventory = [
{ sku: "TRL-0042", name: "Trail Runner Sock 3-pack", bin: "B-12-A", qty: 142, reorder: 60 },
{ sku: "HYD-0118", name: "Hydro Flask 32oz Slate", bin: "B-12-C", qty: 38, reorder: 40 },
{ sku: "LMP-0905", name: "Folding Camp Lantern", bin: "B-07-B", qty: 9, reorder: 25 },
{ sku: "TNT-2210", name: "2-Person Ridge Tent", bin: "B-04-A", qty: 71, reorder: 30 },
{ sku: "GLV-0331", name: "Insulated Work Gloves L", bin: "B-09-D", qty: 0, reorder: 50 },
{ sku: "BTL-0077", name: "Stainless Bottle 18oz", bin: "B-15-A", qty: 88, reorder: 45 },
{ sku: "MAP-0451", name: "Topo Trail Map Set", bin: "B-21-C", qty: 210, reorder: 80 },
{ sku: "BAR-1290", name: "Oat Energy Bar Box", bin: "B-22-A", qty: 17, reorder: 35 },
{ sku: "PCK-0612", name: "Daypack 22L Pine", bin: "B-03-B", qty: 64, reorder: 30 },
{ sku: "HAT-0440", name: "Wide-Brim Sun Hat", bin: "B-18-A", qty: 121, reorder: 50 },
{ sku: "STV-1004", name: "Compact Trail Stove", bin: "B-05-C", qty: 27, reorder: 20 },
{ sku: "RPE-0290", name: "Static Rope 30m", bin: "B-11-D", qty: 95, reorder: 40 }
];
var activeIdx = 0;
/* ---------- helpers ---------- */
var $ = function (s, r) { return (r || document).querySelector(s); };
var checkSvg = '<svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M5 12.5l4.2 4.2L19 7" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></svg>';
function toast(msg, kind) {
var wrap = $("#toastWrap");
var el = document.createElement("div");
el.className = "toast" + (kind ? " " + kind : "");
var ico = kind === "ok" ? "✓" : kind === "warn" ? "!" : "›";
el.innerHTML = '<span class="t-ico" aria-hidden="true">' + ico + "</span><span>" + msg + "</span>";
wrap.appendChild(el);
setTimeout(function () {
el.style.transition = "opacity .3s, transform .3s";
el.style.opacity = "0";
el.style.transform = "translateY(8px)";
setTimeout(function () { el.remove(); }, 320);
}, 2600);
}
function statusFor(item) {
if (item.qty === 0) return "out";
if (item.qty <= item.reorder) return "low";
return "ok";
}
/* ---------- queue render ---------- */
function renderQueue() {
var q = $("#queue");
q.innerHTML = "";
var remaining = 0;
lists.forEach(function (l, i) {
if (!l.done) remaining++;
var li = document.createElement("li");
var btn = document.createElement("button");
btn.type = "button";
btn.className = "queue-item" + (i === activeIdx ? " is-active" : "") + (l.done ? " is-done" : "");
btn.setAttribute("role", "tab");
btn.setAttribute("aria-selected", i === activeIdx ? "true" : "false");
var count = l.picks.length || (l.id === "PL-2294" ? 5 : 6);
var pillCls = l.done ? "done" : l.priority;
var pillTxt = l.done ? "Done" : (l.priority === "priority" ? "Priority" : "Standard");
btn.innerHTML =
'<span class="qi-rank">' + (i + 1) + "</span>" +
'<span class="qi-body"><span class="qi-title">' + l.id + " · " + l.order + "</span>" +
'<span class="qi-meta">' + count + " lines · " + l.sub.split(" · ")[1] + "</span></span>" +
'<span class="pill ' + pillCls + '">' + pillTxt + "</span>";
btn.addEventListener("click", function () { selectList(i); });
li.appendChild(btn);
q.appendChild(li);
});
$("#queueCount").textContent = remaining + " in queue";
}
/* ---------- active list render ---------- */
function renderActive() {
var l = lists[activeIdx];
$("#apId").textContent = l.id;
$("#apOrder").textContent = l.order;
$("#apSub").textContent = l.sub;
var ol = $("#picks");
ol.innerHTML = "";
if (!l.picks.length) {
var p = document.createElement("li");
p.className = "pick";
p.style.gridTemplateColumns = "1fr";
p.innerHTML = '<span class="pick-name">No lines staged yet for this list.</span>';
ol.appendChild(p);
$("#completeBtn").disabled = true;
updateProgress();
return;
}
l.picks.forEach(function (item, idx) {
var li = document.createElement("li");
li.className = "pick" + (item.checked ? " checked" : "");
li.innerHTML =
'<button class="pick-check" type="button" aria-pressed="' + (item.checked ? "true" : "false") +
'" aria-label="Scan-to-pick ' + item.name + '">' + checkSvg + "</button>" +
'<span class="pick-info"><span class="pick-name">' + item.name + "</span>" +
'<span class="pick-sub"><span class="pick-sku">SKU ' + item.sku + "</span></span></span>" +
'<span class="pick-right"><span class="bin-tag">' + item.bin + '</span>' +
'<span class="qty-tag">×' + item.qty + "</span></span>";
li.querySelector(".pick-check").addEventListener("click", function () { togglePick(idx); });
ol.appendChild(li);
});
updateProgress();
}
function togglePick(idx) {
var l = lists[activeIdx];
var item = l.picks[idx];
item.checked = !item.checked;
renderActive();
moveMarker();
if (item.checked) {
toast("Picked " + item.qty + " × " + item.name, "ok");
}
}
function updateProgress() {
var l = lists[activeIdx];
var total = l.picks.length;
var done = l.picks.filter(function (p) { return p.checked; }).length;
$("#bpNum").textContent = done;
$(".bp-den").textContent = "/" + (total || 0);
var pct = total ? (done / total) * 100 : 0;
$("#fill").style.width = pct + "%";
var rail = $("#rail");
rail.setAttribute("aria-valuemax", total);
rail.setAttribute("aria-valuenow", done);
$("#completeBtn").disabled = !(total && done === total);
// next bin
var next = l.picks.find(function (p) { return !p.checked; });
$("#nextBin").textContent = next ? next.bin : "— all picked —";
}
function moveMarker() {
var l = lists[activeIdx];
if (!l.picks.length) return;
var next = l.picks.find(function (p) { return !p.checked; });
var target = next ? next.route : l.picks[l.picks.length - 1].route;
var m = $("#marker");
if (m && target) {
m.setAttribute("cx", target[0]);
m.setAttribute("cy", target[1]);
}
}
function selectList(i) {
activeIdx = i;
renderQueue();
renderActive();
moveMarker();
toast("Opened " + lists[i].id);
}
/* ---------- inventory render ---------- */
function renderInventory() {
var body = $("#invBody");
var lowOnly = $("#lowOnly").checked;
body.innerHTML = "";
var lowCount = 0;
var shown = 0;
inventory.forEach(function (item) {
var st = statusFor(item);
if (st !== "ok") lowCount++;
if (lowOnly && st === "ok") return;
shown++;
var tr = document.createElement("tr");
if (st !== "ok") tr.className = "is-low";
var label = st === "out" ? "Out of stock" : st === "low" ? "Below reorder" : "In stock";
tr.innerHTML =
'<td><span class="sku-name">' + item.name + "</span><br>" +
'<span class="sku-id">' + item.sku + "</span></td>" +
'<td class="bin-cell">' + item.bin + "</td>" +
'<td class="num">' + item.qty + "</td>" +
'<td><span class="stat ' + st + '">' + label + "</span></td>";
body.appendChild(tr);
});
if (!shown) {
var tr = document.createElement("tr");
tr.className = "empty-row";
tr.innerHTML = '<td colspan="4">No SKUs match this filter.</td>';
body.appendChild(tr);
}
$("#invFoot").textContent =
inventory.length + " SKUs · " + lowCount + " below reorder point";
}
/* ---------- actions ---------- */
$("#resetBtn").addEventListener("click", function () {
var l = lists[activeIdx];
l.picks.forEach(function (p) { p.checked = false; });
renderActive();
moveMarker();
toast("Checks reset for " + l.id, "warn");
});
$("#completeBtn").addEventListener("click", function () {
var l = lists[activeIdx];
l.done = true;
toast(l.id + " completed — staged for packing", "ok");
// advance to next undone list
var nextIdx = lists.findIndex(function (x) { return !x.done; });
activeIdx = nextIdx === -1 ? activeIdx : nextIdx;
renderQueue();
renderActive();
moveMarker();
});
$("#lowOnly").addEventListener("change", function () {
renderInventory();
toast(this.checked ? "Showing low stock only" : "Showing all SKUs");
});
/* ---------- init ---------- */
renderQueue();
renderActive();
renderInventory();
moveMarker();
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Northbay Fulfillment — Warehouse Picking</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="shell">
<header class="topbar" role="banner">
<div class="brand">
<span class="brand-mark" aria-hidden="true">▣</span>
<div>
<strong>Northbay Fulfillment</strong>
<span class="brand-sub">Pick & Pack · Zone B floor</span>
</div>
</div>
<div class="topbar-right">
<div class="picker-chip" title="Active picker">
<span class="avatar" aria-hidden="true">RM</span>
<div class="picker-meta">
<span class="picker-name">Rosa Medina</span>
<span class="picker-id">Picker #4071 · Cart C-09</span>
</div>
</div>
</div>
</header>
<main class="layout">
<!-- LEFT: pick-list queue + active pick list -->
<section class="panel pick-panel" aria-labelledby="pl-h">
<div class="panel-head">
<h1 id="pl-h">Pick lists</h1>
<span class="queue-count" id="queueCount">3 in queue</span>
</div>
<ul class="queue" id="queue" role="tablist" aria-label="Pick list queue"></ul>
<article class="active-pick" aria-labelledby="ap-h">
<div class="active-head">
<div>
<span class="eyebrow">Active pick list</span>
<h2 id="ap-h"><span id="apId">PL-2291</span> · <span id="apOrder">Order #88204</span></h2>
<p class="active-sub" id="apSub">Wave 3 · Priority · Carrier cutoff 14:30</p>
</div>
<div class="big-progress" aria-hidden="true">
<span class="bp-num" id="bpNum">0</span><span class="bp-den">/8</span>
<span class="bp-label">picked</span>
</div>
</div>
<div class="progress-rail" role="progressbar" aria-valuemin="0" aria-valuemax="8" aria-valuenow="0" id="rail">
<span class="progress-fill" id="fill"></span>
</div>
<ol class="picks" id="picks" aria-label="Items to pick"></ol>
<div class="active-foot">
<button class="btn ghost" id="resetBtn" type="button">Reset checks</button>
<button class="btn primary" id="completeBtn" type="button" disabled>Complete pick list</button>
</div>
</article>
</section>
<!-- RIGHT: zone map teaser + inventory -->
<aside class="panel side" aria-label="Warehouse status">
<section class="zone-card" aria-labelledby="zone-h">
<div class="panel-head tight">
<h2 id="zone-h">Zone B map</h2>
<span class="legend">
<span class="dot dot-active"></span> route
<span class="dot dot-low"></span> low stock
</span>
</div>
<div class="zone-map" id="zoneMap" role="img" aria-label="Schematic of Zone B picking bins with the active pick route highlighted">
<svg class="route" viewBox="0 0 300 180" preserveAspectRatio="none" aria-hidden="true">
<polyline id="routeLine" points="30,150 90,150 90,60 180,60 180,120 260,120 260,30"
fill="none" stroke="var(--track)" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" />
<circle id="marker" r="6" fill="var(--brand)" stroke="#fff" stroke-width="2" cx="30" cy="150" />
</svg>
</div>
<p class="zone-note">Next bin: <strong id="nextBin">B-12-A</strong> · est. walk 22m</p>
</section>
<section class="inv-card" aria-labelledby="inv-h">
<div class="panel-head tight">
<h2 id="inv-h">Inventory levels</h2>
<label class="lowfilter">
<input type="checkbox" id="lowOnly" />
<span>Low stock only</span>
</label>
</div>
<div class="table-wrap">
<table class="inv" id="invTable">
<thead>
<tr>
<th scope="col">SKU / item</th>
<th scope="col">Bin</th>
<th scope="col" class="num">On hand</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody id="invBody"></tbody>
</table>
</div>
<p class="inv-foot" id="invFoot">12 SKUs · 3 below reorder point</p>
</section>
</aside>
</main>
</div>
<div class="toast-wrap" id="toastWrap" aria-live="polite" aria-atomic="true"></div>
<script src="script.js"></script>
</body>
</html>Warehouse / Picking
A floor-level picking console for a fictional fulfillment operation. The left panel holds a prioritized pick-list queue and the active list, where each line shows the item name, SKU, bin location and pick quantity beside a scan-to-pick check button. Checking items off drives a big picked counter and an animated progress rail; the Complete pick list action only unlocks once every line is confirmed, then advances to the next list in the queue.
The right rail combines a schematic Zone B map teaser with the live inventory table. The map is a CSS grid floor plan with an SVG route, and a driver-style marker glides to the next un-picked bin every time a pick is confirmed. The inventory table lists on-hand counts against each SKU’s reorder point, tagging items as in stock, below reorder, or out of stock, with a Low stock only filter to focus the view.
Everything runs on vanilla JavaScript with no dependencies: queue selection, check-off progress, reset, list completion, marker movement, the low-stock filter and toast feedback are all wired by hand. The layout is responsive down to roughly 360px, collapsing to a single mobile-first column, and interactive controls are keyboard-usable with appropriate aria state.
Illustrative UI only — fictional brand, not a real delivery service.