Brand board revisions, the five dashboard mockups with their verify
script and evidence, the slice 1 S5 design note (SLICE1-VIEWS.md, rev 3
plus the S2c section 10 update), the Console mockup of inbox, tasks,
agents and trail (mockups/slice1/) and checks/slice1-verify.mjs (16
checks; check 16 pinned to bus at d27042fa). Also the CHAT-03 progress
log and the 2026-09-26 dirty-tree manifest. Design and evidence only;
no package code. Row 40 (#1522), committed on its own at Sage's
direction, 2026-10-09.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
46 lines
4.4 KiB
HTML
46 lines
4.4 KiB
HTML
<!doctype html>
|
|
<html lang="en" data-design="board" data-palette="harbor" data-mode="light">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Control board · Mosaic Stack (Board)</title>
|
|
<meta name="description" content="Mosaic Stack web interface mockup, design 4: kanban columns by session state. Prototype only; every action is simulated.">
|
|
<link rel="stylesheet" href="shared/app.css">
|
|
<link rel="stylesheet" href="d4-board.css">
|
|
</head>
|
|
<body>
|
|
<a class="skip" href="#main">Skip to content</a>
|
|
<div id="shell" class="shell"></div>
|
|
<div id="toasts"></div>
|
|
<div id="announce" class="sr-only" aria-live="polite" aria-atomic="true"></div>
|
|
<script src="../brand.js"></script>
|
|
<script src="shared/data.js"></script>
|
|
<script src="shared/views.js"></script>
|
|
<script>
|
|
window.DesignLayout = {
|
|
id: 'board', name: 'Board',
|
|
nav: [["/","home","Control board"],["/sessions","conversation","Sessions"],["/work","board","Work"],["/projects","projects","Projects"],["/agents","agents","Agents"],["/runs","check","Runs"],["/messages","people","Messages"],["/library","extensions","Library"],["/settings","sun","Settings"]],
|
|
shell(ctx, V) {
|
|
const B = window.Brand, D = window.MosaicData;
|
|
return `<header class="bar"><a href="#/" class="wordmark"><i>M</i>Mosaic Stack<small>prototype</small></a>
|
|
<nav class="bar-nav" aria-label="Primary"><ul>${this.nav.map(([h, i, l]) => `<li><a href="#${h}" data-nav class="bar-link">${V.icon(i)}<span>${l}</span></a></li>`).join('')}</ul></nav>
|
|
<div class="bar-right"><label class="sr-only" for="demo-board">Demo state</label><select id="demo-board" data-demo class="demo-select">${['normal','loading','empty','error'].map(s => `<option value="${s}" ${ctx.demoState === s ? 'selected' : ''}>${s}</option>`).join('')}</select><a href="#/settings" class="btn" data-nav aria-label="Settings and appearance">${V.icon('sun')}<span class="bar-theme" data-theme-summary></span></a><a href="#/launch" class="btn primary" data-nav>${V.icon('plus', 'Launch')}</a></div></header>
|
|
<main id="main" tabindex="-1" class="content"></main>
|
|
<footer class="foot"><span>Mosaic Stack web interface mockup · design 4 Board</span><span>Prototype. Actions are simulated.</span><a href="index.html">All designs</a></footer>`;
|
|
},
|
|
home(ctx, V) {
|
|
const D = window.MosaicData; const f = ctx.params.project || 'all';
|
|
const groups = [['Waiting on you', ['waiting','blocked'], 'attn'], ['Running', ['running'], 'ok'], ['Quiet wait', ['quiet'], 'muted'], ['Stalled', ['stalled'], 'danger'], ['Settled', ['settled','stopped'], 'muted']];
|
|
const filtered = f === 'all' ? D.sessions : D.sessions.filter(s => s.project === f);
|
|
const cols = groups.map(([title, states, tone]) => { const list = filtered.filter(s => states.includes(s.state)); return `<section class="column column-${tone}" aria-labelledby="col-${states[0]}"><h2 id="col-${states[0]}">${title} <span class="count">${list.length}</span></h2>${list.map(s => { const w = D.waiting.find(x => x.session === s.id); return V.sessionCard(s).replace('</footer>', '</footer>' + (w ? `<p class="card-wait"><b>${V.esc(w.title)}</b> ${V.esc(w.detail)}</p><div class="actions">${w.actions.map((a, i) => V.actionLink(a, i === 0 ? 'btn primary' : 'btn')).join('')}</div>` : '')); }).join('') || '<p class="column-empty">None</p>'}</section>`; }).join('');
|
|
return `<div class="page-head"><h1>Control board</h1><p class="muted">Sessions grouped by what they need. Columns are state, not priority; the first column always needs you. ${V.feat('proposed')}</p></div>
|
|
<nav class="chips" aria-label="Filter by project"><a href="#/" class="chip" ${f === 'all' ? 'aria-current="true"' : ''}>All projects</a>${D.projects.map(p => `<a href="#/?project=${p.id}" class="chip" ${f === p.id ? 'aria-current="true"' : ''}>${V.esc(p.name)} <span class="count">${D.sessions.filter(s => s.project === p.id && !['settled','stopped'].includes(s.state)).length}</span></a>`).join('')}</nav>
|
|
${V.stateWrap(ctx, 'sessions', `<div class="columns board-columns">${cols}</div>`, {skeleton: 4, emptyAction: ['Launch an agent', '#/launch']})}
|
|
<div class="board-lower"><section class="panel" aria-labelledby="h-act"><h2 id="h-act">Activity</h2>${V.eventStream(ctx, 6)}</section><section class="panel" aria-labelledby="h-ql">${V.quickLaunch()}</section></div>`;
|
|
},
|
|
};
|
|
</script>
|
|
<script src="shared/app.js"></script>
|
|
</body>
|
|
</html>
|