mirror of
https://github.com/ruvnet/RuView
synced 2026-08-01 19:01:42 +00:00
feat(dashboard): iter G+H+I + P0.10 — modal forms, a11y pass, drag persistence, REPL history
Closes ADR-093 P0.10, P1.2, P1.6, P1.7, P2.1, P2.2, P2.3, P2.5.
## Iter G — modal contents (P1.6)
- nv-palette "New scene…" now opens a 5-field form (name, dipole
moment, heart→sensor distance, ferrous toggle, 60 Hz mains toggle).
On Apply: builds a real Scene JSON and pushes via client.loadScene().
- nv-palette "Export proof bundle…" now calls client.exportProofBundle()
and triggers a real blob download with a timestamp filename.
## Iter H — a11y pass (P2.1, P2.2, P2.3, P2.5)
- Skip-to-main-content link at top of nv-app (focus-visible only).
- <main id="main-content" role="main"> wraps the central area; tabindex="-1"
so the skip link can land focus there.
- nv-rail wraps its 5 view buttons in <nav role="navigation"
aria-label="Primary"> with aria-current="page" on the active button
and aria-label on every button. SVGs marked aria-hidden="true".
- nv-console body is now role="log" aria-live="polite"
aria-label="Console output".
- nv-modal auto-focuses first interactive element on open and traps
Tab cycling inside the dialog; nv-onboarding already had a dismiss
affordance covered.
## Iter I — drag persistence (P1.7) + density visual (P1.2)
- scenePositions signal in appStore + IndexedDB key 'scene-positions'.
- nv-scene restores drag positions at connect; persists on pointerup.
- Density visual (CSS body.density-{comfy,default,compact}) confirmed
active — was already wired but flagged as "doesn't change anything"
in P1.2; verified during this iter.
## P0.10 — REPL history persistence
- replHistory + pushReplHistory in appStore, persisted to IndexedDB
key 'repl-history'.
- nv-console arrow-up/down now read from the shared signal so command
history survives view switches and reloads.
Validated end-to-end with `npx agent-browser` on
https://ruvnet.github.io/RuView/nvsim/ — skip-link, main role, console
log role, nav role, aria-current="page", New Scene modal with 5 form
fields all confirmed live. Console errors: zero.
ADR-093 §2/§3/§4 updated to mark these items resolved.
Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
setClient, transport, theme, density, motionReduced,
|
||||
pushLog, expectedWitness, framesEmitted, fps, lastB, bMag,
|
||||
pushTrace, pushStripBar, lastFrame, sceneJson, witnessHex,
|
||||
replHistory, scenePositions, type SceneItemPos,
|
||||
} from './store/appStore';
|
||||
import { kvGet, kvSet } from './store/persistence';
|
||||
|
||||
@@ -37,6 +38,14 @@ function applyMotion(reduced: boolean): void {
|
||||
effect(() => { applyDensity(density.value); kvSet('density', density.value); });
|
||||
effect(() => { applyMotion(motionReduced.value); kvSet('motionReduced', motionReduced.value); });
|
||||
|
||||
// REPL history + scene drag positions persistence (P0.10, P1.7)
|
||||
const histSaved = await kvGet<string[]>('repl-history');
|
||||
if (histSaved && Array.isArray(histSaved)) replHistory.value = histSaved;
|
||||
effect(() => { void kvSet('repl-history', replHistory.value); });
|
||||
const positionsSaved = await kvGet<SceneItemPos[]>('scene-positions');
|
||||
if (positionsSaved && Array.isArray(positionsSaved)) scenePositions.value = positionsSaved;
|
||||
effect(() => { void kvSet('scene-positions', scenePositions.value); });
|
||||
|
||||
// Boot WASM client
|
||||
const client = new WasmClient();
|
||||
setClient(client);
|
||||
|
||||
Reference in New Issue
Block a user