feat(voyage): implement hidden-by-default sidebar-rail with ordered list + filter + jumplist count
Step 19 of v4.3 playground plan. Sidebar now default aria-hidden=true
(translateX collapses panel, leaves 40px FAB rail). FAB toggle has
data-action=toggle-sidebar for keyboard binding (] in Step 20).
New annotation-list section in sidebar panel:
- filter radiogroup: Alle (default), Åpne (unresolved), Resolved
- voyage-jumplist ordered list with numbered badges matching the
gutter-badge ordering (sorted by line ASC)
- aria-live jumplist count: "X av N" (filtered/total)
- click list-item -> setActiveAnchor + scrollIntoView + data-active
renderAnnotationList wires into mountRender so list refreshes on every
render. Filter state (voyageFilterState) persists across renders within
the session.
Trace: SC6, research/04 Dim 1 (hidden-by-default) + Insight 1 +
Recommendation sidebar/navigation.
This commit is contained in:
parent
84f41014f9
commit
6db7c72511
2 changed files with 201 additions and 9 deletions
|
|
@ -250,3 +250,32 @@ test('voyage-playground.html declares injectAnchorBadges JS function (v4.3 Step
|
|||
const text = readFileSync(HTML, 'utf-8');
|
||||
assert.match(text, /function\s+injectAnchorBadges\s*\(\s*\)/, 'injectAnchorBadges() function required');
|
||||
});
|
||||
|
||||
test('voyage-playground.html declares voyage-sidebar hidden-by-default (v4.3 Step 19)', () => {
|
||||
const text = readFileSync(HTML, 'utf-8');
|
||||
assert.match(text, /id="voyage-sidebar"[\s\S]{0,200}aria-hidden="true"/, 'voyage-sidebar must default aria-hidden="true"');
|
||||
});
|
||||
|
||||
test('voyage-playground.html declares data-action="toggle-sidebar" on FAB (v4.3 Step 19)', () => {
|
||||
const text = readFileSync(HTML, 'utf-8');
|
||||
assert.match(text, /data-action="toggle-sidebar"/, 'data-action="toggle-sidebar" required on FAB toggle button');
|
||||
});
|
||||
|
||||
test('voyage-playground.html declares voyage-jumplist + count "X av N" (v4.3 Step 19)', () => {
|
||||
const text = readFileSync(HTML, 'utf-8');
|
||||
assert.match(text, /id="voyage-jumplist"/, 'voyage-jumplist ordered list required');
|
||||
assert.match(text, /id="voyage-jumplist-count"/, 'voyage-jumplist-count container required');
|
||||
assert.match(text, /' av '/, '"X av N" jumplist count format string required in JS');
|
||||
});
|
||||
|
||||
test('voyage-playground.html declares filter-buttons Alle/Åpne/Resolved (v4.3 Step 19)', () => {
|
||||
const text = readFileSync(HTML, 'utf-8');
|
||||
assert.match(text, /data-filter="all"/, 'filter button data-filter="all" required');
|
||||
assert.match(text, /data-filter="open"/, 'filter button data-filter="open" required');
|
||||
assert.match(text, /data-filter="resolved"/, 'filter button data-filter="resolved" required');
|
||||
});
|
||||
|
||||
test('voyage-playground.html declares renderAnnotationList JS function (v4.3 Step 19)', () => {
|
||||
const text = readFileSync(HTML, 'utf-8');
|
||||
assert.match(text, /function\s+renderAnnotationList\s*\(\s*\)/, 'renderAnnotationList() function required');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue