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.9 KiB
HTML
46 lines
4.9 KiB
HTML
<!doctype html>
|
|
<html lang="en" data-design="stream" 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 (Stream)</title>
|
|
<meta name="description" content="Mosaic Stack web interface mockup, design 5: chronological stream with a pinned inbox; bottom tab bar on phones. Prototype only; every action is simulated.">
|
|
<link rel="stylesheet" href="shared/app.css">
|
|
<link rel="stylesheet" href="d5-stream.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: 'stream', name: 'Stream',
|
|
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"]],
|
|
primary: ['/', '/sessions', '/work', '/messages'],
|
|
shell(ctx, V) {
|
|
const B = window.Brand, D = window.MosaicData;
|
|
const link = ([h, i, l]) => `<li><a href="#${h}" data-nav class="nav-link">${V.icon(i)}<span>${l}</span>${h === '/' ? `<span class="count" aria-label="${D.waiting.length} waiting on you">${D.waiting.length}</span>` : ''}</a></li>`;
|
|
return `<header class="head"><a href="#/" class="wordmark"><i>M</i>Mosaic Stack<small>prototype</small></a><span class="head-sub" data-theme-summary></span><a href="#/launch" class="btn primary head-launch" data-nav>${V.icon('plus', 'Launch')}</a></header>
|
|
<div class="frame"><nav class="side" aria-label="Primary"><ul>${this.nav.map(link).join('')}</ul><div class="side-foot"><label class="sr-only" for="demo-stream">Demo state</label><select id="demo-stream" data-demo class="demo-select">${['normal','loading','empty','error'].map(s => `<option value="${s}" ${ctx.demoState === s ? 'selected' : ''}>${s}</option>`).join('')}</select><p class="prototype-note">Prototype. Actions are simulated.</p></div></nav>
|
|
<main id="main" tabindex="-1" class="content"></main></div>
|
|
<nav class="tabbar" aria-label="Primary, phone"><ul>${this.nav.filter(([h]) => this.primary.includes(h)).map(([h, i, l]) => `<li><a href="#${h}" data-nav class="tab-link">${V.icon(i)}<span>${l}</span>${h === '/' ? `<span class="tab-dot" aria-label="${D.waiting.length} waiting on you">${D.waiting.length}</span>` : ''}</a></li>`).join('')}<li><details class="more" data-overlay><summary class="tab-link">${V.icon('board')}<span>More</span></summary><ul class="more-list">${this.nav.filter(([h]) => !this.primary.includes(h)).map(([h, i, l]) => `<li><a href="#${h}" data-nav class="nav-link">${V.icon(i)}<span>${l}</span></a></li>`).join('')}<li><a href="#/launch" class="nav-link" data-nav>${V.icon('plus')}<span>Launch</span></a></li></ul></details></li></ul></nav>
|
|
<footer class="foot"><span>Mosaic Stack web interface mockup · design 5 Stream</span><a href="index.html">All designs</a></footer>`;
|
|
},
|
|
home(ctx, V) {
|
|
const D = window.MosaicData;
|
|
return `<div class="page-head"><h1>Control board</h1><p class="muted">Your inbox stays pinned. Everything else flows past in time order. ${V.feat('proposed')}</p></div>
|
|
<div class="stream-grid"><section class="panel inbox" aria-labelledby="h-wait"><h2 id="h-wait">Waiting on you <span class="count">${D.waiting.length}</span></h2>${V.waitingList(ctx)}</section>
|
|
<section class="panel" aria-labelledby="h-stream"><h2 id="h-stream">Now</h2>${V.stateWrap(ctx, 'sessions', `<ul class="now-list">${V.running().map(s => `<li>${V.avatar(s.agent)}<a href="#/sessions/${s.id}"><b>${V.esc(V.agentOf(s.agent).name)}</b></a> <span class="muted">${V.esc(s.project)}/${V.esc(s.workspace)}</span> ${V.badge(s.state)}<span class="now-goal">${V.esc(s.goal.report)}</span></li>`).join('')}</ul>`, {skeleton: 5, emptyAction: ['Launch an agent', '#/launch']})}<h2 class="stream-h2">Earlier today</h2>${V.eventStream(ctx, 14)}</section>
|
|
<aside class="stream-side"><section class="panel" aria-labelledby="h-msg"><h2 id="h-msg">Messages <span class="count">${D.messages.filter(m => m.unread).length}</span></h2><ul class="plain">${D.messages.slice(0, 3).map(m => `<li><a href="#/messages?id=${m.id}" class="thread ${m.unread ? 'unread' : ''}">${V.avatar(m.from)}<span><b>${V.esc(V.agentOf(m.from).name)}</b> <span class="muted small">${V.ago(m.when)}</span><br><span class="preview">${V.esc(m.text)}</span></span></a></li>`).join('')}</ul></section><section class="panel">${V.quickLaunch()}</section></aside></div>`;
|
|
},
|
|
afterRender() { document.querySelectorAll('details.more[open]').forEach(d => d.removeAttribute('open')); },
|
|
};
|
|
</script>
|
|
<script src="shared/app.js"></script>
|
|
</body>
|
|
</html>
|