feat(voyage): add playground sidebar with tabs + critique-card-list — v4.2 Step 10 [skip-docs]
Right-collapsible sidebar (320px) with 40px icon-rail when collapsed (per critical decision #4 + research-06): - 2-state FAB toggle (aria-expanded toggles aria-hidden on aside) - Visible draft-count badge on FAB (mitigates 'forgot to export' friction) - Two tabs: 'Denne planen (N drafts)' — pending annotations 'Alle revisjoner (M historiske)' — exported (Step 11 wires this) - role="tablist" + role="tab" + aria-selected + tabindex roving - ArrowLeft/ArrowRight keyboard nav between tabs - .findings list of .critique-card per annotation - Click on critique-card scrolls to anchor + .lint-annotation-glow 1s pulse animation - Sort-by-location (Hypothes.is pattern; line ASC) Card visual: intent-badge (color-coded fix=green/change=blue/question=yellow/block=red), ANN-NNNN ID, snippet preview, comment, exported-status. Layout: main shifts margin-right: 320px above 1024px viewport so the sidebar doesn't overlap the rendered artifact. saveModalAsAnnotation + mountRender hooks now refresh the sidebar so new drafts appear immediately and re-render preserves visibility. Test coverage: tests/playground/voyage-playground.test.mjs +2 cases — role="tablist", tabindex. Verify: node --test tests/playground/voyage-playground.test.mjs -> 18 pass / 0 fail. Full npm test: 592 pass / 0 fail / 2 skipped (Docker). Refs plan.md Step 10 + critical decision #4 + research-06.
This commit is contained in:
parent
a7a6a53686
commit
125bfb02b2
2 changed files with 412 additions and 0 deletions
|
|
@ -112,3 +112,15 @@ test('voyage-playground.html declares 300ms grace constant (Step 9 adder-popup g
|
|||
const text = readFileSync(HTML, 'utf-8');
|
||||
assert.match(text, /300\s*ms|GRACE_MS\s*=\s*300|ADDER_GRACE_MS/i, '300ms grace period for adder-popup must be present');
|
||||
});
|
||||
|
||||
// --- Step 10 — sidebar with tabs + critique-card-list ----------------
|
||||
|
||||
test('voyage-playground.html includes role="tablist" (Step 10 sidebar tabs A11Y)', () => {
|
||||
const text = readFileSync(HTML, 'utf-8');
|
||||
assert.match(text, /role="tablist"/, 'sidebar must declare role="tablist" for A11Y');
|
||||
});
|
||||
|
||||
test('voyage-playground.html declares tabindex (Step 10 focus management)', () => {
|
||||
const text = readFileSync(HTML, 'utf-8');
|
||||
assert.match(text, /tabindex/i, 'sidebar tabs must use tabindex for keyboard focus management');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue