Deletes the vanilla shell and mounts App.tsx on #root. main.ts and the
23 views it drove are gone; App.tsx composes the ported components —
sidebar, multi-view, command bar, spawn modal, help and restart
overlays, daemon link, drawer — around the catalog and layout stores.
The pure parts of four deleted modules moved next to the components
that still use them: the spawn-form model and spawnSimilar into
components/spawn, the transcript's markdown/format helpers and the diff
into components/structured, the help overlay's grouping into
components/dialogs. Document-level event names now live in uiEvents.ts.
Deduplicated two pairs the migration left side by side: the sidebar
uses dialogs/KillDialog and common/ContextMenu. It also listens for the
command bar's kill/rename events, which nothing had picked up since
catalog.ts went away.
styles.css stays as the token and base layer, with `#app` renamed to
`#root` and the pane-body rules re-keyed off the classes the React
panes actually carry.
Closes#253
- Add #root div to index.html so React entry point can mount
- Replace unsafe type cast in Sidebar with typed CatalogStore selector
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a web app manifest, icons, and a runtime-caching service worker so the
UI can be installed on Android Chrome (and added to the iOS home screen).
- web/public/manifest.webmanifest: standalone display, theme/bg colors, icon set
- web/public/icon.svg + generated icon-192/512 and apple-touch-icon PNGs
- web/public/sw.js: caches the static shell for offline launch; never touches
/api (HTTP or WS), so live-daemon behavior is unchanged
- index.html: link manifest + apple-touch-icon, iOS standalone metas
- main.ts: register the service worker (production only)
Assets land in web/dist via Vite's public/ dir and are embedded by the
existing include_dir! in maestro-web, so no Rust changes are needed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On Android the soft keyboard overlaid the layout viewport and the browser
auto-scrolled the document on focus, dragging the shell (and its special-key
bar) to the top of the screen and forcing a manual scroll.
- index.html: interactive-widget=resizes-content so Chrome resizes the layout
viewport instead of overlaying the keyboard, killing the auto-scroll.
- viewport.ts: mirror visualViewport.offsetTop into --app-top for iOS / older
browsers that ignore interactive-widget and still scroll under the keyboard.
- styles.css: translateY(--app-top) re-pins #app to the visible region.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrite styles.css as an OKLCH design-system: cool-slate neutrals with a
single committed signal-green for "alive" (running status, primary action,
focus, selection). Monospace becomes the UI typeface; dark is default with a
full light theme via tokens, OS-following with a persisted header toggle.
- catalog: pulsing wordmark, status-bar tally (N sessions / M live) + daemon
chips, color-independent session status (pulsing dot for running, hollow
ring + "exited" badge for dead), reveal-on-hover kill, three teaching
empty states.
- attach: state pill (live/closed/error), framed dark xterm w/ green cursor.
- spawn: bottom-sheet/dialog form, mono inputs with green focus rings.
- a11y: AA contrast both themes, visible focus, prefers-reduced-motion paths,
status never color-only.
- theme.ts: dark/light toggle + persistence; mock.ts: DEV-only review fixture
(?mock / ?mock&spawn / ?theme=), tree-shaken from production builds.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
NAP-218. Browser UI for the prototype: catalog tree derived from
`metadata.label`, live updates over `WS /api/events`, search across
session name+label, spawn modal (with optional git worktree), and an
attach view that opens the daemon's per-session WS for xterm.js.
Framework choice: vanilla TypeScript. The interactivity surface is
small enough that pulling in a framework wouldn't pay back; xterm.js
does the heavy lifting. Easy to swap later without protocol impact.
Hash-based routing (`#/`, `#/attach/<id>`) keeps the registry's
static surface dumb — no SPA fallback needed; concurrent attaches
work by opening the same hash URL in another tab.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>