detached f5cbe22

#31 fix(web): ARIA semantics for MR panels, dialogs, palette, forms and status regions

state
merged · 5d69f2b · squash
branch
fix/a11y → main
opened
bnema ·
updated
CommitSubjectAuthorDateSignatureStatus
f5cbe22test(app): update web goldens for the ARIA changesbriceGPG Verified
1f47bc8fix(web): keep MR panels open on refresh, expose one option per palette result, clear finder statusbriceGPG Verified
21b3830fix(web): improve ARIA semantics of MR panels, dialogs, palette, forms and status regionsbriceGPG Verified

Checks 4

55 files · +1051 -671
4/4
A internal/adapters/web/accessibility_test.go +53 -0
M internal/adapters/web/fragments.templ +1 -0
M internal/adapters/web/fragments_templ.go +2 -2
M internal/adapters/web/issues_form.templ +47 -9
M internal/adapters/web/issues_form_templ.go +161 -84
M internal/adapters/web/issues_form_test.go +2 -2
M internal/adapters/web/jstest/a11y.test.mjs +79 -1
M internal/adapters/web/jstest/finder.test.mjs +9 -8
M internal/adapters/web/jstest/mr.test.mjs +33 -1
M internal/adapters/web/mr.templ +9 -9
M internal/adapters/web/mr_templ.go +7 -7
M internal/adapters/web/mr_test.go +8 -7
M internal/adapters/web/overlays.templ +5 -5
M internal/adapters/web/overlays_templ.go +35 -12
M internal/adapters/web/shell.templ +4 -4
M internal/adapters/web/shell_templ.go +1 -1
M internal/adapters/web/static/css/20-shell.css +2 -1
M internal/adapters/web/static/css/60-mr.css +5 -8
M internal/adapters/web/static/css/85-mobile.css +1 -1
M internal/adapters/web/static/js/ermite.js +15 -0
M internal/adapters/web/static/js/files.js +4 -3
M internal/adapters/web/static/js/mr.js +3 -3
M internal/adapters/web/tree.templ +1 -1
M internal/adapters/web/tree_templ.go +1 -1
M internal/app/testdata/web/blob-binary.html +19 -17
M internal/app/testdata/web/blob-code.html +19 -17
@@ -211,18 +211,20 @@
211211 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
212212 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
213213 </footer>
214-<div class="hint" role="status" aria-live="polite">
215-<span class="hint-nav" :text="document.body.dataset.nav || ''">
214+<div class="hint">
215+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
216216 </span>
217+<span role="status" aria-live="polite">
217218 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
218219 </span>
219220 <span class="hint-flash" :text="document.body.dataset.flash || ''">
220221 </span>
222+</span>
221223 </div>
222224 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
223225 <div class="panel-head">
224226 <h2>Keyboard shortcuts</h2>
225-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
227+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
226228 <kbd>esc</kbd> close</button>
227229 </div>
228230 <div class="keys-pref">
@@ -356,7 +358,7 @@
356358 <div class="panel-head">
357359 <label for="refs-filter" class="sr">filter branches and tags</label>
358360 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
359-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
361+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
360362 <kbd>esc</kbd>
361363 </button>
362364 </div>
@@ -391,79 +393,79 @@
391393 <div class="panel-head">
392394 <label for="cmd-q" class="sr">go to</label>
393395 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
394-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
396+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
395397 <kbd>esc</kbd>
396398 </button>
397399 </div>
398400 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
399401 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
400-<a href="/" tabindex="-1">
402+<a role="presentation" data-href="/">
401403 <span class="lbl">home</span>
402404 <span class="k">go</span>
403405 </a>
404406 </li>
405407 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
406-<a href="/files" tabindex="-1">
408+<a role="presentation" data-href="/files">
407409 <span class="lbl">summary</span>
408410 <span class="k">section</span>
409411 </a>
410412 </li>
411413 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
412-<a href="/files/tree/main" tabindex="-1">
414+<a role="presentation" data-href="/files/tree/main">
413415 <span class="lbl">files</span>
414416 <span class="k">section</span>
415417 </a>
416418 </li>
417419 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
418-<a href="/files/commits/main" tabindex="-1">
420+<a role="presentation" data-href="/files/commits/main">
419421 <span class="lbl">commits</span>
420422 <span class="k">section</span>
421423 </a>
422424 </li>
423425 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
424-<a href="/files/refs" tabindex="-1">
426+<a role="presentation" data-href="/files/refs">
425427 <span class="lbl">branches &amp; tags</span>
426428 <span class="k">section</span>
427429 </a>
428430 </li>
429431 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
430-<a href="/files/merge-requests" tabindex="-1">
432+<a role="presentation" data-href="/files/merge-requests">
431433 <span class="lbl">merge requests</span>
432434 <span class="k">section</span>
433435 </a>
434436 </li>
435437 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
436-<a href="/files/releases" tabindex="-1">
438+<a role="presentation" data-href="/files/releases">
437439 <span class="lbl">releases</span>
438440 <span class="k">section</span>
439441 </a>
440442 </li>
441443 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
442-<a href="/files/actions" tabindex="-1">
444+<a role="presentation" data-href="/files/actions">
443445 <span class="lbl">actions</span>
444446 <span class="k">section</span>
445447 </a>
446448 </li>
447449 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
448-<a href="/files/tree/feature/x" tabindex="-1">
450+<a role="presentation" data-href="/files/tree/feature/x">
449451 <span class="lbl">feature/x</span>
450452 <span class="k">branch</span>
451453 </a>
452454 </li>
453455 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
454-<a href="/files/tree/main" tabindex="-1">
456+<a role="presentation" data-href="/files/tree/main">
455457 <span class="lbl">main</span>
456458 <span class="k">branch</span>
457459 </a>
458460 </li>
459461 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
460-<a href="/files/tree/v1.0" tabindex="-1">
462+<a role="presentation" data-href="/files/tree/v1.0">
461463 <span class="lbl">v1.0</span>
462464 <span class="k">tag</span>
463465 </a>
464466 </li>
465467 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
466-<a href="#" data-fire="keys" tabindex="-1">
468+<a role="presentation" data-fire="keys">
467469 <span class="lbl">turn single-key shortcuts off</span>
468470 <span class="k">action</span>
469471 </a>
@@ -211,18 +211,20 @@
211 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">211 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
212 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>212 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
213 </footer>213 </footer>
214-<div class="hint" role="status" aria-live="polite">214+<div class="hint">
215-<span class="hint-nav" :text="document.body.dataset.nav || ''">215+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
216 </span>216 </span>
217+<span role="status" aria-live="polite">
217 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">218 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
218 </span>219 </span>
219 <span class="hint-flash" :text="document.body.dataset.flash || ''">220 <span class="hint-flash" :text="document.body.dataset.flash || ''">
220 </span>221 </span>
222+</span>
221 </div>223 </div>
222 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">224 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
223 <div class="panel-head">225 <div class="panel-head">
224 <h2>Keyboard shortcuts</h2>226 <h2>Keyboard shortcuts</h2>
225-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">227+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
226 <kbd>esc</kbd> close</button>228 <kbd>esc</kbd> close</button>
227 </div>229 </div>
228 <div class="keys-pref">230 <div class="keys-pref">
@@ -356,7 +358,7 @@
356 <div class="panel-head">358 <div class="panel-head">
357 <label for="refs-filter" class="sr">filter branches and tags</label>359 <label for="refs-filter" class="sr">filter branches and tags</label>
358 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">360 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
359-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">361+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
360 <kbd>esc</kbd>362 <kbd>esc</kbd>
361 </button>363 </button>
362 </div>364 </div>
@@ -391,79 +393,79 @@
391 <div class="panel-head">393 <div class="panel-head">
392 <label for="cmd-q" class="sr">go to</label>394 <label for="cmd-q" class="sr">go to</label>
393 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">395 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
394-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">396+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
395 <kbd>esc</kbd>397 <kbd>esc</kbd>
396 </button>398 </button>
397 </div>399 </div>
398 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">400 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
399 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>401 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
400-<a href="/" tabindex="-1">402+<a role="presentation" data-href="/">
401 <span class="lbl">home</span>403 <span class="lbl">home</span>
402 <span class="k">go</span>404 <span class="k">go</span>
403 </a>405 </a>
404 </li>406 </li>
405 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">407 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
406-<a href="/files" tabindex="-1">408+<a role="presentation" data-href="/files">
407 <span class="lbl">summary</span>409 <span class="lbl">summary</span>
408 <span class="k">section</span>410 <span class="k">section</span>
409 </a>411 </a>
410 </li>412 </li>
411 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">413 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
412-<a href="/files/tree/main" tabindex="-1">414+<a role="presentation" data-href="/files/tree/main">
413 <span class="lbl">files</span>415 <span class="lbl">files</span>
414 <span class="k">section</span>416 <span class="k">section</span>
415 </a>417 </a>
416 </li>418 </li>
417 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">419 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
418-<a href="/files/commits/main" tabindex="-1">420+<a role="presentation" data-href="/files/commits/main">
419 <span class="lbl">commits</span>421 <span class="lbl">commits</span>
420 <span class="k">section</span>422 <span class="k">section</span>
421 </a>423 </a>
422 </li>424 </li>
423 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">425 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
424-<a href="/files/refs" tabindex="-1">426+<a role="presentation" data-href="/files/refs">
425 <span class="lbl">branches &amp; tags</span>427 <span class="lbl">branches &amp; tags</span>
426 <span class="k">section</span>428 <span class="k">section</span>
427 </a>429 </a>
428 </li>430 </li>
429 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">431 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
430-<a href="/files/merge-requests" tabindex="-1">432+<a role="presentation" data-href="/files/merge-requests">
431 <span class="lbl">merge requests</span>433 <span class="lbl">merge requests</span>
432 <span class="k">section</span>434 <span class="k">section</span>
433 </a>435 </a>
434 </li>436 </li>
435 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">437 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
436-<a href="/files/releases" tabindex="-1">438+<a role="presentation" data-href="/files/releases">
437 <span class="lbl">releases</span>439 <span class="lbl">releases</span>
438 <span class="k">section</span>440 <span class="k">section</span>
439 </a>441 </a>
440 </li>442 </li>
441 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">443 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
442-<a href="/files/actions" tabindex="-1">444+<a role="presentation" data-href="/files/actions">
443 <span class="lbl">actions</span>445 <span class="lbl">actions</span>
444 <span class="k">section</span>446 <span class="k">section</span>
445 </a>447 </a>
446 </li>448 </li>
447 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">449 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
448-<a href="/files/tree/feature/x" tabindex="-1">450+<a role="presentation" data-href="/files/tree/feature/x">
449 <span class="lbl">feature/x</span>451 <span class="lbl">feature/x</span>
450 <span class="k">branch</span>452 <span class="k">branch</span>
451 </a>453 </a>
452 </li>454 </li>
453 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">455 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
454-<a href="/files/tree/main" tabindex="-1">456+<a role="presentation" data-href="/files/tree/main">
455 <span class="lbl">main</span>457 <span class="lbl">main</span>
456 <span class="k">branch</span>458 <span class="k">branch</span>
457 </a>459 </a>
458 </li>460 </li>
459 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">461 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
460-<a href="/files/tree/v1.0" tabindex="-1">462+<a role="presentation" data-href="/files/tree/v1.0">
461 <span class="lbl">v1.0</span>463 <span class="lbl">v1.0</span>
462 <span class="k">tag</span>464 <span class="k">tag</span>
463 </a>465 </a>
464 </li>466 </li>
465 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">467 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
466-<a href="#" data-fire="keys" tabindex="-1">468+<a role="presentation" data-fire="keys">
467 <span class="lbl">turn single-key shortcuts off</span>469 <span class="lbl">turn single-key shortcuts off</span>
468 <span class="k">action</span>470 <span class="k">action</span>
469 </a>471 </a>
M internal/app/testdata/web/blob-empty.html +19 -17
@@ -141,18 +141,20 @@
141141 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
142142 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
143143 </footer>
144-<div class="hint" role="status" aria-live="polite">
145-<span class="hint-nav" :text="document.body.dataset.nav || ''">
144+<div class="hint">
145+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
146146 </span>
147+<span role="status" aria-live="polite">
147148 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
148149 </span>
149150 <span class="hint-flash" :text="document.body.dataset.flash || ''">
150151 </span>
152+</span>
151153 </div>
152154 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
153155 <div class="panel-head">
154156 <h2>Keyboard shortcuts</h2>
155-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
157+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
156158 <kbd>esc</kbd> close</button>
157159 </div>
158160 <div class="keys-pref">
@@ -286,7 +288,7 @@
286288 <div class="panel-head">
287289 <label for="refs-filter" class="sr">filter branches and tags</label>
288290 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
289-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
291+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
290292 <kbd>esc</kbd>
291293 </button>
292294 </div>
@@ -321,79 +323,79 @@
321323 <div class="panel-head">
322324 <label for="cmd-q" class="sr">go to</label>
323325 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
324-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
326+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
325327 <kbd>esc</kbd>
326328 </button>
327329 </div>
328330 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
329331 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
330-<a href="/" tabindex="-1">
332+<a role="presentation" data-href="/">
331333 <span class="lbl">home</span>
332334 <span class="k">go</span>
333335 </a>
334336 </li>
335337 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
336-<a href="/files" tabindex="-1">
338+<a role="presentation" data-href="/files">
337339 <span class="lbl">summary</span>
338340 <span class="k">section</span>
339341 </a>
340342 </li>
341343 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
342-<a href="/files/tree/main" tabindex="-1">
344+<a role="presentation" data-href="/files/tree/main">
343345 <span class="lbl">files</span>
344346 <span class="k">section</span>
345347 </a>
346348 </li>
347349 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
348-<a href="/files/commits/main" tabindex="-1">
350+<a role="presentation" data-href="/files/commits/main">
349351 <span class="lbl">commits</span>
350352 <span class="k">section</span>
351353 </a>
352354 </li>
353355 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
354-<a href="/files/refs" tabindex="-1">
356+<a role="presentation" data-href="/files/refs">
355357 <span class="lbl">branches &amp; tags</span>
356358 <span class="k">section</span>
357359 </a>
358360 </li>
359361 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
360-<a href="/files/merge-requests" tabindex="-1">
362+<a role="presentation" data-href="/files/merge-requests">
361363 <span class="lbl">merge requests</span>
362364 <span class="k">section</span>
363365 </a>
364366 </li>
365367 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
366-<a href="/files/releases" tabindex="-1">
368+<a role="presentation" data-href="/files/releases">
367369 <span class="lbl">releases</span>
368370 <span class="k">section</span>
369371 </a>
370372 </li>
371373 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
372-<a href="/files/actions" tabindex="-1">
374+<a role="presentation" data-href="/files/actions">
373375 <span class="lbl">actions</span>
374376 <span class="k">section</span>
375377 </a>
376378 </li>
377379 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
378-<a href="/files/tree/feature/x" tabindex="-1">
380+<a role="presentation" data-href="/files/tree/feature/x">
379381 <span class="lbl">feature/x</span>
380382 <span class="k">branch</span>
381383 </a>
382384 </li>
383385 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
384-<a href="/files/tree/main" tabindex="-1">
386+<a role="presentation" data-href="/files/tree/main">
385387 <span class="lbl">main</span>
386388 <span class="k">branch</span>
387389 </a>
388390 </li>
389391 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
390-<a href="/files/tree/v1.0" tabindex="-1">
392+<a role="presentation" data-href="/files/tree/v1.0">
391393 <span class="lbl">v1.0</span>
392394 <span class="k">tag</span>
393395 </a>
394396 </li>
395397 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
396-<a href="#" data-fire="keys" tabindex="-1">
398+<a role="presentation" data-fire="keys">
397399 <span class="lbl">turn single-key shortcuts off</span>
398400 <span class="k">action</span>
399401 </a>
@@ -141,18 +141,20 @@
141 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">141 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
142 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>142 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
143 </footer>143 </footer>
144-<div class="hint" role="status" aria-live="polite">144+<div class="hint">
145-<span class="hint-nav" :text="document.body.dataset.nav || ''">145+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
146 </span>146 </span>
147+<span role="status" aria-live="polite">
147 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">148 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
148 </span>149 </span>
149 <span class="hint-flash" :text="document.body.dataset.flash || ''">150 <span class="hint-flash" :text="document.body.dataset.flash || ''">
150 </span>151 </span>
152+</span>
151 </div>153 </div>
152 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">154 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
153 <div class="panel-head">155 <div class="panel-head">
154 <h2>Keyboard shortcuts</h2>156 <h2>Keyboard shortcuts</h2>
155-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">157+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
156 <kbd>esc</kbd> close</button>158 <kbd>esc</kbd> close</button>
157 </div>159 </div>
158 <div class="keys-pref">160 <div class="keys-pref">
@@ -286,7 +288,7 @@
286 <div class="panel-head">288 <div class="panel-head">
287 <label for="refs-filter" class="sr">filter branches and tags</label>289 <label for="refs-filter" class="sr">filter branches and tags</label>
288 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">290 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
289-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">291+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
290 <kbd>esc</kbd>292 <kbd>esc</kbd>
291 </button>293 </button>
292 </div>294 </div>
@@ -321,79 +323,79 @@
321 <div class="panel-head">323 <div class="panel-head">
322 <label for="cmd-q" class="sr">go to</label>324 <label for="cmd-q" class="sr">go to</label>
323 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">325 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
324-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">326+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
325 <kbd>esc</kbd>327 <kbd>esc</kbd>
326 </button>328 </button>
327 </div>329 </div>
328 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">330 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
329 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>331 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
330-<a href="/" tabindex="-1">332+<a role="presentation" data-href="/">
331 <span class="lbl">home</span>333 <span class="lbl">home</span>
332 <span class="k">go</span>334 <span class="k">go</span>
333 </a>335 </a>
334 </li>336 </li>
335 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">337 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
336-<a href="/files" tabindex="-1">338+<a role="presentation" data-href="/files">
337 <span class="lbl">summary</span>339 <span class="lbl">summary</span>
338 <span class="k">section</span>340 <span class="k">section</span>
339 </a>341 </a>
340 </li>342 </li>
341 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">343 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
342-<a href="/files/tree/main" tabindex="-1">344+<a role="presentation" data-href="/files/tree/main">
343 <span class="lbl">files</span>345 <span class="lbl">files</span>
344 <span class="k">section</span>346 <span class="k">section</span>
345 </a>347 </a>
346 </li>348 </li>
347 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">349 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
348-<a href="/files/commits/main" tabindex="-1">350+<a role="presentation" data-href="/files/commits/main">
349 <span class="lbl">commits</span>351 <span class="lbl">commits</span>
350 <span class="k">section</span>352 <span class="k">section</span>
351 </a>353 </a>
352 </li>354 </li>
353 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">355 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
354-<a href="/files/refs" tabindex="-1">356+<a role="presentation" data-href="/files/refs">
355 <span class="lbl">branches &amp; tags</span>357 <span class="lbl">branches &amp; tags</span>
356 <span class="k">section</span>358 <span class="k">section</span>
357 </a>359 </a>
358 </li>360 </li>
359 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">361 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
360-<a href="/files/merge-requests" tabindex="-1">362+<a role="presentation" data-href="/files/merge-requests">
361 <span class="lbl">merge requests</span>363 <span class="lbl">merge requests</span>
362 <span class="k">section</span>364 <span class="k">section</span>
363 </a>365 </a>
364 </li>366 </li>
365 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">367 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
366-<a href="/files/releases" tabindex="-1">368+<a role="presentation" data-href="/files/releases">
367 <span class="lbl">releases</span>369 <span class="lbl">releases</span>
368 <span class="k">section</span>370 <span class="k">section</span>
369 </a>371 </a>
370 </li>372 </li>
371 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">373 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
372-<a href="/files/actions" tabindex="-1">374+<a role="presentation" data-href="/files/actions">
373 <span class="lbl">actions</span>375 <span class="lbl">actions</span>
374 <span class="k">section</span>376 <span class="k">section</span>
375 </a>377 </a>
376 </li>378 </li>
377 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">379 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
378-<a href="/files/tree/feature/x" tabindex="-1">380+<a role="presentation" data-href="/files/tree/feature/x">
379 <span class="lbl">feature/x</span>381 <span class="lbl">feature/x</span>
380 <span class="k">branch</span>382 <span class="k">branch</span>
381 </a>383 </a>
382 </li>384 </li>
383 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">385 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
384-<a href="/files/tree/main" tabindex="-1">386+<a role="presentation" data-href="/files/tree/main">
385 <span class="lbl">main</span>387 <span class="lbl">main</span>
386 <span class="k">branch</span>388 <span class="k">branch</span>
387 </a>389 </a>
388 </li>390 </li>
389 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">391 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
390-<a href="/files/tree/v1.0" tabindex="-1">392+<a role="presentation" data-href="/files/tree/v1.0">
391 <span class="lbl">v1.0</span>393 <span class="lbl">v1.0</span>
392 <span class="k">tag</span>394 <span class="k">tag</span>
393 </a>395 </a>
394 </li>396 </li>
395 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">397 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
396-<a href="#" data-fire="keys" tabindex="-1">398+<a role="presentation" data-fire="keys">
397 <span class="lbl">turn single-key shortcuts off</span>399 <span class="lbl">turn single-key shortcuts off</span>
398 <span class="k">action</span>400 <span class="k">action</span>
399 </a>401 </a>
M internal/app/testdata/web/blob-image.html +19 -17
@@ -143,18 +143,20 @@
143143 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
144144 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
145145 </footer>
146-<div class="hint" role="status" aria-live="polite">
147-<span class="hint-nav" :text="document.body.dataset.nav || ''">
146+<div class="hint">
147+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
148148 </span>
149+<span role="status" aria-live="polite">
149150 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
150151 </span>
151152 <span class="hint-flash" :text="document.body.dataset.flash || ''">
152153 </span>
154+</span>
153155 </div>
154156 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
155157 <div class="panel-head">
156158 <h2>Keyboard shortcuts</h2>
157-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
159+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
158160 <kbd>esc</kbd> close</button>
159161 </div>
160162 <div class="keys-pref">
@@ -288,7 +290,7 @@
288290 <div class="panel-head">
289291 <label for="refs-filter" class="sr">filter branches and tags</label>
290292 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
291-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
293+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
292294 <kbd>esc</kbd>
293295 </button>
294296 </div>
@@ -323,79 +325,79 @@
323325 <div class="panel-head">
324326 <label for="cmd-q" class="sr">go to</label>
325327 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
326-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
328+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
327329 <kbd>esc</kbd>
328330 </button>
329331 </div>
330332 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
331333 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
332-<a href="/" tabindex="-1">
334+<a role="presentation" data-href="/">
333335 <span class="lbl">home</span>
334336 <span class="k">go</span>
335337 </a>
336338 </li>
337339 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
338-<a href="/files" tabindex="-1">
340+<a role="presentation" data-href="/files">
339341 <span class="lbl">summary</span>
340342 <span class="k">section</span>
341343 </a>
342344 </li>
343345 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
344-<a href="/files/tree/main" tabindex="-1">
346+<a role="presentation" data-href="/files/tree/main">
345347 <span class="lbl">files</span>
346348 <span class="k">section</span>
347349 </a>
348350 </li>
349351 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
350-<a href="/files/commits/main" tabindex="-1">
352+<a role="presentation" data-href="/files/commits/main">
351353 <span class="lbl">commits</span>
352354 <span class="k">section</span>
353355 </a>
354356 </li>
355357 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
356-<a href="/files/refs" tabindex="-1">
358+<a role="presentation" data-href="/files/refs">
357359 <span class="lbl">branches &amp; tags</span>
358360 <span class="k">section</span>
359361 </a>
360362 </li>
361363 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
362-<a href="/files/merge-requests" tabindex="-1">
364+<a role="presentation" data-href="/files/merge-requests">
363365 <span class="lbl">merge requests</span>
364366 <span class="k">section</span>
365367 </a>
366368 </li>
367369 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
368-<a href="/files/releases" tabindex="-1">
370+<a role="presentation" data-href="/files/releases">
369371 <span class="lbl">releases</span>
370372 <span class="k">section</span>
371373 </a>
372374 </li>
373375 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
374-<a href="/files/actions" tabindex="-1">
376+<a role="presentation" data-href="/files/actions">
375377 <span class="lbl">actions</span>
376378 <span class="k">section</span>
377379 </a>
378380 </li>
379381 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
380-<a href="/files/tree/feature/x" tabindex="-1">
382+<a role="presentation" data-href="/files/tree/feature/x">
381383 <span class="lbl">feature/x</span>
382384 <span class="k">branch</span>
383385 </a>
384386 </li>
385387 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
386-<a href="/files/tree/main" tabindex="-1">
388+<a role="presentation" data-href="/files/tree/main">
387389 <span class="lbl">main</span>
388390 <span class="k">branch</span>
389391 </a>
390392 </li>
391393 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
392-<a href="/files/tree/v1.0" tabindex="-1">
394+<a role="presentation" data-href="/files/tree/v1.0">
393395 <span class="lbl">v1.0</span>
394396 <span class="k">tag</span>
395397 </a>
396398 </li>
397399 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
398-<a href="#" data-fire="keys" tabindex="-1">
400+<a role="presentation" data-fire="keys">
399401 <span class="lbl">turn single-key shortcuts off</span>
400402 <span class="k">action</span>
401403 </a>
@@ -143,18 +143,20 @@
143 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">143 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
144 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>144 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
145 </footer>145 </footer>
146-<div class="hint" role="status" aria-live="polite">146+<div class="hint">
147-<span class="hint-nav" :text="document.body.dataset.nav || ''">147+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
148 </span>148 </span>
149+<span role="status" aria-live="polite">
149 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">150 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
150 </span>151 </span>
151 <span class="hint-flash" :text="document.body.dataset.flash || ''">152 <span class="hint-flash" :text="document.body.dataset.flash || ''">
152 </span>153 </span>
154+</span>
153 </div>155 </div>
154 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">156 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
155 <div class="panel-head">157 <div class="panel-head">
156 <h2>Keyboard shortcuts</h2>158 <h2>Keyboard shortcuts</h2>
157-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">159+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
158 <kbd>esc</kbd> close</button>160 <kbd>esc</kbd> close</button>
159 </div>161 </div>
160 <div class="keys-pref">162 <div class="keys-pref">
@@ -288,7 +290,7 @@
288 <div class="panel-head">290 <div class="panel-head">
289 <label for="refs-filter" class="sr">filter branches and tags</label>291 <label for="refs-filter" class="sr">filter branches and tags</label>
290 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">292 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
291-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">293+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
292 <kbd>esc</kbd>294 <kbd>esc</kbd>
293 </button>295 </button>
294 </div>296 </div>
@@ -323,79 +325,79 @@
323 <div class="panel-head">325 <div class="panel-head">
324 <label for="cmd-q" class="sr">go to</label>326 <label for="cmd-q" class="sr">go to</label>
325 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">327 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
326-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">328+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
327 <kbd>esc</kbd>329 <kbd>esc</kbd>
328 </button>330 </button>
329 </div>331 </div>
330 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">332 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
331 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>333 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
332-<a href="/" tabindex="-1">334+<a role="presentation" data-href="/">
333 <span class="lbl">home</span>335 <span class="lbl">home</span>
334 <span class="k">go</span>336 <span class="k">go</span>
335 </a>337 </a>
336 </li>338 </li>
337 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">339 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
338-<a href="/files" tabindex="-1">340+<a role="presentation" data-href="/files">
339 <span class="lbl">summary</span>341 <span class="lbl">summary</span>
340 <span class="k">section</span>342 <span class="k">section</span>
341 </a>343 </a>
342 </li>344 </li>
343 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">345 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
344-<a href="/files/tree/main" tabindex="-1">346+<a role="presentation" data-href="/files/tree/main">
345 <span class="lbl">files</span>347 <span class="lbl">files</span>
346 <span class="k">section</span>348 <span class="k">section</span>
347 </a>349 </a>
348 </li>350 </li>
349 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">351 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
350-<a href="/files/commits/main" tabindex="-1">352+<a role="presentation" data-href="/files/commits/main">
351 <span class="lbl">commits</span>353 <span class="lbl">commits</span>
352 <span class="k">section</span>354 <span class="k">section</span>
353 </a>355 </a>
354 </li>356 </li>
355 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">357 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
356-<a href="/files/refs" tabindex="-1">358+<a role="presentation" data-href="/files/refs">
357 <span class="lbl">branches &amp; tags</span>359 <span class="lbl">branches &amp; tags</span>
358 <span class="k">section</span>360 <span class="k">section</span>
359 </a>361 </a>
360 </li>362 </li>
361 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">363 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
362-<a href="/files/merge-requests" tabindex="-1">364+<a role="presentation" data-href="/files/merge-requests">
363 <span class="lbl">merge requests</span>365 <span class="lbl">merge requests</span>
364 <span class="k">section</span>366 <span class="k">section</span>
365 </a>367 </a>
366 </li>368 </li>
367 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">369 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
368-<a href="/files/releases" tabindex="-1">370+<a role="presentation" data-href="/files/releases">
369 <span class="lbl">releases</span>371 <span class="lbl">releases</span>
370 <span class="k">section</span>372 <span class="k">section</span>
371 </a>373 </a>
372 </li>374 </li>
373 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">375 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
374-<a href="/files/actions" tabindex="-1">376+<a role="presentation" data-href="/files/actions">
375 <span class="lbl">actions</span>377 <span class="lbl">actions</span>
376 <span class="k">section</span>378 <span class="k">section</span>
377 </a>379 </a>
378 </li>380 </li>
379 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">381 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
380-<a href="/files/tree/feature/x" tabindex="-1">382+<a role="presentation" data-href="/files/tree/feature/x">
381 <span class="lbl">feature/x</span>383 <span class="lbl">feature/x</span>
382 <span class="k">branch</span>384 <span class="k">branch</span>
383 </a>385 </a>
384 </li>386 </li>
385 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">387 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
386-<a href="/files/tree/main" tabindex="-1">388+<a role="presentation" data-href="/files/tree/main">
387 <span class="lbl">main</span>389 <span class="lbl">main</span>
388 <span class="k">branch</span>390 <span class="k">branch</span>
389 </a>391 </a>
390 </li>392 </li>
391 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">393 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
392-<a href="/files/tree/v1.0" tabindex="-1">394+<a role="presentation" data-href="/files/tree/v1.0">
393 <span class="lbl">v1.0</span>395 <span class="lbl">v1.0</span>
394 <span class="k">tag</span>396 <span class="k">tag</span>
395 </a>397 </a>
396 </li>398 </li>
397 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">399 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
398-<a href="#" data-fire="keys" tabindex="-1">400+<a role="presentation" data-fire="keys">
399 <span class="lbl">turn single-key shortcuts off</span>401 <span class="lbl">turn single-key shortcuts off</span>
400 <span class="k">action</span>402 <span class="k">action</span>
401 </a>403 </a>
M internal/app/testdata/web/blob-markdown.html +19 -17
@@ -208,18 +208,20 @@
208208 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
209209 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
210210 </footer>
211-<div class="hint" role="status" aria-live="polite">
212-<span class="hint-nav" :text="document.body.dataset.nav || ''">
211+<div class="hint">
212+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
213213 </span>
214+<span role="status" aria-live="polite">
214215 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
215216 </span>
216217 <span class="hint-flash" :text="document.body.dataset.flash || ''">
217218 </span>
219+</span>
218220 </div>
219221 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
220222 <div class="panel-head">
221223 <h2>Keyboard shortcuts</h2>
222-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
224+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
223225 <kbd>esc</kbd> close</button>
224226 </div>
225227 <div class="keys-pref">
@@ -353,7 +355,7 @@
353355 <div class="panel-head">
354356 <label for="refs-filter" class="sr">filter branches and tags</label>
355357 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
356-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
358+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
357359 <kbd>esc</kbd>
358360 </button>
359361 </div>
@@ -388,79 +390,79 @@
388390 <div class="panel-head">
389391 <label for="cmd-q" class="sr">go to</label>
390392 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
391-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
393+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
392394 <kbd>esc</kbd>
393395 </button>
394396 </div>
395397 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
396398 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
397-<a href="/" tabindex="-1">
399+<a role="presentation" data-href="/">
398400 <span class="lbl">home</span>
399401 <span class="k">go</span>
400402 </a>
401403 </li>
402404 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
403-<a href="/files" tabindex="-1">
405+<a role="presentation" data-href="/files">
404406 <span class="lbl">summary</span>
405407 <span class="k">section</span>
406408 </a>
407409 </li>
408410 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
409-<a href="/files/tree/main" tabindex="-1">
411+<a role="presentation" data-href="/files/tree/main">
410412 <span class="lbl">files</span>
411413 <span class="k">section</span>
412414 </a>
413415 </li>
414416 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
415-<a href="/files/commits/main" tabindex="-1">
417+<a role="presentation" data-href="/files/commits/main">
416418 <span class="lbl">commits</span>
417419 <span class="k">section</span>
418420 </a>
419421 </li>
420422 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
421-<a href="/files/refs" tabindex="-1">
423+<a role="presentation" data-href="/files/refs">
422424 <span class="lbl">branches &amp; tags</span>
423425 <span class="k">section</span>
424426 </a>
425427 </li>
426428 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
427-<a href="/files/merge-requests" tabindex="-1">
429+<a role="presentation" data-href="/files/merge-requests">
428430 <span class="lbl">merge requests</span>
429431 <span class="k">section</span>
430432 </a>
431433 </li>
432434 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
433-<a href="/files/releases" tabindex="-1">
435+<a role="presentation" data-href="/files/releases">
434436 <span class="lbl">releases</span>
435437 <span class="k">section</span>
436438 </a>
437439 </li>
438440 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
439-<a href="/files/actions" tabindex="-1">
441+<a role="presentation" data-href="/files/actions">
440442 <span class="lbl">actions</span>
441443 <span class="k">section</span>
442444 </a>
443445 </li>
444446 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
445-<a href="/files/tree/feature/x" tabindex="-1">
447+<a role="presentation" data-href="/files/tree/feature/x">
446448 <span class="lbl">feature/x</span>
447449 <span class="k">branch</span>
448450 </a>
449451 </li>
450452 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
451-<a href="/files/tree/main" tabindex="-1">
453+<a role="presentation" data-href="/files/tree/main">
452454 <span class="lbl">main</span>
453455 <span class="k">branch</span>
454456 </a>
455457 </li>
456458 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
457-<a href="/files/tree/v1.0" tabindex="-1">
459+<a role="presentation" data-href="/files/tree/v1.0">
458460 <span class="lbl">v1.0</span>
459461 <span class="k">tag</span>
460462 </a>
461463 </li>
462464 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
463-<a href="#" data-fire="keys" tabindex="-1">
465+<a role="presentation" data-fire="keys">
464466 <span class="lbl">turn single-key shortcuts off</span>
465467 <span class="k">action</span>
466468 </a>
@@ -208,18 +208,20 @@
208 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">208 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
209 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>209 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
210 </footer>210 </footer>
211-<div class="hint" role="status" aria-live="polite">211+<div class="hint">
212-<span class="hint-nav" :text="document.body.dataset.nav || ''">212+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
213 </span>213 </span>
214+<span role="status" aria-live="polite">
214 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">215 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
215 </span>216 </span>
216 <span class="hint-flash" :text="document.body.dataset.flash || ''">217 <span class="hint-flash" :text="document.body.dataset.flash || ''">
217 </span>218 </span>
219+</span>
218 </div>220 </div>
219 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">221 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
220 <div class="panel-head">222 <div class="panel-head">
221 <h2>Keyboard shortcuts</h2>223 <h2>Keyboard shortcuts</h2>
222-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">224+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
223 <kbd>esc</kbd> close</button>225 <kbd>esc</kbd> close</button>
224 </div>226 </div>
225 <div class="keys-pref">227 <div class="keys-pref">
@@ -353,7 +355,7 @@
353 <div class="panel-head">355 <div class="panel-head">
354 <label for="refs-filter" class="sr">filter branches and tags</label>356 <label for="refs-filter" class="sr">filter branches and tags</label>
355 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">357 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
356-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">358+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
357 <kbd>esc</kbd>359 <kbd>esc</kbd>
358 </button>360 </button>
359 </div>361 </div>
@@ -388,79 +390,79 @@
388 <div class="panel-head">390 <div class="panel-head">
389 <label for="cmd-q" class="sr">go to</label>391 <label for="cmd-q" class="sr">go to</label>
390 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">392 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
391-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">393+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
392 <kbd>esc</kbd>394 <kbd>esc</kbd>
393 </button>395 </button>
394 </div>396 </div>
395 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">397 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
396 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>398 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
397-<a href="/" tabindex="-1">399+<a role="presentation" data-href="/">
398 <span class="lbl">home</span>400 <span class="lbl">home</span>
399 <span class="k">go</span>401 <span class="k">go</span>
400 </a>402 </a>
401 </li>403 </li>
402 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">404 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
403-<a href="/files" tabindex="-1">405+<a role="presentation" data-href="/files">
404 <span class="lbl">summary</span>406 <span class="lbl">summary</span>
405 <span class="k">section</span>407 <span class="k">section</span>
406 </a>408 </a>
407 </li>409 </li>
408 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">410 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
409-<a href="/files/tree/main" tabindex="-1">411+<a role="presentation" data-href="/files/tree/main">
410 <span class="lbl">files</span>412 <span class="lbl">files</span>
411 <span class="k">section</span>413 <span class="k">section</span>
412 </a>414 </a>
413 </li>415 </li>
414 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">416 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
415-<a href="/files/commits/main" tabindex="-1">417+<a role="presentation" data-href="/files/commits/main">
416 <span class="lbl">commits</span>418 <span class="lbl">commits</span>
417 <span class="k">section</span>419 <span class="k">section</span>
418 </a>420 </a>
419 </li>421 </li>
420 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">422 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
421-<a href="/files/refs" tabindex="-1">423+<a role="presentation" data-href="/files/refs">
422 <span class="lbl">branches &amp; tags</span>424 <span class="lbl">branches &amp; tags</span>
423 <span class="k">section</span>425 <span class="k">section</span>
424 </a>426 </a>
425 </li>427 </li>
426 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">428 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
427-<a href="/files/merge-requests" tabindex="-1">429+<a role="presentation" data-href="/files/merge-requests">
428 <span class="lbl">merge requests</span>430 <span class="lbl">merge requests</span>
429 <span class="k">section</span>431 <span class="k">section</span>
430 </a>432 </a>
431 </li>433 </li>
432 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">434 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
433-<a href="/files/releases" tabindex="-1">435+<a role="presentation" data-href="/files/releases">
434 <span class="lbl">releases</span>436 <span class="lbl">releases</span>
435 <span class="k">section</span>437 <span class="k">section</span>
436 </a>438 </a>
437 </li>439 </li>
438 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">440 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
439-<a href="/files/actions" tabindex="-1">441+<a role="presentation" data-href="/files/actions">
440 <span class="lbl">actions</span>442 <span class="lbl">actions</span>
441 <span class="k">section</span>443 <span class="k">section</span>
442 </a>444 </a>
443 </li>445 </li>
444 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">446 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
445-<a href="/files/tree/feature/x" tabindex="-1">447+<a role="presentation" data-href="/files/tree/feature/x">
446 <span class="lbl">feature/x</span>448 <span class="lbl">feature/x</span>
447 <span class="k">branch</span>449 <span class="k">branch</span>
448 </a>450 </a>
449 </li>451 </li>
450 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">452 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
451-<a href="/files/tree/main" tabindex="-1">453+<a role="presentation" data-href="/files/tree/main">
452 <span class="lbl">main</span>454 <span class="lbl">main</span>
453 <span class="k">branch</span>455 <span class="k">branch</span>
454 </a>456 </a>
455 </li>457 </li>
456 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">458 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
457-<a href="/files/tree/v1.0" tabindex="-1">459+<a role="presentation" data-href="/files/tree/v1.0">
458 <span class="lbl">v1.0</span>460 <span class="lbl">v1.0</span>
459 <span class="k">tag</span>461 <span class="k">tag</span>
460 </a>462 </a>
461 </li>463 </li>
462 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">464 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
463-<a href="#" data-fire="keys" tabindex="-1">465+<a role="presentation" data-fire="keys">
464 <span class="lbl">turn single-key shortcuts off</span>466 <span class="lbl">turn single-key shortcuts off</span>
465 <span class="k">action</span>467 <span class="k">action</span>
466 </a>468 </a>
M internal/app/testdata/web/blob-svg.html +19 -17
@@ -166,18 +166,20 @@
166166 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
167167 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
168168 </footer>
169-<div class="hint" role="status" aria-live="polite">
170-<span class="hint-nav" :text="document.body.dataset.nav || ''">
169+<div class="hint">
170+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
171171 </span>
172+<span role="status" aria-live="polite">
172173 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
173174 </span>
174175 <span class="hint-flash" :text="document.body.dataset.flash || ''">
175176 </span>
177+</span>
176178 </div>
177179 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
178180 <div class="panel-head">
179181 <h2>Keyboard shortcuts</h2>
180-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
182+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
181183 <kbd>esc</kbd> close</button>
182184 </div>
183185 <div class="keys-pref">
@@ -311,7 +313,7 @@
311313 <div class="panel-head">
312314 <label for="refs-filter" class="sr">filter branches and tags</label>
313315 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
314-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
316+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
315317 <kbd>esc</kbd>
316318 </button>
317319 </div>
@@ -346,79 +348,79 @@
346348 <div class="panel-head">
347349 <label for="cmd-q" class="sr">go to</label>
348350 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
349-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
351+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
350352 <kbd>esc</kbd>
351353 </button>
352354 </div>
353355 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
354356 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
355-<a href="/" tabindex="-1">
357+<a role="presentation" data-href="/">
356358 <span class="lbl">home</span>
357359 <span class="k">go</span>
358360 </a>
359361 </li>
360362 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
361-<a href="/files" tabindex="-1">
363+<a role="presentation" data-href="/files">
362364 <span class="lbl">summary</span>
363365 <span class="k">section</span>
364366 </a>
365367 </li>
366368 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
367-<a href="/files/tree/main" tabindex="-1">
369+<a role="presentation" data-href="/files/tree/main">
368370 <span class="lbl">files</span>
369371 <span class="k">section</span>
370372 </a>
371373 </li>
372374 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
373-<a href="/files/commits/main" tabindex="-1">
375+<a role="presentation" data-href="/files/commits/main">
374376 <span class="lbl">commits</span>
375377 <span class="k">section</span>
376378 </a>
377379 </li>
378380 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
379-<a href="/files/refs" tabindex="-1">
381+<a role="presentation" data-href="/files/refs">
380382 <span class="lbl">branches &amp; tags</span>
381383 <span class="k">section</span>
382384 </a>
383385 </li>
384386 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
385-<a href="/files/merge-requests" tabindex="-1">
387+<a role="presentation" data-href="/files/merge-requests">
386388 <span class="lbl">merge requests</span>
387389 <span class="k">section</span>
388390 </a>
389391 </li>
390392 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
391-<a href="/files/releases" tabindex="-1">
393+<a role="presentation" data-href="/files/releases">
392394 <span class="lbl">releases</span>
393395 <span class="k">section</span>
394396 </a>
395397 </li>
396398 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
397-<a href="/files/actions" tabindex="-1">
399+<a role="presentation" data-href="/files/actions">
398400 <span class="lbl">actions</span>
399401 <span class="k">section</span>
400402 </a>
401403 </li>
402404 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
403-<a href="/files/tree/feature/x" tabindex="-1">
405+<a role="presentation" data-href="/files/tree/feature/x">
404406 <span class="lbl">feature/x</span>
405407 <span class="k">branch</span>
406408 </a>
407409 </li>
408410 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
409-<a href="/files/tree/main" tabindex="-1">
411+<a role="presentation" data-href="/files/tree/main">
410412 <span class="lbl">main</span>
411413 <span class="k">branch</span>
412414 </a>
413415 </li>
414416 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
415-<a href="/files/tree/v1.0" tabindex="-1">
417+<a role="presentation" data-href="/files/tree/v1.0">
416418 <span class="lbl">v1.0</span>
417419 <span class="k">tag</span>
418420 </a>
419421 </li>
420422 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
421-<a href="#" data-fire="keys" tabindex="-1">
423+<a role="presentation" data-fire="keys">
422424 <span class="lbl">turn single-key shortcuts off</span>
423425 <span class="k">action</span>
424426 </a>
@@ -166,18 +166,20 @@
166 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">166 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
167 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>167 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
168 </footer>168 </footer>
169-<div class="hint" role="status" aria-live="polite">169+<div class="hint">
170-<span class="hint-nav" :text="document.body.dataset.nav || ''">170+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
171 </span>171 </span>
172+<span role="status" aria-live="polite">
172 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">173 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
173 </span>174 </span>
174 <span class="hint-flash" :text="document.body.dataset.flash || ''">175 <span class="hint-flash" :text="document.body.dataset.flash || ''">
175 </span>176 </span>
177+</span>
176 </div>178 </div>
177 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">179 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
178 <div class="panel-head">180 <div class="panel-head">
179 <h2>Keyboard shortcuts</h2>181 <h2>Keyboard shortcuts</h2>
180-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">182+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
181 <kbd>esc</kbd> close</button>183 <kbd>esc</kbd> close</button>
182 </div>184 </div>
183 <div class="keys-pref">185 <div class="keys-pref">
@@ -311,7 +313,7 @@
311 <div class="panel-head">313 <div class="panel-head">
312 <label for="refs-filter" class="sr">filter branches and tags</label>314 <label for="refs-filter" class="sr">filter branches and tags</label>
313 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">315 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
314-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">316+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
315 <kbd>esc</kbd>317 <kbd>esc</kbd>
316 </button>318 </button>
317 </div>319 </div>
@@ -346,79 +348,79 @@
346 <div class="panel-head">348 <div class="panel-head">
347 <label for="cmd-q" class="sr">go to</label>349 <label for="cmd-q" class="sr">go to</label>
348 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">350 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
349-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">351+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
350 <kbd>esc</kbd>352 <kbd>esc</kbd>
351 </button>353 </button>
352 </div>354 </div>
353 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">355 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
354 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>356 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
355-<a href="/" tabindex="-1">357+<a role="presentation" data-href="/">
356 <span class="lbl">home</span>358 <span class="lbl">home</span>
357 <span class="k">go</span>359 <span class="k">go</span>
358 </a>360 </a>
359 </li>361 </li>
360 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">362 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
361-<a href="/files" tabindex="-1">363+<a role="presentation" data-href="/files">
362 <span class="lbl">summary</span>364 <span class="lbl">summary</span>
363 <span class="k">section</span>365 <span class="k">section</span>
364 </a>366 </a>
365 </li>367 </li>
366 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">368 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
367-<a href="/files/tree/main" tabindex="-1">369+<a role="presentation" data-href="/files/tree/main">
368 <span class="lbl">files</span>370 <span class="lbl">files</span>
369 <span class="k">section</span>371 <span class="k">section</span>
370 </a>372 </a>
371 </li>373 </li>
372 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">374 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
373-<a href="/files/commits/main" tabindex="-1">375+<a role="presentation" data-href="/files/commits/main">
374 <span class="lbl">commits</span>376 <span class="lbl">commits</span>
375 <span class="k">section</span>377 <span class="k">section</span>
376 </a>378 </a>
377 </li>379 </li>
378 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">380 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
379-<a href="/files/refs" tabindex="-1">381+<a role="presentation" data-href="/files/refs">
380 <span class="lbl">branches &amp; tags</span>382 <span class="lbl">branches &amp; tags</span>
381 <span class="k">section</span>383 <span class="k">section</span>
382 </a>384 </a>
383 </li>385 </li>
384 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">386 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
385-<a href="/files/merge-requests" tabindex="-1">387+<a role="presentation" data-href="/files/merge-requests">
386 <span class="lbl">merge requests</span>388 <span class="lbl">merge requests</span>
387 <span class="k">section</span>389 <span class="k">section</span>
388 </a>390 </a>
389 </li>391 </li>
390 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">392 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
391-<a href="/files/releases" tabindex="-1">393+<a role="presentation" data-href="/files/releases">
392 <span class="lbl">releases</span>394 <span class="lbl">releases</span>
393 <span class="k">section</span>395 <span class="k">section</span>
394 </a>396 </a>
395 </li>397 </li>
396 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">398 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
397-<a href="/files/actions" tabindex="-1">399+<a role="presentation" data-href="/files/actions">
398 <span class="lbl">actions</span>400 <span class="lbl">actions</span>
399 <span class="k">section</span>401 <span class="k">section</span>
400 </a>402 </a>
401 </li>403 </li>
402 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">404 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
403-<a href="/files/tree/feature/x" tabindex="-1">405+<a role="presentation" data-href="/files/tree/feature/x">
404 <span class="lbl">feature/x</span>406 <span class="lbl">feature/x</span>
405 <span class="k">branch</span>407 <span class="k">branch</span>
406 </a>408 </a>
407 </li>409 </li>
408 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">410 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
409-<a href="/files/tree/main" tabindex="-1">411+<a role="presentation" data-href="/files/tree/main">
410 <span class="lbl">main</span>412 <span class="lbl">main</span>
411 <span class="k">branch</span>413 <span class="k">branch</span>
412 </a>414 </a>
413 </li>415 </li>
414 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">416 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
415-<a href="/files/tree/v1.0" tabindex="-1">417+<a role="presentation" data-href="/files/tree/v1.0">
416 <span class="lbl">v1.0</span>418 <span class="lbl">v1.0</span>
417 <span class="k">tag</span>419 <span class="k">tag</span>
418 </a>420 </a>
419 </li>421 </li>
420 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">422 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
421-<a href="#" data-fire="keys" tabindex="-1">423+<a role="presentation" data-fire="keys">
422 <span class="lbl">turn single-key shortcuts off</span>424 <span class="lbl">turn single-key shortcuts off</span>
423 <span class="k">action</span>425 <span class="k">action</span>
424 </a>426 </a>
M internal/app/testdata/web/blob-text.html +19 -17
@@ -161,18 +161,20 @@
161161 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
162162 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
163163 </footer>
164-<div class="hint" role="status" aria-live="polite">
165-<span class="hint-nav" :text="document.body.dataset.nav || ''">
164+<div class="hint">
165+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
166166 </span>
167+<span role="status" aria-live="polite">
167168 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
168169 </span>
169170 <span class="hint-flash" :text="document.body.dataset.flash || ''">
170171 </span>
172+</span>
171173 </div>
172174 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
173175 <div class="panel-head">
174176 <h2>Keyboard shortcuts</h2>
175-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
177+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
176178 <kbd>esc</kbd> close</button>
177179 </div>
178180 <div class="keys-pref">
@@ -306,7 +308,7 @@
306308 <div class="panel-head">
307309 <label for="refs-filter" class="sr">filter branches and tags</label>
308310 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
309-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
311+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
310312 <kbd>esc</kbd>
311313 </button>
312314 </div>
@@ -341,79 +343,79 @@
341343 <div class="panel-head">
342344 <label for="cmd-q" class="sr">go to</label>
343345 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
344-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
346+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
345347 <kbd>esc</kbd>
346348 </button>
347349 </div>
348350 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
349351 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
350-<a href="/" tabindex="-1">
352+<a role="presentation" data-href="/">
351353 <span class="lbl">home</span>
352354 <span class="k">go</span>
353355 </a>
354356 </li>
355357 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
356-<a href="/files" tabindex="-1">
358+<a role="presentation" data-href="/files">
357359 <span class="lbl">summary</span>
358360 <span class="k">section</span>
359361 </a>
360362 </li>
361363 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
362-<a href="/files/tree/main" tabindex="-1">
364+<a role="presentation" data-href="/files/tree/main">
363365 <span class="lbl">files</span>
364366 <span class="k">section</span>
365367 </a>
366368 </li>
367369 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
368-<a href="/files/commits/main" tabindex="-1">
370+<a role="presentation" data-href="/files/commits/main">
369371 <span class="lbl">commits</span>
370372 <span class="k">section</span>
371373 </a>
372374 </li>
373375 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
374-<a href="/files/refs" tabindex="-1">
376+<a role="presentation" data-href="/files/refs">
375377 <span class="lbl">branches &amp; tags</span>
376378 <span class="k">section</span>
377379 </a>
378380 </li>
379381 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
380-<a href="/files/merge-requests" tabindex="-1">
382+<a role="presentation" data-href="/files/merge-requests">
381383 <span class="lbl">merge requests</span>
382384 <span class="k">section</span>
383385 </a>
384386 </li>
385387 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
386-<a href="/files/releases" tabindex="-1">
388+<a role="presentation" data-href="/files/releases">
387389 <span class="lbl">releases</span>
388390 <span class="k">section</span>
389391 </a>
390392 </li>
391393 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
392-<a href="/files/actions" tabindex="-1">
394+<a role="presentation" data-href="/files/actions">
393395 <span class="lbl">actions</span>
394396 <span class="k">section</span>
395397 </a>
396398 </li>
397399 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
398-<a href="/files/tree/feature/x" tabindex="-1">
400+<a role="presentation" data-href="/files/tree/feature/x">
399401 <span class="lbl">feature/x</span>
400402 <span class="k">branch</span>
401403 </a>
402404 </li>
403405 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
404-<a href="/files/tree/main" tabindex="-1">
406+<a role="presentation" data-href="/files/tree/main">
405407 <span class="lbl">main</span>
406408 <span class="k">branch</span>
407409 </a>
408410 </li>
409411 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
410-<a href="/files/tree/v1.0" tabindex="-1">
412+<a role="presentation" data-href="/files/tree/v1.0">
411413 <span class="lbl">v1.0</span>
412414 <span class="k">tag</span>
413415 </a>
414416 </li>
415417 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
416-<a href="#" data-fire="keys" tabindex="-1">
418+<a role="presentation" data-fire="keys">
417419 <span class="lbl">turn single-key shortcuts off</span>
418420 <span class="k">action</span>
419421 </a>
@@ -161,18 +161,20 @@
161 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">161 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
162 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>162 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
163 </footer>163 </footer>
164-<div class="hint" role="status" aria-live="polite">164+<div class="hint">
165-<span class="hint-nav" :text="document.body.dataset.nav || ''">165+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
166 </span>166 </span>
167+<span role="status" aria-live="polite">
167 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">168 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
168 </span>169 </span>
169 <span class="hint-flash" :text="document.body.dataset.flash || ''">170 <span class="hint-flash" :text="document.body.dataset.flash || ''">
170 </span>171 </span>
172+</span>
171 </div>173 </div>
172 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">174 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
173 <div class="panel-head">175 <div class="panel-head">
174 <h2>Keyboard shortcuts</h2>176 <h2>Keyboard shortcuts</h2>
175-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">177+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
176 <kbd>esc</kbd> close</button>178 <kbd>esc</kbd> close</button>
177 </div>179 </div>
178 <div class="keys-pref">180 <div class="keys-pref">
@@ -306,7 +308,7 @@
306 <div class="panel-head">308 <div class="panel-head">
307 <label for="refs-filter" class="sr">filter branches and tags</label>309 <label for="refs-filter" class="sr">filter branches and tags</label>
308 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">310 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
309-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">311+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
310 <kbd>esc</kbd>312 <kbd>esc</kbd>
311 </button>313 </button>
312 </div>314 </div>
@@ -341,79 +343,79 @@
341 <div class="panel-head">343 <div class="panel-head">
342 <label for="cmd-q" class="sr">go to</label>344 <label for="cmd-q" class="sr">go to</label>
343 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">345 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
344-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">346+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
345 <kbd>esc</kbd>347 <kbd>esc</kbd>
346 </button>348 </button>
347 </div>349 </div>
348 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">350 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
349 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>351 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
350-<a href="/" tabindex="-1">352+<a role="presentation" data-href="/">
351 <span class="lbl">home</span>353 <span class="lbl">home</span>
352 <span class="k">go</span>354 <span class="k">go</span>
353 </a>355 </a>
354 </li>356 </li>
355 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">357 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
356-<a href="/files" tabindex="-1">358+<a role="presentation" data-href="/files">
357 <span class="lbl">summary</span>359 <span class="lbl">summary</span>
358 <span class="k">section</span>360 <span class="k">section</span>
359 </a>361 </a>
360 </li>362 </li>
361 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">363 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
362-<a href="/files/tree/main" tabindex="-1">364+<a role="presentation" data-href="/files/tree/main">
363 <span class="lbl">files</span>365 <span class="lbl">files</span>
364 <span class="k">section</span>366 <span class="k">section</span>
365 </a>367 </a>
366 </li>368 </li>
367 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">369 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
368-<a href="/files/commits/main" tabindex="-1">370+<a role="presentation" data-href="/files/commits/main">
369 <span class="lbl">commits</span>371 <span class="lbl">commits</span>
370 <span class="k">section</span>372 <span class="k">section</span>
371 </a>373 </a>
372 </li>374 </li>
373 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">375 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
374-<a href="/files/refs" tabindex="-1">376+<a role="presentation" data-href="/files/refs">
375 <span class="lbl">branches &amp; tags</span>377 <span class="lbl">branches &amp; tags</span>
376 <span class="k">section</span>378 <span class="k">section</span>
377 </a>379 </a>
378 </li>380 </li>
379 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">381 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
380-<a href="/files/merge-requests" tabindex="-1">382+<a role="presentation" data-href="/files/merge-requests">
381 <span class="lbl">merge requests</span>383 <span class="lbl">merge requests</span>
382 <span class="k">section</span>384 <span class="k">section</span>
383 </a>385 </a>
384 </li>386 </li>
385 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">387 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
386-<a href="/files/releases" tabindex="-1">388+<a role="presentation" data-href="/files/releases">
387 <span class="lbl">releases</span>389 <span class="lbl">releases</span>
388 <span class="k">section</span>390 <span class="k">section</span>
389 </a>391 </a>
390 </li>392 </li>
391 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">393 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
392-<a href="/files/actions" tabindex="-1">394+<a role="presentation" data-href="/files/actions">
393 <span class="lbl">actions</span>395 <span class="lbl">actions</span>
394 <span class="k">section</span>396 <span class="k">section</span>
395 </a>397 </a>
396 </li>398 </li>
397 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">399 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
398-<a href="/files/tree/feature/x" tabindex="-1">400+<a role="presentation" data-href="/files/tree/feature/x">
399 <span class="lbl">feature/x</span>401 <span class="lbl">feature/x</span>
400 <span class="k">branch</span>402 <span class="k">branch</span>
401 </a>403 </a>
402 </li>404 </li>
403 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">405 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
404-<a href="/files/tree/main" tabindex="-1">406+<a role="presentation" data-href="/files/tree/main">
405 <span class="lbl">main</span>407 <span class="lbl">main</span>
406 <span class="k">branch</span>408 <span class="k">branch</span>
407 </a>409 </a>
408 </li>410 </li>
409 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">411 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
410-<a href="/files/tree/v1.0" tabindex="-1">412+<a role="presentation" data-href="/files/tree/v1.0">
411 <span class="lbl">v1.0</span>413 <span class="lbl">v1.0</span>
412 <span class="k">tag</span>414 <span class="k">tag</span>
413 </a>415 </a>
414 </li>416 </li>
415 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">417 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
416-<a href="#" data-fire="keys" tabindex="-1">418+<a role="presentation" data-fire="keys">
417 <span class="lbl">turn single-key shortcuts off</span>419 <span class="lbl">turn single-key shortcuts off</span>
418 <span class="k">action</span>420 <span class="k">action</span>
419 </a>421 </a>
M internal/app/testdata/web/blob-too-large.html +19 -17
@@ -141,18 +141,20 @@
141141 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
142142 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
143143 </footer>
144-<div class="hint" role="status" aria-live="polite">
145-<span class="hint-nav" :text="document.body.dataset.nav || ''">
144+<div class="hint">
145+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
146146 </span>
147+<span role="status" aria-live="polite">
147148 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
148149 </span>
149150 <span class="hint-flash" :text="document.body.dataset.flash || ''">
150151 </span>
152+</span>
151153 </div>
152154 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
153155 <div class="panel-head">
154156 <h2>Keyboard shortcuts</h2>
155-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
157+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
156158 <kbd>esc</kbd> close</button>
157159 </div>
158160 <div class="keys-pref">
@@ -286,7 +288,7 @@
286288 <div class="panel-head">
287289 <label for="refs-filter" class="sr">filter branches and tags</label>
288290 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
289-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
291+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
290292 <kbd>esc</kbd>
291293 </button>
292294 </div>
@@ -321,79 +323,79 @@
321323 <div class="panel-head">
322324 <label for="cmd-q" class="sr">go to</label>
323325 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
324-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
326+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
325327 <kbd>esc</kbd>
326328 </button>
327329 </div>
328330 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
329331 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
330-<a href="/" tabindex="-1">
332+<a role="presentation" data-href="/">
331333 <span class="lbl">home</span>
332334 <span class="k">go</span>
333335 </a>
334336 </li>
335337 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
336-<a href="/files" tabindex="-1">
338+<a role="presentation" data-href="/files">
337339 <span class="lbl">summary</span>
338340 <span class="k">section</span>
339341 </a>
340342 </li>
341343 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
342-<a href="/files/tree/main" tabindex="-1">
344+<a role="presentation" data-href="/files/tree/main">
343345 <span class="lbl">files</span>
344346 <span class="k">section</span>
345347 </a>
346348 </li>
347349 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
348-<a href="/files/commits/main" tabindex="-1">
350+<a role="presentation" data-href="/files/commits/main">
349351 <span class="lbl">commits</span>
350352 <span class="k">section</span>
351353 </a>
352354 </li>
353355 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
354-<a href="/files/refs" tabindex="-1">
356+<a role="presentation" data-href="/files/refs">
355357 <span class="lbl">branches &amp; tags</span>
356358 <span class="k">section</span>
357359 </a>
358360 </li>
359361 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
360-<a href="/files/merge-requests" tabindex="-1">
362+<a role="presentation" data-href="/files/merge-requests">
361363 <span class="lbl">merge requests</span>
362364 <span class="k">section</span>
363365 </a>
364366 </li>
365367 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
366-<a href="/files/releases" tabindex="-1">
368+<a role="presentation" data-href="/files/releases">
367369 <span class="lbl">releases</span>
368370 <span class="k">section</span>
369371 </a>
370372 </li>
371373 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
372-<a href="/files/actions" tabindex="-1">
374+<a role="presentation" data-href="/files/actions">
373375 <span class="lbl">actions</span>
374376 <span class="k">section</span>
375377 </a>
376378 </li>
377379 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
378-<a href="/files/tree/feature/x" tabindex="-1">
380+<a role="presentation" data-href="/files/tree/feature/x">
379381 <span class="lbl">feature/x</span>
380382 <span class="k">branch</span>
381383 </a>
382384 </li>
383385 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
384-<a href="/files/tree/main" tabindex="-1">
386+<a role="presentation" data-href="/files/tree/main">
385387 <span class="lbl">main</span>
386388 <span class="k">branch</span>
387389 </a>
388390 </li>
389391 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
390-<a href="/files/tree/v1.0" tabindex="-1">
392+<a role="presentation" data-href="/files/tree/v1.0">
391393 <span class="lbl">v1.0</span>
392394 <span class="k">tag</span>
393395 </a>
394396 </li>
395397 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
396-<a href="#" data-fire="keys" tabindex="-1">
398+<a role="presentation" data-fire="keys">
397399 <span class="lbl">turn single-key shortcuts off</span>
398400 <span class="k">action</span>
399401 </a>
@@ -141,18 +141,20 @@
141 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">141 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
142 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>142 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
143 </footer>143 </footer>
144-<div class="hint" role="status" aria-live="polite">144+<div class="hint">
145-<span class="hint-nav" :text="document.body.dataset.nav || ''">145+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
146 </span>146 </span>
147+<span role="status" aria-live="polite">
147 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">148 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
148 </span>149 </span>
149 <span class="hint-flash" :text="document.body.dataset.flash || ''">150 <span class="hint-flash" :text="document.body.dataset.flash || ''">
150 </span>151 </span>
152+</span>
151 </div>153 </div>
152 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">154 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
153 <div class="panel-head">155 <div class="panel-head">
154 <h2>Keyboard shortcuts</h2>156 <h2>Keyboard shortcuts</h2>
155-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">157+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
156 <kbd>esc</kbd> close</button>158 <kbd>esc</kbd> close</button>
157 </div>159 </div>
158 <div class="keys-pref">160 <div class="keys-pref">
@@ -286,7 +288,7 @@
286 <div class="panel-head">288 <div class="panel-head">
287 <label for="refs-filter" class="sr">filter branches and tags</label>289 <label for="refs-filter" class="sr">filter branches and tags</label>
288 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">290 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
289-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">291+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
290 <kbd>esc</kbd>292 <kbd>esc</kbd>
291 </button>293 </button>
292 </div>294 </div>
@@ -321,79 +323,79 @@
321 <div class="panel-head">323 <div class="panel-head">
322 <label for="cmd-q" class="sr">go to</label>324 <label for="cmd-q" class="sr">go to</label>
323 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">325 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
324-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">326+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
325 <kbd>esc</kbd>327 <kbd>esc</kbd>
326 </button>328 </button>
327 </div>329 </div>
328 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">330 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
329 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>331 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
330-<a href="/" tabindex="-1">332+<a role="presentation" data-href="/">
331 <span class="lbl">home</span>333 <span class="lbl">home</span>
332 <span class="k">go</span>334 <span class="k">go</span>
333 </a>335 </a>
334 </li>336 </li>
335 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">337 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
336-<a href="/files" tabindex="-1">338+<a role="presentation" data-href="/files">
337 <span class="lbl">summary</span>339 <span class="lbl">summary</span>
338 <span class="k">section</span>340 <span class="k">section</span>
339 </a>341 </a>
340 </li>342 </li>
341 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">343 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
342-<a href="/files/tree/main" tabindex="-1">344+<a role="presentation" data-href="/files/tree/main">
343 <span class="lbl">files</span>345 <span class="lbl">files</span>
344 <span class="k">section</span>346 <span class="k">section</span>
345 </a>347 </a>
346 </li>348 </li>
347 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">349 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
348-<a href="/files/commits/main" tabindex="-1">350+<a role="presentation" data-href="/files/commits/main">
349 <span class="lbl">commits</span>351 <span class="lbl">commits</span>
350 <span class="k">section</span>352 <span class="k">section</span>
351 </a>353 </a>
352 </li>354 </li>
353 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">355 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
354-<a href="/files/refs" tabindex="-1">356+<a role="presentation" data-href="/files/refs">
355 <span class="lbl">branches &amp; tags</span>357 <span class="lbl">branches &amp; tags</span>
356 <span class="k">section</span>358 <span class="k">section</span>
357 </a>359 </a>
358 </li>360 </li>
359 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">361 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
360-<a href="/files/merge-requests" tabindex="-1">362+<a role="presentation" data-href="/files/merge-requests">
361 <span class="lbl">merge requests</span>363 <span class="lbl">merge requests</span>
362 <span class="k">section</span>364 <span class="k">section</span>
363 </a>365 </a>
364 </li>366 </li>
365 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">367 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
366-<a href="/files/releases" tabindex="-1">368+<a role="presentation" data-href="/files/releases">
367 <span class="lbl">releases</span>369 <span class="lbl">releases</span>
368 <span class="k">section</span>370 <span class="k">section</span>
369 </a>371 </a>
370 </li>372 </li>
371 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">373 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
372-<a href="/files/actions" tabindex="-1">374+<a role="presentation" data-href="/files/actions">
373 <span class="lbl">actions</span>375 <span class="lbl">actions</span>
374 <span class="k">section</span>376 <span class="k">section</span>
375 </a>377 </a>
376 </li>378 </li>
377 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">379 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
378-<a href="/files/tree/feature/x" tabindex="-1">380+<a role="presentation" data-href="/files/tree/feature/x">
379 <span class="lbl">feature/x</span>381 <span class="lbl">feature/x</span>
380 <span class="k">branch</span>382 <span class="k">branch</span>
381 </a>383 </a>
382 </li>384 </li>
383 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">385 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
384-<a href="/files/tree/main" tabindex="-1">386+<a role="presentation" data-href="/files/tree/main">
385 <span class="lbl">main</span>387 <span class="lbl">main</span>
386 <span class="k">branch</span>388 <span class="k">branch</span>
387 </a>389 </a>
388 </li>390 </li>
389 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">391 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
390-<a href="/files/tree/v1.0" tabindex="-1">392+<a role="presentation" data-href="/files/tree/v1.0">
391 <span class="lbl">v1.0</span>393 <span class="lbl">v1.0</span>
392 <span class="k">tag</span>394 <span class="k">tag</span>
393 </a>395 </a>
394 </li>396 </li>
395 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">397 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
396-<a href="#" data-fire="keys" tabindex="-1">398+<a role="presentation" data-fire="keys">
397 <span class="lbl">turn single-key shortcuts off</span>399 <span class="lbl">turn single-key shortcuts off</span>
398 <span class="k">action</span>400 <span class="k">action</span>
399 </a>401 </a>
M internal/app/testdata/web/blob-trojan.html +19 -17
@@ -208,18 +208,20 @@
208208 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
209209 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
210210 </footer>
211-<div class="hint" role="status" aria-live="polite">
212-<span class="hint-nav" :text="document.body.dataset.nav || ''">
211+<div class="hint">
212+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
213213 </span>
214+<span role="status" aria-live="polite">
214215 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
215216 </span>
216217 <span class="hint-flash" :text="document.body.dataset.flash || ''">
217218 </span>
219+</span>
218220 </div>
219221 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
220222 <div class="panel-head">
221223 <h2>Keyboard shortcuts</h2>
222-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
224+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
223225 <kbd>esc</kbd> close</button>
224226 </div>
225227 <div class="keys-pref">
@@ -353,7 +355,7 @@
353355 <div class="panel-head">
354356 <label for="refs-filter" class="sr">filter branches and tags</label>
355357 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
356-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
358+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
357359 <kbd>esc</kbd>
358360 </button>
359361 </div>
@@ -388,79 +390,79 @@
388390 <div class="panel-head">
389391 <label for="cmd-q" class="sr">go to</label>
390392 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
391-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
393+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
392394 <kbd>esc</kbd>
393395 </button>
394396 </div>
395397 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
396398 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
397-<a href="/" tabindex="-1">
399+<a role="presentation" data-href="/">
398400 <span class="lbl">home</span>
399401 <span class="k">go</span>
400402 </a>
401403 </li>
402404 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
403-<a href="/files" tabindex="-1">
405+<a role="presentation" data-href="/files">
404406 <span class="lbl">summary</span>
405407 <span class="k">section</span>
406408 </a>
407409 </li>
408410 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
409-<a href="/files/tree/main" tabindex="-1">
411+<a role="presentation" data-href="/files/tree/main">
410412 <span class="lbl">files</span>
411413 <span class="k">section</span>
412414 </a>
413415 </li>
414416 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
415-<a href="/files/commits/main" tabindex="-1">
417+<a role="presentation" data-href="/files/commits/main">
416418 <span class="lbl">commits</span>
417419 <span class="k">section</span>
418420 </a>
419421 </li>
420422 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
421-<a href="/files/refs" tabindex="-1">
423+<a role="presentation" data-href="/files/refs">
422424 <span class="lbl">branches &amp; tags</span>
423425 <span class="k">section</span>
424426 </a>
425427 </li>
426428 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
427-<a href="/files/merge-requests" tabindex="-1">
429+<a role="presentation" data-href="/files/merge-requests">
428430 <span class="lbl">merge requests</span>
429431 <span class="k">section</span>
430432 </a>
431433 </li>
432434 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
433-<a href="/files/releases" tabindex="-1">
435+<a role="presentation" data-href="/files/releases">
434436 <span class="lbl">releases</span>
435437 <span class="k">section</span>
436438 </a>
437439 </li>
438440 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
439-<a href="/files/actions" tabindex="-1">
441+<a role="presentation" data-href="/files/actions">
440442 <span class="lbl">actions</span>
441443 <span class="k">section</span>
442444 </a>
443445 </li>
444446 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
445-<a href="/files/tree/feature/x" tabindex="-1">
447+<a role="presentation" data-href="/files/tree/feature/x">
446448 <span class="lbl">feature/x</span>
447449 <span class="k">branch</span>
448450 </a>
449451 </li>
450452 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
451-<a href="/files/tree/main" tabindex="-1">
453+<a role="presentation" data-href="/files/tree/main">
452454 <span class="lbl">main</span>
453455 <span class="k">branch</span>
454456 </a>
455457 </li>
456458 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
457-<a href="/files/tree/v1.0" tabindex="-1">
459+<a role="presentation" data-href="/files/tree/v1.0">
458460 <span class="lbl">v1.0</span>
459461 <span class="k">tag</span>
460462 </a>
461463 </li>
462464 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
463-<a href="#" data-fire="keys" tabindex="-1">
465+<a role="presentation" data-fire="keys">
464466 <span class="lbl">turn single-key shortcuts off</span>
465467 <span class="k">action</span>
466468 </a>
@@ -208,18 +208,20 @@
208 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">208 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
209 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>209 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
210 </footer>210 </footer>
211-<div class="hint" role="status" aria-live="polite">211+<div class="hint">
212-<span class="hint-nav" :text="document.body.dataset.nav || ''">212+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
213 </span>213 </span>
214+<span role="status" aria-live="polite">
214 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">215 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
215 </span>216 </span>
216 <span class="hint-flash" :text="document.body.dataset.flash || ''">217 <span class="hint-flash" :text="document.body.dataset.flash || ''">
217 </span>218 </span>
219+</span>
218 </div>220 </div>
219 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">221 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
220 <div class="panel-head">222 <div class="panel-head">
221 <h2>Keyboard shortcuts</h2>223 <h2>Keyboard shortcuts</h2>
222-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">224+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
223 <kbd>esc</kbd> close</button>225 <kbd>esc</kbd> close</button>
224 </div>226 </div>
225 <div class="keys-pref">227 <div class="keys-pref">
@@ -353,7 +355,7 @@
353 <div class="panel-head">355 <div class="panel-head">
354 <label for="refs-filter" class="sr">filter branches and tags</label>356 <label for="refs-filter" class="sr">filter branches and tags</label>
355 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">357 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
356-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">358+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
357 <kbd>esc</kbd>359 <kbd>esc</kbd>
358 </button>360 </button>
359 </div>361 </div>
@@ -388,79 +390,79 @@
388 <div class="panel-head">390 <div class="panel-head">
389 <label for="cmd-q" class="sr">go to</label>391 <label for="cmd-q" class="sr">go to</label>
390 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">392 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
391-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">393+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
392 <kbd>esc</kbd>394 <kbd>esc</kbd>
393 </button>395 </button>
394 </div>396 </div>
395 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">397 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
396 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>398 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
397-<a href="/" tabindex="-1">399+<a role="presentation" data-href="/">
398 <span class="lbl">home</span>400 <span class="lbl">home</span>
399 <span class="k">go</span>401 <span class="k">go</span>
400 </a>402 </a>
401 </li>403 </li>
402 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">404 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
403-<a href="/files" tabindex="-1">405+<a role="presentation" data-href="/files">
404 <span class="lbl">summary</span>406 <span class="lbl">summary</span>
405 <span class="k">section</span>407 <span class="k">section</span>
406 </a>408 </a>
407 </li>409 </li>
408 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">410 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
409-<a href="/files/tree/main" tabindex="-1">411+<a role="presentation" data-href="/files/tree/main">
410 <span class="lbl">files</span>412 <span class="lbl">files</span>
411 <span class="k">section</span>413 <span class="k">section</span>
412 </a>414 </a>
413 </li>415 </li>
414 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">416 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
415-<a href="/files/commits/main" tabindex="-1">417+<a role="presentation" data-href="/files/commits/main">
416 <span class="lbl">commits</span>418 <span class="lbl">commits</span>
417 <span class="k">section</span>419 <span class="k">section</span>
418 </a>420 </a>
419 </li>421 </li>
420 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">422 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
421-<a href="/files/refs" tabindex="-1">423+<a role="presentation" data-href="/files/refs">
422 <span class="lbl">branches &amp; tags</span>424 <span class="lbl">branches &amp; tags</span>
423 <span class="k">section</span>425 <span class="k">section</span>
424 </a>426 </a>
425 </li>427 </li>
426 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">428 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
427-<a href="/files/merge-requests" tabindex="-1">429+<a role="presentation" data-href="/files/merge-requests">
428 <span class="lbl">merge requests</span>430 <span class="lbl">merge requests</span>
429 <span class="k">section</span>431 <span class="k">section</span>
430 </a>432 </a>
431 </li>433 </li>
432 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">434 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
433-<a href="/files/releases" tabindex="-1">435+<a role="presentation" data-href="/files/releases">
434 <span class="lbl">releases</span>436 <span class="lbl">releases</span>
435 <span class="k">section</span>437 <span class="k">section</span>
436 </a>438 </a>
437 </li>439 </li>
438 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">440 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
439-<a href="/files/actions" tabindex="-1">441+<a role="presentation" data-href="/files/actions">
440 <span class="lbl">actions</span>442 <span class="lbl">actions</span>
441 <span class="k">section</span>443 <span class="k">section</span>
442 </a>444 </a>
443 </li>445 </li>
444 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">446 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
445-<a href="/files/tree/feature/x" tabindex="-1">447+<a role="presentation" data-href="/files/tree/feature/x">
446 <span class="lbl">feature/x</span>448 <span class="lbl">feature/x</span>
447 <span class="k">branch</span>449 <span class="k">branch</span>
448 </a>450 </a>
449 </li>451 </li>
450 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">452 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
451-<a href="/files/tree/main" tabindex="-1">453+<a role="presentation" data-href="/files/tree/main">
452 <span class="lbl">main</span>454 <span class="lbl">main</span>
453 <span class="k">branch</span>455 <span class="k">branch</span>
454 </a>456 </a>
455 </li>457 </li>
456 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">458 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0">
457-<a href="/files/tree/v1.0" tabindex="-1">459+<a role="presentation" data-href="/files/tree/v1.0">
458 <span class="lbl">v1.0</span>460 <span class="lbl">v1.0</span>
459 <span class="k">tag</span>461 <span class="k">tag</span>
460 </a>462 </a>
461 </li>463 </li>
462 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">464 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
463-<a href="#" data-fire="keys" tabindex="-1">465+<a role="presentation" data-fire="keys">
464 <span class="lbl">turn single-key shortcuts off</span>466 <span class="lbl">turn single-key shortcuts off</span>
465 <span class="k">action</span>467 <span class="k">action</span>
466 </a>468 </a>
M internal/app/testdata/web/commit-big.html +19 -17
@@ -193,18 +193,20 @@
193193 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
194194 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
195195 </footer>
196-<div class="hint" role="status" aria-live="polite">
197-<span class="hint-nav" :text="document.body.dataset.nav || ''">
196+<div class="hint">
197+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
198198 </span>
199+<span role="status" aria-live="polite">
199200 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
200201 </span>
201202 <span class="hint-flash" :text="document.body.dataset.flash || ''">
202203 </span>
204+</span>
203205 </div>
204206 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
205207 <div class="panel-head">
206208 <h2>Keyboard shortcuts</h2>
207-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
209+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
208210 <kbd>esc</kbd> close</button>
209211 </div>
210212 <div class="keys-pref">
@@ -338,7 +340,7 @@
338340 <div class="panel-head">
339341 <label for="refs-filter" class="sr">filter branches and tags</label>
340342 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
341-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
343+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
342344 <kbd>esc</kbd>
343345 </button>
344346 </div>
@@ -373,79 +375,79 @@
373375 <div class="panel-head">
374376 <label for="cmd-q" class="sr">go to</label>
375377 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
376-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
378+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
377379 <kbd>esc</kbd>
378380 </button>
379381 </div>
380382 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
381383 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
382-<a href="/" tabindex="-1">
384+<a role="presentation" data-href="/">
383385 <span class="lbl">home</span>
384386 <span class="k">go</span>
385387 </a>
386388 </li>
387389 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
388-<a href="/diffs" tabindex="-1">
390+<a role="presentation" data-href="/diffs">
389391 <span class="lbl">summary</span>
390392 <span class="k">section</span>
391393 </a>
392394 </li>
393395 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
394-<a href="/diffs/tree/main" tabindex="-1">
396+<a role="presentation" data-href="/diffs/tree/main">
395397 <span class="lbl">files</span>
396398 <span class="k">section</span>
397399 </a>
398400 </li>
399401 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
400-<a href="/diffs/commits/main" tabindex="-1">
402+<a role="presentation" data-href="/diffs/commits/main">
401403 <span class="lbl">commits</span>
402404 <span class="k">section</span>
403405 </a>
404406 </li>
405407 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
406-<a href="/diffs/refs" tabindex="-1">
408+<a role="presentation" data-href="/diffs/refs">
407409 <span class="lbl">branches &amp; tags</span>
408410 <span class="k">section</span>
409411 </a>
410412 </li>
411413 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
412-<a href="/diffs/merge-requests" tabindex="-1">
414+<a role="presentation" data-href="/diffs/merge-requests">
413415 <span class="lbl">merge requests</span>
414416 <span class="k">section</span>
415417 </a>
416418 </li>
417419 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
418-<a href="/diffs/releases" tabindex="-1">
420+<a role="presentation" data-href="/diffs/releases">
419421 <span class="lbl">releases</span>
420422 <span class="k">section</span>
421423 </a>
422424 </li>
423425 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
424-<a href="/diffs/actions" tabindex="-1">
426+<a role="presentation" data-href="/diffs/actions">
425427 <span class="lbl">actions</span>
426428 <span class="k">section</span>
427429 </a>
428430 </li>
429431 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
430-<a href="/diffs/tree/main" tabindex="-1">
432+<a role="presentation" data-href="/diffs/tree/main">
431433 <span class="lbl">main</span>
432434 <span class="k">branch</span>
433435 </a>
434436 </li>
435437 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
436-<a href="/diffs/tree/side" tabindex="-1">
438+<a role="presentation" data-href="/diffs/tree/side">
437439 <span class="lbl">side</span>
438440 <span class="k">branch</span>
439441 </a>
440442 </li>
441443 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
442-<a href="/diffs/tree/v1.0.0" tabindex="-1">
444+<a role="presentation" data-href="/diffs/tree/v1.0.0">
443445 <span class="lbl">v1.0.0</span>
444446 <span class="k">tag</span>
445447 </a>
446448 </li>
447449 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
448-<a href="#" data-fire="keys" tabindex="-1">
450+<a role="presentation" data-fire="keys">
449451 <span class="lbl">turn single-key shortcuts off</span>
450452 <span class="k">action</span>
451453 </a>
@@ -193,18 +193,20 @@
193 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">193 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
194 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>194 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
195 </footer>195 </footer>
196-<div class="hint" role="status" aria-live="polite">196+<div class="hint">
197-<span class="hint-nav" :text="document.body.dataset.nav || ''">197+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
198 </span>198 </span>
199+<span role="status" aria-live="polite">
199 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">200 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
200 </span>201 </span>
201 <span class="hint-flash" :text="document.body.dataset.flash || ''">202 <span class="hint-flash" :text="document.body.dataset.flash || ''">
202 </span>203 </span>
204+</span>
203 </div>205 </div>
204 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">206 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
205 <div class="panel-head">207 <div class="panel-head">
206 <h2>Keyboard shortcuts</h2>208 <h2>Keyboard shortcuts</h2>
207-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">209+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
208 <kbd>esc</kbd> close</button>210 <kbd>esc</kbd> close</button>
209 </div>211 </div>
210 <div class="keys-pref">212 <div class="keys-pref">
@@ -338,7 +340,7 @@
338 <div class="panel-head">340 <div class="panel-head">
339 <label for="refs-filter" class="sr">filter branches and tags</label>341 <label for="refs-filter" class="sr">filter branches and tags</label>
340 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">342 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
341-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">343+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
342 <kbd>esc</kbd>344 <kbd>esc</kbd>
343 </button>345 </button>
344 </div>346 </div>
@@ -373,79 +375,79 @@
373 <div class="panel-head">375 <div class="panel-head">
374 <label for="cmd-q" class="sr">go to</label>376 <label for="cmd-q" class="sr">go to</label>
375 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">377 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
376-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">378+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
377 <kbd>esc</kbd>379 <kbd>esc</kbd>
378 </button>380 </button>
379 </div>381 </div>
380 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">382 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
381 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>383 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
382-<a href="/" tabindex="-1">384+<a role="presentation" data-href="/">
383 <span class="lbl">home</span>385 <span class="lbl">home</span>
384 <span class="k">go</span>386 <span class="k">go</span>
385 </a>387 </a>
386 </li>388 </li>
387 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">389 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
388-<a href="/diffs" tabindex="-1">390+<a role="presentation" data-href="/diffs">
389 <span class="lbl">summary</span>391 <span class="lbl">summary</span>
390 <span class="k">section</span>392 <span class="k">section</span>
391 </a>393 </a>
392 </li>394 </li>
393 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">395 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
394-<a href="/diffs/tree/main" tabindex="-1">396+<a role="presentation" data-href="/diffs/tree/main">
395 <span class="lbl">files</span>397 <span class="lbl">files</span>
396 <span class="k">section</span>398 <span class="k">section</span>
397 </a>399 </a>
398 </li>400 </li>
399 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">401 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
400-<a href="/diffs/commits/main" tabindex="-1">402+<a role="presentation" data-href="/diffs/commits/main">
401 <span class="lbl">commits</span>403 <span class="lbl">commits</span>
402 <span class="k">section</span>404 <span class="k">section</span>
403 </a>405 </a>
404 </li>406 </li>
405 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">407 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
406-<a href="/diffs/refs" tabindex="-1">408+<a role="presentation" data-href="/diffs/refs">
407 <span class="lbl">branches &amp; tags</span>409 <span class="lbl">branches &amp; tags</span>
408 <span class="k">section</span>410 <span class="k">section</span>
409 </a>411 </a>
410 </li>412 </li>
411 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">413 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
412-<a href="/diffs/merge-requests" tabindex="-1">414+<a role="presentation" data-href="/diffs/merge-requests">
413 <span class="lbl">merge requests</span>415 <span class="lbl">merge requests</span>
414 <span class="k">section</span>416 <span class="k">section</span>
415 </a>417 </a>
416 </li>418 </li>
417 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">419 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
418-<a href="/diffs/releases" tabindex="-1">420+<a role="presentation" data-href="/diffs/releases">
419 <span class="lbl">releases</span>421 <span class="lbl">releases</span>
420 <span class="k">section</span>422 <span class="k">section</span>
421 </a>423 </a>
422 </li>424 </li>
423 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">425 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
424-<a href="/diffs/actions" tabindex="-1">426+<a role="presentation" data-href="/diffs/actions">
425 <span class="lbl">actions</span>427 <span class="lbl">actions</span>
426 <span class="k">section</span>428 <span class="k">section</span>
427 </a>429 </a>
428 </li>430 </li>
429 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">431 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
430-<a href="/diffs/tree/main" tabindex="-1">432+<a role="presentation" data-href="/diffs/tree/main">
431 <span class="lbl">main</span>433 <span class="lbl">main</span>
432 <span class="k">branch</span>434 <span class="k">branch</span>
433 </a>435 </a>
434 </li>436 </li>
435 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">437 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
436-<a href="/diffs/tree/side" tabindex="-1">438+<a role="presentation" data-href="/diffs/tree/side">
437 <span class="lbl">side</span>439 <span class="lbl">side</span>
438 <span class="k">branch</span>440 <span class="k">branch</span>
439 </a>441 </a>
440 </li>442 </li>
441 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">443 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
442-<a href="/diffs/tree/v1.0.0" tabindex="-1">444+<a role="presentation" data-href="/diffs/tree/v1.0.0">
443 <span class="lbl">v1.0.0</span>445 <span class="lbl">v1.0.0</span>
444 <span class="k">tag</span>446 <span class="k">tag</span>
445 </a>447 </a>
446 </li>448 </li>
447 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">449 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
448-<a href="#" data-fire="keys" tabindex="-1">450+<a role="presentation" data-fire="keys">
449 <span class="lbl">turn single-key shortcuts off</span>451 <span class="lbl">turn single-key shortcuts off</span>
450 <span class="k">action</span>452 <span class="k">action</span>
451 </a>453 </a>
M internal/app/testdata/web/commit-binary.html +19 -17
@@ -184,18 +184,20 @@
184184 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
185185 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
186186 </footer>
187-<div class="hint" role="status" aria-live="polite">
188-<span class="hint-nav" :text="document.body.dataset.nav || ''">
187+<div class="hint">
188+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
189189 </span>
190+<span role="status" aria-live="polite">
190191 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
191192 </span>
192193 <span class="hint-flash" :text="document.body.dataset.flash || ''">
193194 </span>
195+</span>
194196 </div>
195197 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
196198 <div class="panel-head">
197199 <h2>Keyboard shortcuts</h2>
198-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
200+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
199201 <kbd>esc</kbd> close</button>
200202 </div>
201203 <div class="keys-pref">
@@ -329,7 +331,7 @@
329331 <div class="panel-head">
330332 <label for="refs-filter" class="sr">filter branches and tags</label>
331333 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
332-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
334+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
333335 <kbd>esc</kbd>
334336 </button>
335337 </div>
@@ -364,79 +366,79 @@
364366 <div class="panel-head">
365367 <label for="cmd-q" class="sr">go to</label>
366368 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
367-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
369+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
368370 <kbd>esc</kbd>
369371 </button>
370372 </div>
371373 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
372374 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
373-<a href="/" tabindex="-1">
375+<a role="presentation" data-href="/">
374376 <span class="lbl">home</span>
375377 <span class="k">go</span>
376378 </a>
377379 </li>
378380 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
379-<a href="/diffs" tabindex="-1">
381+<a role="presentation" data-href="/diffs">
380382 <span class="lbl">summary</span>
381383 <span class="k">section</span>
382384 </a>
383385 </li>
384386 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
385-<a href="/diffs/tree/main" tabindex="-1">
387+<a role="presentation" data-href="/diffs/tree/main">
386388 <span class="lbl">files</span>
387389 <span class="k">section</span>
388390 </a>
389391 </li>
390392 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
391-<a href="/diffs/commits/main" tabindex="-1">
393+<a role="presentation" data-href="/diffs/commits/main">
392394 <span class="lbl">commits</span>
393395 <span class="k">section</span>
394396 </a>
395397 </li>
396398 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
397-<a href="/diffs/refs" tabindex="-1">
399+<a role="presentation" data-href="/diffs/refs">
398400 <span class="lbl">branches &amp; tags</span>
399401 <span class="k">section</span>
400402 </a>
401403 </li>
402404 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
403-<a href="/diffs/merge-requests" tabindex="-1">
405+<a role="presentation" data-href="/diffs/merge-requests">
404406 <span class="lbl">merge requests</span>
405407 <span class="k">section</span>
406408 </a>
407409 </li>
408410 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
409-<a href="/diffs/releases" tabindex="-1">
411+<a role="presentation" data-href="/diffs/releases">
410412 <span class="lbl">releases</span>
411413 <span class="k">section</span>
412414 </a>
413415 </li>
414416 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
415-<a href="/diffs/actions" tabindex="-1">
417+<a role="presentation" data-href="/diffs/actions">
416418 <span class="lbl">actions</span>
417419 <span class="k">section</span>
418420 </a>
419421 </li>
420422 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
421-<a href="/diffs/tree/main" tabindex="-1">
423+<a role="presentation" data-href="/diffs/tree/main">
422424 <span class="lbl">main</span>
423425 <span class="k">branch</span>
424426 </a>
425427 </li>
426428 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
427-<a href="/diffs/tree/side" tabindex="-1">
429+<a role="presentation" data-href="/diffs/tree/side">
428430 <span class="lbl">side</span>
429431 <span class="k">branch</span>
430432 </a>
431433 </li>
432434 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
433-<a href="/diffs/tree/v1.0.0" tabindex="-1">
435+<a role="presentation" data-href="/diffs/tree/v1.0.0">
434436 <span class="lbl">v1.0.0</span>
435437 <span class="k">tag</span>
436438 </a>
437439 </li>
438440 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
439-<a href="#" data-fire="keys" tabindex="-1">
441+<a role="presentation" data-fire="keys">
440442 <span class="lbl">turn single-key shortcuts off</span>
441443 <span class="k">action</span>
442444 </a>
@@ -184,18 +184,20 @@
184 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">184 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
185 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>185 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
186 </footer>186 </footer>
187-<div class="hint" role="status" aria-live="polite">187+<div class="hint">
188-<span class="hint-nav" :text="document.body.dataset.nav || ''">188+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
189 </span>189 </span>
190+<span role="status" aria-live="polite">
190 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">191 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
191 </span>192 </span>
192 <span class="hint-flash" :text="document.body.dataset.flash || ''">193 <span class="hint-flash" :text="document.body.dataset.flash || ''">
193 </span>194 </span>
195+</span>
194 </div>196 </div>
195 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">197 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
196 <div class="panel-head">198 <div class="panel-head">
197 <h2>Keyboard shortcuts</h2>199 <h2>Keyboard shortcuts</h2>
198-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">200+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
199 <kbd>esc</kbd> close</button>201 <kbd>esc</kbd> close</button>
200 </div>202 </div>
201 <div class="keys-pref">203 <div class="keys-pref">
@@ -329,7 +331,7 @@
329 <div class="panel-head">331 <div class="panel-head">
330 <label for="refs-filter" class="sr">filter branches and tags</label>332 <label for="refs-filter" class="sr">filter branches and tags</label>
331 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">333 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
332-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">334+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
333 <kbd>esc</kbd>335 <kbd>esc</kbd>
334 </button>336 </button>
335 </div>337 </div>
@@ -364,79 +366,79 @@
364 <div class="panel-head">366 <div class="panel-head">
365 <label for="cmd-q" class="sr">go to</label>367 <label for="cmd-q" class="sr">go to</label>
366 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">368 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
367-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">369+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
368 <kbd>esc</kbd>370 <kbd>esc</kbd>
369 </button>371 </button>
370 </div>372 </div>
371 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">373 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
372 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>374 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
373-<a href="/" tabindex="-1">375+<a role="presentation" data-href="/">
374 <span class="lbl">home</span>376 <span class="lbl">home</span>
375 <span class="k">go</span>377 <span class="k">go</span>
376 </a>378 </a>
377 </li>379 </li>
378 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">380 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
379-<a href="/diffs" tabindex="-1">381+<a role="presentation" data-href="/diffs">
380 <span class="lbl">summary</span>382 <span class="lbl">summary</span>
381 <span class="k">section</span>383 <span class="k">section</span>
382 </a>384 </a>
383 </li>385 </li>
384 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">386 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
385-<a href="/diffs/tree/main" tabindex="-1">387+<a role="presentation" data-href="/diffs/tree/main">
386 <span class="lbl">files</span>388 <span class="lbl">files</span>
387 <span class="k">section</span>389 <span class="k">section</span>
388 </a>390 </a>
389 </li>391 </li>
390 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">392 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
391-<a href="/diffs/commits/main" tabindex="-1">393+<a role="presentation" data-href="/diffs/commits/main">
392 <span class="lbl">commits</span>394 <span class="lbl">commits</span>
393 <span class="k">section</span>395 <span class="k">section</span>
394 </a>396 </a>
395 </li>397 </li>
396 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">398 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
397-<a href="/diffs/refs" tabindex="-1">399+<a role="presentation" data-href="/diffs/refs">
398 <span class="lbl">branches &amp; tags</span>400 <span class="lbl">branches &amp; tags</span>
399 <span class="k">section</span>401 <span class="k">section</span>
400 </a>402 </a>
401 </li>403 </li>
402 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">404 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
403-<a href="/diffs/merge-requests" tabindex="-1">405+<a role="presentation" data-href="/diffs/merge-requests">
404 <span class="lbl">merge requests</span>406 <span class="lbl">merge requests</span>
405 <span class="k">section</span>407 <span class="k">section</span>
406 </a>408 </a>
407 </li>409 </li>
408 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">410 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
409-<a href="/diffs/releases" tabindex="-1">411+<a role="presentation" data-href="/diffs/releases">
410 <span class="lbl">releases</span>412 <span class="lbl">releases</span>
411 <span class="k">section</span>413 <span class="k">section</span>
412 </a>414 </a>
413 </li>415 </li>
414 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">416 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
415-<a href="/diffs/actions" tabindex="-1">417+<a role="presentation" data-href="/diffs/actions">
416 <span class="lbl">actions</span>418 <span class="lbl">actions</span>
417 <span class="k">section</span>419 <span class="k">section</span>
418 </a>420 </a>
419 </li>421 </li>
420 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">422 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
421-<a href="/diffs/tree/main" tabindex="-1">423+<a role="presentation" data-href="/diffs/tree/main">
422 <span class="lbl">main</span>424 <span class="lbl">main</span>
423 <span class="k">branch</span>425 <span class="k">branch</span>
424 </a>426 </a>
425 </li>427 </li>
426 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">428 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
427-<a href="/diffs/tree/side" tabindex="-1">429+<a role="presentation" data-href="/diffs/tree/side">
428 <span class="lbl">side</span>430 <span class="lbl">side</span>
429 <span class="k">branch</span>431 <span class="k">branch</span>
430 </a>432 </a>
431 </li>433 </li>
432 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">434 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
433-<a href="/diffs/tree/v1.0.0" tabindex="-1">435+<a role="presentation" data-href="/diffs/tree/v1.0.0">
434 <span class="lbl">v1.0.0</span>436 <span class="lbl">v1.0.0</span>
435 <span class="k">tag</span>437 <span class="k">tag</span>
436 </a>438 </a>
437 </li>439 </li>
438 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">440 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
439-<a href="#" data-fire="keys" tabindex="-1">441+<a role="presentation" data-fire="keys">
440 <span class="lbl">turn single-key shortcuts off</span>442 <span class="lbl">turn single-key shortcuts off</span>
441 <span class="k">action</span>443 <span class="k">action</span>
442 </a>444 </a>
M internal/app/testdata/web/commit-merge.html +19 -17
@@ -226,18 +226,20 @@
226226 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
227227 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
228228 </footer>
229-<div class="hint" role="status" aria-live="polite">
230-<span class="hint-nav" :text="document.body.dataset.nav || ''">
229+<div class="hint">
230+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
231231 </span>
232+<span role="status" aria-live="polite">
232233 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
233234 </span>
234235 <span class="hint-flash" :text="document.body.dataset.flash || ''">
235236 </span>
237+</span>
236238 </div>
237239 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
238240 <div class="panel-head">
239241 <h2>Keyboard shortcuts</h2>
240-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
242+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
241243 <kbd>esc</kbd> close</button>
242244 </div>
243245 <div class="keys-pref">
@@ -371,7 +373,7 @@
371373 <div class="panel-head">
372374 <label for="refs-filter" class="sr">filter branches and tags</label>
373375 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
374-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
376+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
375377 <kbd>esc</kbd>
376378 </button>
377379 </div>
@@ -406,79 +408,79 @@
406408 <div class="panel-head">
407409 <label for="cmd-q" class="sr">go to</label>
408410 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
409-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
411+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
410412 <kbd>esc</kbd>
411413 </button>
412414 </div>
413415 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
414416 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
415-<a href="/" tabindex="-1">
417+<a role="presentation" data-href="/">
416418 <span class="lbl">home</span>
417419 <span class="k">go</span>
418420 </a>
419421 </li>
420422 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
421-<a href="/diffs" tabindex="-1">
423+<a role="presentation" data-href="/diffs">
422424 <span class="lbl">summary</span>
423425 <span class="k">section</span>
424426 </a>
425427 </li>
426428 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
427-<a href="/diffs/tree/main" tabindex="-1">
429+<a role="presentation" data-href="/diffs/tree/main">
428430 <span class="lbl">files</span>
429431 <span class="k">section</span>
430432 </a>
431433 </li>
432434 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
433-<a href="/diffs/commits/main" tabindex="-1">
435+<a role="presentation" data-href="/diffs/commits/main">
434436 <span class="lbl">commits</span>
435437 <span class="k">section</span>
436438 </a>
437439 </li>
438440 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
439-<a href="/diffs/refs" tabindex="-1">
441+<a role="presentation" data-href="/diffs/refs">
440442 <span class="lbl">branches &amp; tags</span>
441443 <span class="k">section</span>
442444 </a>
443445 </li>
444446 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
445-<a href="/diffs/merge-requests" tabindex="-1">
447+<a role="presentation" data-href="/diffs/merge-requests">
446448 <span class="lbl">merge requests</span>
447449 <span class="k">section</span>
448450 </a>
449451 </li>
450452 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
451-<a href="/diffs/releases" tabindex="-1">
453+<a role="presentation" data-href="/diffs/releases">
452454 <span class="lbl">releases</span>
453455 <span class="k">section</span>
454456 </a>
455457 </li>
456458 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
457-<a href="/diffs/actions" tabindex="-1">
459+<a role="presentation" data-href="/diffs/actions">
458460 <span class="lbl">actions</span>
459461 <span class="k">section</span>
460462 </a>
461463 </li>
462464 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
463-<a href="/diffs/tree/main" tabindex="-1">
465+<a role="presentation" data-href="/diffs/tree/main">
464466 <span class="lbl">main</span>
465467 <span class="k">branch</span>
466468 </a>
467469 </li>
468470 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
469-<a href="/diffs/tree/side" tabindex="-1">
471+<a role="presentation" data-href="/diffs/tree/side">
470472 <span class="lbl">side</span>
471473 <span class="k">branch</span>
472474 </a>
473475 </li>
474476 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
475-<a href="/diffs/tree/v1.0.0" tabindex="-1">
477+<a role="presentation" data-href="/diffs/tree/v1.0.0">
476478 <span class="lbl">v1.0.0</span>
477479 <span class="k">tag</span>
478480 </a>
479481 </li>
480482 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
481-<a href="#" data-fire="keys" tabindex="-1">
483+<a role="presentation" data-fire="keys">
482484 <span class="lbl">turn single-key shortcuts off</span>
483485 <span class="k">action</span>
484486 </a>
@@ -226,18 +226,20 @@
226 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">226 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
227 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>227 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
228 </footer>228 </footer>
229-<div class="hint" role="status" aria-live="polite">229+<div class="hint">
230-<span class="hint-nav" :text="document.body.dataset.nav || ''">230+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
231 </span>231 </span>
232+<span role="status" aria-live="polite">
232 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">233 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
233 </span>234 </span>
234 <span class="hint-flash" :text="document.body.dataset.flash || ''">235 <span class="hint-flash" :text="document.body.dataset.flash || ''">
235 </span>236 </span>
237+</span>
236 </div>238 </div>
237 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">239 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
238 <div class="panel-head">240 <div class="panel-head">
239 <h2>Keyboard shortcuts</h2>241 <h2>Keyboard shortcuts</h2>
240-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">242+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
241 <kbd>esc</kbd> close</button>243 <kbd>esc</kbd> close</button>
242 </div>244 </div>
243 <div class="keys-pref">245 <div class="keys-pref">
@@ -371,7 +373,7 @@
371 <div class="panel-head">373 <div class="panel-head">
372 <label for="refs-filter" class="sr">filter branches and tags</label>374 <label for="refs-filter" class="sr">filter branches and tags</label>
373 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">375 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
374-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">376+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
375 <kbd>esc</kbd>377 <kbd>esc</kbd>
376 </button>378 </button>
377 </div>379 </div>
@@ -406,79 +408,79 @@
406 <div class="panel-head">408 <div class="panel-head">
407 <label for="cmd-q" class="sr">go to</label>409 <label for="cmd-q" class="sr">go to</label>
408 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">410 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
409-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">411+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
410 <kbd>esc</kbd>412 <kbd>esc</kbd>
411 </button>413 </button>
412 </div>414 </div>
413 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">415 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
414 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>416 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
415-<a href="/" tabindex="-1">417+<a role="presentation" data-href="/">
416 <span class="lbl">home</span>418 <span class="lbl">home</span>
417 <span class="k">go</span>419 <span class="k">go</span>
418 </a>420 </a>
419 </li>421 </li>
420 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">422 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
421-<a href="/diffs" tabindex="-1">423+<a role="presentation" data-href="/diffs">
422 <span class="lbl">summary</span>424 <span class="lbl">summary</span>
423 <span class="k">section</span>425 <span class="k">section</span>
424 </a>426 </a>
425 </li>427 </li>
426 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">428 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
427-<a href="/diffs/tree/main" tabindex="-1">429+<a role="presentation" data-href="/diffs/tree/main">
428 <span class="lbl">files</span>430 <span class="lbl">files</span>
429 <span class="k">section</span>431 <span class="k">section</span>
430 </a>432 </a>
431 </li>433 </li>
432 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">434 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
433-<a href="/diffs/commits/main" tabindex="-1">435+<a role="presentation" data-href="/diffs/commits/main">
434 <span class="lbl">commits</span>436 <span class="lbl">commits</span>
435 <span class="k">section</span>437 <span class="k">section</span>
436 </a>438 </a>
437 </li>439 </li>
438 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">440 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
439-<a href="/diffs/refs" tabindex="-1">441+<a role="presentation" data-href="/diffs/refs">
440 <span class="lbl">branches &amp; tags</span>442 <span class="lbl">branches &amp; tags</span>
441 <span class="k">section</span>443 <span class="k">section</span>
442 </a>444 </a>
443 </li>445 </li>
444 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">446 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
445-<a href="/diffs/merge-requests" tabindex="-1">447+<a role="presentation" data-href="/diffs/merge-requests">
446 <span class="lbl">merge requests</span>448 <span class="lbl">merge requests</span>
447 <span class="k">section</span>449 <span class="k">section</span>
448 </a>450 </a>
449 </li>451 </li>
450 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">452 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
451-<a href="/diffs/releases" tabindex="-1">453+<a role="presentation" data-href="/diffs/releases">
452 <span class="lbl">releases</span>454 <span class="lbl">releases</span>
453 <span class="k">section</span>455 <span class="k">section</span>
454 </a>456 </a>
455 </li>457 </li>
456 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">458 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
457-<a href="/diffs/actions" tabindex="-1">459+<a role="presentation" data-href="/diffs/actions">
458 <span class="lbl">actions</span>460 <span class="lbl">actions</span>
459 <span class="k">section</span>461 <span class="k">section</span>
460 </a>462 </a>
461 </li>463 </li>
462 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">464 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
463-<a href="/diffs/tree/main" tabindex="-1">465+<a role="presentation" data-href="/diffs/tree/main">
464 <span class="lbl">main</span>466 <span class="lbl">main</span>
465 <span class="k">branch</span>467 <span class="k">branch</span>
466 </a>468 </a>
467 </li>469 </li>
468 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">470 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
469-<a href="/diffs/tree/side" tabindex="-1">471+<a role="presentation" data-href="/diffs/tree/side">
470 <span class="lbl">side</span>472 <span class="lbl">side</span>
471 <span class="k">branch</span>473 <span class="k">branch</span>
472 </a>474 </a>
473 </li>475 </li>
474 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">476 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
475-<a href="/diffs/tree/v1.0.0" tabindex="-1">477+<a role="presentation" data-href="/diffs/tree/v1.0.0">
476 <span class="lbl">v1.0.0</span>478 <span class="lbl">v1.0.0</span>
477 <span class="k">tag</span>479 <span class="k">tag</span>
478 </a>480 </a>
479 </li>481 </li>
480 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">482 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
481-<a href="#" data-fire="keys" tabindex="-1">483+<a role="presentation" data-fire="keys">
482 <span class="lbl">turn single-key shortcuts off</span>484 <span class="lbl">turn single-key shortcuts off</span>
483 <span class="k">action</span>485 <span class="k">action</span>
484 </a>486 </a>
M internal/app/testdata/web/commit-modify-split.html +19 -17
@@ -349,18 +349,20 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
349349 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
350350 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
351351 </footer>
352-<div class="hint" role="status" aria-live="polite">
353-<span class="hint-nav" :text="document.body.dataset.nav || ''">
352+<div class="hint">
353+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
354354 </span>
355+<span role="status" aria-live="polite">
355356 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
356357 </span>
357358 <span class="hint-flash" :text="document.body.dataset.flash || ''">
358359 </span>
360+</span>
359361 </div>
360362 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
361363 <div class="panel-head">
362364 <h2>Keyboard shortcuts</h2>
363-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
365+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
364366 <kbd>esc</kbd> close</button>
365367 </div>
366368 <div class="keys-pref">
@@ -494,7 +496,7 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
494496 <div class="panel-head">
495497 <label for="refs-filter" class="sr">filter branches and tags</label>
496498 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
497-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
499+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
498500 <kbd>esc</kbd>
499501 </button>
500502 </div>
@@ -529,79 +531,79 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
529531 <div class="panel-head">
530532 <label for="cmd-q" class="sr">go to</label>
531533 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
532-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
534+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
533535 <kbd>esc</kbd>
534536 </button>
535537 </div>
536538 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
537539 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
538-<a href="/" tabindex="-1">
540+<a role="presentation" data-href="/">
539541 <span class="lbl">home</span>
540542 <span class="k">go</span>
541543 </a>
542544 </li>
543545 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
544-<a href="/diffs" tabindex="-1">
546+<a role="presentation" data-href="/diffs">
545547 <span class="lbl">summary</span>
546548 <span class="k">section</span>
547549 </a>
548550 </li>
549551 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
550-<a href="/diffs/tree/main" tabindex="-1">
552+<a role="presentation" data-href="/diffs/tree/main">
551553 <span class="lbl">files</span>
552554 <span class="k">section</span>
553555 </a>
554556 </li>
555557 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
556-<a href="/diffs/commits/main" tabindex="-1">
558+<a role="presentation" data-href="/diffs/commits/main">
557559 <span class="lbl">commits</span>
558560 <span class="k">section</span>
559561 </a>
560562 </li>
561563 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
562-<a href="/diffs/refs" tabindex="-1">
564+<a role="presentation" data-href="/diffs/refs">
563565 <span class="lbl">branches &amp; tags</span>
564566 <span class="k">section</span>
565567 </a>
566568 </li>
567569 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
568-<a href="/diffs/merge-requests" tabindex="-1">
570+<a role="presentation" data-href="/diffs/merge-requests">
569571 <span class="lbl">merge requests</span>
570572 <span class="k">section</span>
571573 </a>
572574 </li>
573575 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
574-<a href="/diffs/releases" tabindex="-1">
576+<a role="presentation" data-href="/diffs/releases">
575577 <span class="lbl">releases</span>
576578 <span class="k">section</span>
577579 </a>
578580 </li>
579581 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
580-<a href="/diffs/actions" tabindex="-1">
582+<a role="presentation" data-href="/diffs/actions">
581583 <span class="lbl">actions</span>
582584 <span class="k">section</span>
583585 </a>
584586 </li>
585587 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
586-<a href="/diffs/tree/main" tabindex="-1">
588+<a role="presentation" data-href="/diffs/tree/main">
587589 <span class="lbl">main</span>
588590 <span class="k">branch</span>
589591 </a>
590592 </li>
591593 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
592-<a href="/diffs/tree/side" tabindex="-1">
594+<a role="presentation" data-href="/diffs/tree/side">
593595 <span class="lbl">side</span>
594596 <span class="k">branch</span>
595597 </a>
596598 </li>
597599 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
598-<a href="/diffs/tree/v1.0.0" tabindex="-1">
600+<a role="presentation" data-href="/diffs/tree/v1.0.0">
599601 <span class="lbl">v1.0.0</span>
600602 <span class="k">tag</span>
601603 </a>
602604 </li>
603605 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
604-<a href="#" data-fire="keys" tabindex="-1">
606+<a role="presentation" data-fire="keys">
605607 <span class="lbl">turn single-key shortcuts off</span>
606608 <span class="k">action</span>
607609 </a>
@@ -349,18 +349,20 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
349 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">349 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
350 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>350 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
351 </footer>351 </footer>
352-<div class="hint" role="status" aria-live="polite">352+<div class="hint">
353-<span class="hint-nav" :text="document.body.dataset.nav || ''">353+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
354 </span>354 </span>
355+<span role="status" aria-live="polite">
355 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">356 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
356 </span>357 </span>
357 <span class="hint-flash" :text="document.body.dataset.flash || ''">358 <span class="hint-flash" :text="document.body.dataset.flash || ''">
358 </span>359 </span>
360+</span>
359 </div>361 </div>
360 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">362 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
361 <div class="panel-head">363 <div class="panel-head">
362 <h2>Keyboard shortcuts</h2>364 <h2>Keyboard shortcuts</h2>
363-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">365+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
364 <kbd>esc</kbd> close</button>366 <kbd>esc</kbd> close</button>
365 </div>367 </div>
366 <div class="keys-pref">368 <div class="keys-pref">
@@ -494,7 +496,7 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
494 <div class="panel-head">496 <div class="panel-head">
495 <label for="refs-filter" class="sr">filter branches and tags</label>497 <label for="refs-filter" class="sr">filter branches and tags</label>
496 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">498 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
497-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">499+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
498 <kbd>esc</kbd>500 <kbd>esc</kbd>
499 </button>501 </button>
500 </div>502 </div>
@@ -529,79 +531,79 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
529 <div class="panel-head">531 <div class="panel-head">
530 <label for="cmd-q" class="sr">go to</label>532 <label for="cmd-q" class="sr">go to</label>
531 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">533 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
532-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">534+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
533 <kbd>esc</kbd>535 <kbd>esc</kbd>
534 </button>536 </button>
535 </div>537 </div>
536 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">538 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
537 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>539 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
538-<a href="/" tabindex="-1">540+<a role="presentation" data-href="/">
539 <span class="lbl">home</span>541 <span class="lbl">home</span>
540 <span class="k">go</span>542 <span class="k">go</span>
541 </a>543 </a>
542 </li>544 </li>
543 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">545 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
544-<a href="/diffs" tabindex="-1">546+<a role="presentation" data-href="/diffs">
545 <span class="lbl">summary</span>547 <span class="lbl">summary</span>
546 <span class="k">section</span>548 <span class="k">section</span>
547 </a>549 </a>
548 </li>550 </li>
549 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">551 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
550-<a href="/diffs/tree/main" tabindex="-1">552+<a role="presentation" data-href="/diffs/tree/main">
551 <span class="lbl">files</span>553 <span class="lbl">files</span>
552 <span class="k">section</span>554 <span class="k">section</span>
553 </a>555 </a>
554 </li>556 </li>
555 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">557 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
556-<a href="/diffs/commits/main" tabindex="-1">558+<a role="presentation" data-href="/diffs/commits/main">
557 <span class="lbl">commits</span>559 <span class="lbl">commits</span>
558 <span class="k">section</span>560 <span class="k">section</span>
559 </a>561 </a>
560 </li>562 </li>
561 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">563 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
562-<a href="/diffs/refs" tabindex="-1">564+<a role="presentation" data-href="/diffs/refs">
563 <span class="lbl">branches &amp; tags</span>565 <span class="lbl">branches &amp; tags</span>
564 <span class="k">section</span>566 <span class="k">section</span>
565 </a>567 </a>
566 </li>568 </li>
567 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">569 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
568-<a href="/diffs/merge-requests" tabindex="-1">570+<a role="presentation" data-href="/diffs/merge-requests">
569 <span class="lbl">merge requests</span>571 <span class="lbl">merge requests</span>
570 <span class="k">section</span>572 <span class="k">section</span>
571 </a>573 </a>
572 </li>574 </li>
573 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">575 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
574-<a href="/diffs/releases" tabindex="-1">576+<a role="presentation" data-href="/diffs/releases">
575 <span class="lbl">releases</span>577 <span class="lbl">releases</span>
576 <span class="k">section</span>578 <span class="k">section</span>
577 </a>579 </a>
578 </li>580 </li>
579 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">581 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
580-<a href="/diffs/actions" tabindex="-1">582+<a role="presentation" data-href="/diffs/actions">
581 <span class="lbl">actions</span>583 <span class="lbl">actions</span>
582 <span class="k">section</span>584 <span class="k">section</span>
583 </a>585 </a>
584 </li>586 </li>
585 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">587 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
586-<a href="/diffs/tree/main" tabindex="-1">588+<a role="presentation" data-href="/diffs/tree/main">
587 <span class="lbl">main</span>589 <span class="lbl">main</span>
588 <span class="k">branch</span>590 <span class="k">branch</span>
589 </a>591 </a>
590 </li>592 </li>
591 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">593 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
592-<a href="/diffs/tree/side" tabindex="-1">594+<a role="presentation" data-href="/diffs/tree/side">
593 <span class="lbl">side</span>595 <span class="lbl">side</span>
594 <span class="k">branch</span>596 <span class="k">branch</span>
595 </a>597 </a>
596 </li>598 </li>
597 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">599 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
598-<a href="/diffs/tree/v1.0.0" tabindex="-1">600+<a role="presentation" data-href="/diffs/tree/v1.0.0">
599 <span class="lbl">v1.0.0</span>601 <span class="lbl">v1.0.0</span>
600 <span class="k">tag</span>602 <span class="k">tag</span>
601 </a>603 </a>
602 </li>604 </li>
603 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">605 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
604-<a href="#" data-fire="keys" tabindex="-1">606+<a role="presentation" data-fire="keys">
605 <span class="lbl">turn single-key shortcuts off</span>607 <span class="lbl">turn single-key shortcuts off</span>
606 <span class="k">action</span>608 <span class="k">action</span>
607 </a>609 </a>
M internal/app/testdata/web/commit-modify.html +19 -17
@@ -349,18 +349,20 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
349349 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
350350 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
351351 </footer>
352-<div class="hint" role="status" aria-live="polite">
353-<span class="hint-nav" :text="document.body.dataset.nav || ''">
352+<div class="hint">
353+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
354354 </span>
355+<span role="status" aria-live="polite">
355356 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
356357 </span>
357358 <span class="hint-flash" :text="document.body.dataset.flash || ''">
358359 </span>
360+</span>
359361 </div>
360362 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
361363 <div class="panel-head">
362364 <h2>Keyboard shortcuts</h2>
363-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
365+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
364366 <kbd>esc</kbd> close</button>
365367 </div>
366368 <div class="keys-pref">
@@ -494,7 +496,7 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
494496 <div class="panel-head">
495497 <label for="refs-filter" class="sr">filter branches and tags</label>
496498 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
497-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
499+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
498500 <kbd>esc</kbd>
499501 </button>
500502 </div>
@@ -529,79 +531,79 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
529531 <div class="panel-head">
530532 <label for="cmd-q" class="sr">go to</label>
531533 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
532-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
534+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
533535 <kbd>esc</kbd>
534536 </button>
535537 </div>
536538 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
537539 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
538-<a href="/" tabindex="-1">
540+<a role="presentation" data-href="/">
539541 <span class="lbl">home</span>
540542 <span class="k">go</span>
541543 </a>
542544 </li>
543545 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
544-<a href="/diffs" tabindex="-1">
546+<a role="presentation" data-href="/diffs">
545547 <span class="lbl">summary</span>
546548 <span class="k">section</span>
547549 </a>
548550 </li>
549551 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
550-<a href="/diffs/tree/main" tabindex="-1">
552+<a role="presentation" data-href="/diffs/tree/main">
551553 <span class="lbl">files</span>
552554 <span class="k">section</span>
553555 </a>
554556 </li>
555557 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
556-<a href="/diffs/commits/main" tabindex="-1">
558+<a role="presentation" data-href="/diffs/commits/main">
557559 <span class="lbl">commits</span>
558560 <span class="k">section</span>
559561 </a>
560562 </li>
561563 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
562-<a href="/diffs/refs" tabindex="-1">
564+<a role="presentation" data-href="/diffs/refs">
563565 <span class="lbl">branches &amp; tags</span>
564566 <span class="k">section</span>
565567 </a>
566568 </li>
567569 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
568-<a href="/diffs/merge-requests" tabindex="-1">
570+<a role="presentation" data-href="/diffs/merge-requests">
569571 <span class="lbl">merge requests</span>
570572 <span class="k">section</span>
571573 </a>
572574 </li>
573575 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
574-<a href="/diffs/releases" tabindex="-1">
576+<a role="presentation" data-href="/diffs/releases">
575577 <span class="lbl">releases</span>
576578 <span class="k">section</span>
577579 </a>
578580 </li>
579581 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
580-<a href="/diffs/actions" tabindex="-1">
582+<a role="presentation" data-href="/diffs/actions">
581583 <span class="lbl">actions</span>
582584 <span class="k">section</span>
583585 </a>
584586 </li>
585587 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
586-<a href="/diffs/tree/main" tabindex="-1">
588+<a role="presentation" data-href="/diffs/tree/main">
587589 <span class="lbl">main</span>
588590 <span class="k">branch</span>
589591 </a>
590592 </li>
591593 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
592-<a href="/diffs/tree/side" tabindex="-1">
594+<a role="presentation" data-href="/diffs/tree/side">
593595 <span class="lbl">side</span>
594596 <span class="k">branch</span>
595597 </a>
596598 </li>
597599 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
598-<a href="/diffs/tree/v1.0.0" tabindex="-1">
600+<a role="presentation" data-href="/diffs/tree/v1.0.0">
599601 <span class="lbl">v1.0.0</span>
600602 <span class="k">tag</span>
601603 </a>
602604 </li>
603605 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
604-<a href="#" data-fire="keys" tabindex="-1">
606+<a role="presentation" data-fire="keys">
605607 <span class="lbl">turn single-key shortcuts off</span>
606608 <span class="k">action</span>
607609 </a>
@@ -349,18 +349,20 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
349 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">349 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
350 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>350 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
351 </footer>351 </footer>
352-<div class="hint" role="status" aria-live="polite">352+<div class="hint">
353-<span class="hint-nav" :text="document.body.dataset.nav || ''">353+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
354 </span>354 </span>
355+<span role="status" aria-live="polite">
355 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">356 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
356 </span>357 </span>
357 <span class="hint-flash" :text="document.body.dataset.flash || ''">358 <span class="hint-flash" :text="document.body.dataset.flash || ''">
358 </span>359 </span>
360+</span>
359 </div>361 </div>
360 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">362 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
361 <div class="panel-head">363 <div class="panel-head">
362 <h2>Keyboard shortcuts</h2>364 <h2>Keyboard shortcuts</h2>
363-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">365+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
364 <kbd>esc</kbd> close</button>366 <kbd>esc</kbd> close</button>
365 </div>367 </div>
366 <div class="keys-pref">368 <div class="keys-pref">
@@ -494,7 +496,7 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
494 <div class="panel-head">496 <div class="panel-head">
495 <label for="refs-filter" class="sr">filter branches and tags</label>497 <label for="refs-filter" class="sr">filter branches and tags</label>
496 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">498 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
497-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">499+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
498 <kbd>esc</kbd>500 <kbd>esc</kbd>
499 </button>501 </button>
500 </div>502 </div>
@@ -529,79 +531,79 @@ And &lt;b&gt;html&lt;/b&gt; &amp; &#34;quotes&#34;.</pre>
529 <div class="panel-head">531 <div class="panel-head">
530 <label for="cmd-q" class="sr">go to</label>532 <label for="cmd-q" class="sr">go to</label>
531 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">533 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
532-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">534+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
533 <kbd>esc</kbd>535 <kbd>esc</kbd>
534 </button>536 </button>
535 </div>537 </div>
536 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">538 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
537 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>539 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
538-<a href="/" tabindex="-1">540+<a role="presentation" data-href="/">
539 <span class="lbl">home</span>541 <span class="lbl">home</span>
540 <span class="k">go</span>542 <span class="k">go</span>
541 </a>543 </a>
542 </li>544 </li>
543 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">545 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
544-<a href="/diffs" tabindex="-1">546+<a role="presentation" data-href="/diffs">
545 <span class="lbl">summary</span>547 <span class="lbl">summary</span>
546 <span class="k">section</span>548 <span class="k">section</span>
547 </a>549 </a>
548 </li>550 </li>
549 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">551 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
550-<a href="/diffs/tree/main" tabindex="-1">552+<a role="presentation" data-href="/diffs/tree/main">
551 <span class="lbl">files</span>553 <span class="lbl">files</span>
552 <span class="k">section</span>554 <span class="k">section</span>
553 </a>555 </a>
554 </li>556 </li>
555 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">557 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
556-<a href="/diffs/commits/main" tabindex="-1">558+<a role="presentation" data-href="/diffs/commits/main">
557 <span class="lbl">commits</span>559 <span class="lbl">commits</span>
558 <span class="k">section</span>560 <span class="k">section</span>
559 </a>561 </a>
560 </li>562 </li>
561 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">563 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
562-<a href="/diffs/refs" tabindex="-1">564+<a role="presentation" data-href="/diffs/refs">
563 <span class="lbl">branches &amp; tags</span>565 <span class="lbl">branches &amp; tags</span>
564 <span class="k">section</span>566 <span class="k">section</span>
565 </a>567 </a>
566 </li>568 </li>
567 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">569 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
568-<a href="/diffs/merge-requests" tabindex="-1">570+<a role="presentation" data-href="/diffs/merge-requests">
569 <span class="lbl">merge requests</span>571 <span class="lbl">merge requests</span>
570 <span class="k">section</span>572 <span class="k">section</span>
571 </a>573 </a>
572 </li>574 </li>
573 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">575 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
574-<a href="/diffs/releases" tabindex="-1">576+<a role="presentation" data-href="/diffs/releases">
575 <span class="lbl">releases</span>577 <span class="lbl">releases</span>
576 <span class="k">section</span>578 <span class="k">section</span>
577 </a>579 </a>
578 </li>580 </li>
579 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">581 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
580-<a href="/diffs/actions" tabindex="-1">582+<a role="presentation" data-href="/diffs/actions">
581 <span class="lbl">actions</span>583 <span class="lbl">actions</span>
582 <span class="k">section</span>584 <span class="k">section</span>
583 </a>585 </a>
584 </li>586 </li>
585 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">587 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
586-<a href="/diffs/tree/main" tabindex="-1">588+<a role="presentation" data-href="/diffs/tree/main">
587 <span class="lbl">main</span>589 <span class="lbl">main</span>
588 <span class="k">branch</span>590 <span class="k">branch</span>
589 </a>591 </a>
590 </li>592 </li>
591 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">593 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
592-<a href="/diffs/tree/side" tabindex="-1">594+<a role="presentation" data-href="/diffs/tree/side">
593 <span class="lbl">side</span>595 <span class="lbl">side</span>
594 <span class="k">branch</span>596 <span class="k">branch</span>
595 </a>597 </a>
596 </li>598 </li>
597 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">599 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
598-<a href="/diffs/tree/v1.0.0" tabindex="-1">600+<a role="presentation" data-href="/diffs/tree/v1.0.0">
599 <span class="lbl">v1.0.0</span>601 <span class="lbl">v1.0.0</span>
600 <span class="k">tag</span>602 <span class="k">tag</span>
601 </a>603 </a>
602 </li>604 </li>
603 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">605 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
604-<a href="#" data-fire="keys" tabindex="-1">606+<a role="presentation" data-fire="keys">
605 <span class="lbl">turn single-key shortcuts off</span>607 <span class="lbl">turn single-key shortcuts off</span>
606 <span class="k">action</span>608 <span class="k">action</span>
607 </a>609 </a>
M internal/app/testdata/web/commit-rename.html +19 -17
@@ -253,18 +253,20 @@
253253 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
254254 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
255255 </footer>
256-<div class="hint" role="status" aria-live="polite">
257-<span class="hint-nav" :text="document.body.dataset.nav || ''">
256+<div class="hint">
257+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
258258 </span>
259+<span role="status" aria-live="polite">
259260 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
260261 </span>
261262 <span class="hint-flash" :text="document.body.dataset.flash || ''">
262263 </span>
264+</span>
263265 </div>
264266 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
265267 <div class="panel-head">
266268 <h2>Keyboard shortcuts</h2>
267-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
269+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
268270 <kbd>esc</kbd> close</button>
269271 </div>
270272 <div class="keys-pref">
@@ -398,7 +400,7 @@
398400 <div class="panel-head">
399401 <label for="refs-filter" class="sr">filter branches and tags</label>
400402 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
401-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
403+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
402404 <kbd>esc</kbd>
403405 </button>
404406 </div>
@@ -433,79 +435,79 @@
433435 <div class="panel-head">
434436 <label for="cmd-q" class="sr">go to</label>
435437 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
436-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
438+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
437439 <kbd>esc</kbd>
438440 </button>
439441 </div>
440442 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
441443 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
442-<a href="/" tabindex="-1">
444+<a role="presentation" data-href="/">
443445 <span class="lbl">home</span>
444446 <span class="k">go</span>
445447 </a>
446448 </li>
447449 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
448-<a href="/diffs" tabindex="-1">
450+<a role="presentation" data-href="/diffs">
449451 <span class="lbl">summary</span>
450452 <span class="k">section</span>
451453 </a>
452454 </li>
453455 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
454-<a href="/diffs/tree/main" tabindex="-1">
456+<a role="presentation" data-href="/diffs/tree/main">
455457 <span class="lbl">files</span>
456458 <span class="k">section</span>
457459 </a>
458460 </li>
459461 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
460-<a href="/diffs/commits/main" tabindex="-1">
462+<a role="presentation" data-href="/diffs/commits/main">
461463 <span class="lbl">commits</span>
462464 <span class="k">section</span>
463465 </a>
464466 </li>
465467 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
466-<a href="/diffs/refs" tabindex="-1">
468+<a role="presentation" data-href="/diffs/refs">
467469 <span class="lbl">branches &amp; tags</span>
468470 <span class="k">section</span>
469471 </a>
470472 </li>
471473 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
472-<a href="/diffs/merge-requests" tabindex="-1">
474+<a role="presentation" data-href="/diffs/merge-requests">
473475 <span class="lbl">merge requests</span>
474476 <span class="k">section</span>
475477 </a>
476478 </li>
477479 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
478-<a href="/diffs/releases" tabindex="-1">
480+<a role="presentation" data-href="/diffs/releases">
479481 <span class="lbl">releases</span>
480482 <span class="k">section</span>
481483 </a>
482484 </li>
483485 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
484-<a href="/diffs/actions" tabindex="-1">
486+<a role="presentation" data-href="/diffs/actions">
485487 <span class="lbl">actions</span>
486488 <span class="k">section</span>
487489 </a>
488490 </li>
489491 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
490-<a href="/diffs/tree/main" tabindex="-1">
492+<a role="presentation" data-href="/diffs/tree/main">
491493 <span class="lbl">main</span>
492494 <span class="k">branch</span>
493495 </a>
494496 </li>
495497 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
496-<a href="/diffs/tree/side" tabindex="-1">
498+<a role="presentation" data-href="/diffs/tree/side">
497499 <span class="lbl">side</span>
498500 <span class="k">branch</span>
499501 </a>
500502 </li>
501503 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
502-<a href="/diffs/tree/v1.0.0" tabindex="-1">
504+<a role="presentation" data-href="/diffs/tree/v1.0.0">
503505 <span class="lbl">v1.0.0</span>
504506 <span class="k">tag</span>
505507 </a>
506508 </li>
507509 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
508-<a href="#" data-fire="keys" tabindex="-1">
510+<a role="presentation" data-fire="keys">
509511 <span class="lbl">turn single-key shortcuts off</span>
510512 <span class="k">action</span>
511513 </a>
@@ -253,18 +253,20 @@
253 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">253 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
254 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>254 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
255 </footer>255 </footer>
256-<div class="hint" role="status" aria-live="polite">256+<div class="hint">
257-<span class="hint-nav" :text="document.body.dataset.nav || ''">257+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
258 </span>258 </span>
259+<span role="status" aria-live="polite">
259 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">260 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
260 </span>261 </span>
261 <span class="hint-flash" :text="document.body.dataset.flash || ''">262 <span class="hint-flash" :text="document.body.dataset.flash || ''">
262 </span>263 </span>
264+</span>
263 </div>265 </div>
264 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">266 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
265 <div class="panel-head">267 <div class="panel-head">
266 <h2>Keyboard shortcuts</h2>268 <h2>Keyboard shortcuts</h2>
267-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">269+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
268 <kbd>esc</kbd> close</button>270 <kbd>esc</kbd> close</button>
269 </div>271 </div>
270 <div class="keys-pref">272 <div class="keys-pref">
@@ -398,7 +400,7 @@
398 <div class="panel-head">400 <div class="panel-head">
399 <label for="refs-filter" class="sr">filter branches and tags</label>401 <label for="refs-filter" class="sr">filter branches and tags</label>
400 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">402 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
401-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">403+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
402 <kbd>esc</kbd>404 <kbd>esc</kbd>
403 </button>405 </button>
404 </div>406 </div>
@@ -433,79 +435,79 @@
433 <div class="panel-head">435 <div class="panel-head">
434 <label for="cmd-q" class="sr">go to</label>436 <label for="cmd-q" class="sr">go to</label>
435 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">437 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
436-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">438+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
437 <kbd>esc</kbd>439 <kbd>esc</kbd>
438 </button>440 </button>
439 </div>441 </div>
440 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">442 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
441 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>443 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
442-<a href="/" tabindex="-1">444+<a role="presentation" data-href="/">
443 <span class="lbl">home</span>445 <span class="lbl">home</span>
444 <span class="k">go</span>446 <span class="k">go</span>
445 </a>447 </a>
446 </li>448 </li>
447 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">449 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
448-<a href="/diffs" tabindex="-1">450+<a role="presentation" data-href="/diffs">
449 <span class="lbl">summary</span>451 <span class="lbl">summary</span>
450 <span class="k">section</span>452 <span class="k">section</span>
451 </a>453 </a>
452 </li>454 </li>
453 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">455 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
454-<a href="/diffs/tree/main" tabindex="-1">456+<a role="presentation" data-href="/diffs/tree/main">
455 <span class="lbl">files</span>457 <span class="lbl">files</span>
456 <span class="k">section</span>458 <span class="k">section</span>
457 </a>459 </a>
458 </li>460 </li>
459 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">461 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
460-<a href="/diffs/commits/main" tabindex="-1">462+<a role="presentation" data-href="/diffs/commits/main">
461 <span class="lbl">commits</span>463 <span class="lbl">commits</span>
462 <span class="k">section</span>464 <span class="k">section</span>
463 </a>465 </a>
464 </li>466 </li>
465 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">467 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
466-<a href="/diffs/refs" tabindex="-1">468+<a role="presentation" data-href="/diffs/refs">
467 <span class="lbl">branches &amp; tags</span>469 <span class="lbl">branches &amp; tags</span>
468 <span class="k">section</span>470 <span class="k">section</span>
469 </a>471 </a>
470 </li>472 </li>
471 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">473 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
472-<a href="/diffs/merge-requests" tabindex="-1">474+<a role="presentation" data-href="/diffs/merge-requests">
473 <span class="lbl">merge requests</span>475 <span class="lbl">merge requests</span>
474 <span class="k">section</span>476 <span class="k">section</span>
475 </a>477 </a>
476 </li>478 </li>
477 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">479 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
478-<a href="/diffs/releases" tabindex="-1">480+<a role="presentation" data-href="/diffs/releases">
479 <span class="lbl">releases</span>481 <span class="lbl">releases</span>
480 <span class="k">section</span>482 <span class="k">section</span>
481 </a>483 </a>
482 </li>484 </li>
483 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">485 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
484-<a href="/diffs/actions" tabindex="-1">486+<a role="presentation" data-href="/diffs/actions">
485 <span class="lbl">actions</span>487 <span class="lbl">actions</span>
486 <span class="k">section</span>488 <span class="k">section</span>
487 </a>489 </a>
488 </li>490 </li>
489 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">491 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
490-<a href="/diffs/tree/main" tabindex="-1">492+<a role="presentation" data-href="/diffs/tree/main">
491 <span class="lbl">main</span>493 <span class="lbl">main</span>
492 <span class="k">branch</span>494 <span class="k">branch</span>
493 </a>495 </a>
494 </li>496 </li>
495 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">497 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
496-<a href="/diffs/tree/side" tabindex="-1">498+<a role="presentation" data-href="/diffs/tree/side">
497 <span class="lbl">side</span>499 <span class="lbl">side</span>
498 <span class="k">branch</span>500 <span class="k">branch</span>
499 </a>501 </a>
500 </li>502 </li>
501 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">503 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
502-<a href="/diffs/tree/v1.0.0" tabindex="-1">504+<a role="presentation" data-href="/diffs/tree/v1.0.0">
503 <span class="lbl">v1.0.0</span>505 <span class="lbl">v1.0.0</span>
504 <span class="k">tag</span>506 <span class="k">tag</span>
505 </a>507 </a>
506 </li>508 </li>
507 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">509 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
508-<a href="#" data-fire="keys" tabindex="-1">510+<a role="presentation" data-fire="keys">
509 <span class="lbl">turn single-key shortcuts off</span>511 <span class="lbl">turn single-key shortcuts off</span>
510 <span class="k">action</span>512 <span class="k">action</span>
511 </a>513 </a>
M internal/app/testdata/web/commit-root.html +19 -17
@@ -572,18 +572,20 @@
572572 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
573573 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
574574 </footer>
575-<div class="hint" role="status" aria-live="polite">
576-<span class="hint-nav" :text="document.body.dataset.nav || ''">
575+<div class="hint">
576+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
577577 </span>
578+<span role="status" aria-live="polite">
578579 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
579580 </span>
580581 <span class="hint-flash" :text="document.body.dataset.flash || ''">
581582 </span>
583+</span>
582584 </div>
583585 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
584586 <div class="panel-head">
585587 <h2>Keyboard shortcuts</h2>
586-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
588+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
587589 <kbd>esc</kbd> close</button>
588590 </div>
589591 <div class="keys-pref">
@@ -717,7 +719,7 @@
717719 <div class="panel-head">
718720 <label for="refs-filter" class="sr">filter branches and tags</label>
719721 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
720-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
722+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
721723 <kbd>esc</kbd>
722724 </button>
723725 </div>
@@ -752,79 +754,79 @@
752754 <div class="panel-head">
753755 <label for="cmd-q" class="sr">go to</label>
754756 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
755-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
757+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
756758 <kbd>esc</kbd>
757759 </button>
758760 </div>
759761 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
760762 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
761-<a href="/" tabindex="-1">
763+<a role="presentation" data-href="/">
762764 <span class="lbl">home</span>
763765 <span class="k">go</span>
764766 </a>
765767 </li>
766768 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
767-<a href="/diffs" tabindex="-1">
769+<a role="presentation" data-href="/diffs">
768770 <span class="lbl">summary</span>
769771 <span class="k">section</span>
770772 </a>
771773 </li>
772774 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
773-<a href="/diffs/tree/main" tabindex="-1">
775+<a role="presentation" data-href="/diffs/tree/main">
774776 <span class="lbl">files</span>
775777 <span class="k">section</span>
776778 </a>
777779 </li>
778780 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
779-<a href="/diffs/commits/main" tabindex="-1">
781+<a role="presentation" data-href="/diffs/commits/main">
780782 <span class="lbl">commits</span>
781783 <span class="k">section</span>
782784 </a>
783785 </li>
784786 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
785-<a href="/diffs/refs" tabindex="-1">
787+<a role="presentation" data-href="/diffs/refs">
786788 <span class="lbl">branches &amp; tags</span>
787789 <span class="k">section</span>
788790 </a>
789791 </li>
790792 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
791-<a href="/diffs/merge-requests" tabindex="-1">
793+<a role="presentation" data-href="/diffs/merge-requests">
792794 <span class="lbl">merge requests</span>
793795 <span class="k">section</span>
794796 </a>
795797 </li>
796798 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
797-<a href="/diffs/releases" tabindex="-1">
799+<a role="presentation" data-href="/diffs/releases">
798800 <span class="lbl">releases</span>
799801 <span class="k">section</span>
800802 </a>
801803 </li>
802804 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
803-<a href="/diffs/actions" tabindex="-1">
805+<a role="presentation" data-href="/diffs/actions">
804806 <span class="lbl">actions</span>
805807 <span class="k">section</span>
806808 </a>
807809 </li>
808810 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
809-<a href="/diffs/tree/main" tabindex="-1">
811+<a role="presentation" data-href="/diffs/tree/main">
810812 <span class="lbl">main</span>
811813 <span class="k">branch</span>
812814 </a>
813815 </li>
814816 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
815-<a href="/diffs/tree/side" tabindex="-1">
817+<a role="presentation" data-href="/diffs/tree/side">
816818 <span class="lbl">side</span>
817819 <span class="k">branch</span>
818820 </a>
819821 </li>
820822 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
821-<a href="/diffs/tree/v1.0.0" tabindex="-1">
823+<a role="presentation" data-href="/diffs/tree/v1.0.0">
822824 <span class="lbl">v1.0.0</span>
823825 <span class="k">tag</span>
824826 </a>
825827 </li>
826828 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
827-<a href="#" data-fire="keys" tabindex="-1">
829+<a role="presentation" data-fire="keys">
828830 <span class="lbl">turn single-key shortcuts off</span>
829831 <span class="k">action</span>
830832 </a>
@@ -572,18 +572,20 @@
572 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">572 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
573 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>573 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
574 </footer>574 </footer>
575-<div class="hint" role="status" aria-live="polite">575+<div class="hint">
576-<span class="hint-nav" :text="document.body.dataset.nav || ''">576+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
577 </span>577 </span>
578+<span role="status" aria-live="polite">
578 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">579 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
579 </span>580 </span>
580 <span class="hint-flash" :text="document.body.dataset.flash || ''">581 <span class="hint-flash" :text="document.body.dataset.flash || ''">
581 </span>582 </span>
583+</span>
582 </div>584 </div>
583 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">585 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
584 <div class="panel-head">586 <div class="panel-head">
585 <h2>Keyboard shortcuts</h2>587 <h2>Keyboard shortcuts</h2>
586-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">588+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
587 <kbd>esc</kbd> close</button>589 <kbd>esc</kbd> close</button>
588 </div>590 </div>
589 <div class="keys-pref">591 <div class="keys-pref">
@@ -717,7 +719,7 @@
717 <div class="panel-head">719 <div class="panel-head">
718 <label for="refs-filter" class="sr">filter branches and tags</label>720 <label for="refs-filter" class="sr">filter branches and tags</label>
719 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">721 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
720-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">722+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
721 <kbd>esc</kbd>723 <kbd>esc</kbd>
722 </button>724 </button>
723 </div>725 </div>
@@ -752,79 +754,79 @@
752 <div class="panel-head">754 <div class="panel-head">
753 <label for="cmd-q" class="sr">go to</label>755 <label for="cmd-q" class="sr">go to</label>
754 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">756 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
755-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">757+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
756 <kbd>esc</kbd>758 <kbd>esc</kbd>
757 </button>759 </button>
758 </div>760 </div>
759 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">761 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
760 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>762 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
761-<a href="/" tabindex="-1">763+<a role="presentation" data-href="/">
762 <span class="lbl">home</span>764 <span class="lbl">home</span>
763 <span class="k">go</span>765 <span class="k">go</span>
764 </a>766 </a>
765 </li>767 </li>
766 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">768 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
767-<a href="/diffs" tabindex="-1">769+<a role="presentation" data-href="/diffs">
768 <span class="lbl">summary</span>770 <span class="lbl">summary</span>
769 <span class="k">section</span>771 <span class="k">section</span>
770 </a>772 </a>
771 </li>773 </li>
772 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">774 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
773-<a href="/diffs/tree/main" tabindex="-1">775+<a role="presentation" data-href="/diffs/tree/main">
774 <span class="lbl">files</span>776 <span class="lbl">files</span>
775 <span class="k">section</span>777 <span class="k">section</span>
776 </a>778 </a>
777 </li>779 </li>
778 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">780 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
779-<a href="/diffs/commits/main" tabindex="-1">781+<a role="presentation" data-href="/diffs/commits/main">
780 <span class="lbl">commits</span>782 <span class="lbl">commits</span>
781 <span class="k">section</span>783 <span class="k">section</span>
782 </a>784 </a>
783 </li>785 </li>
784 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">786 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
785-<a href="/diffs/refs" tabindex="-1">787+<a role="presentation" data-href="/diffs/refs">
786 <span class="lbl">branches &amp; tags</span>788 <span class="lbl">branches &amp; tags</span>
787 <span class="k">section</span>789 <span class="k">section</span>
788 </a>790 </a>
789 </li>791 </li>
790 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">792 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
791-<a href="/diffs/merge-requests" tabindex="-1">793+<a role="presentation" data-href="/diffs/merge-requests">
792 <span class="lbl">merge requests</span>794 <span class="lbl">merge requests</span>
793 <span class="k">section</span>795 <span class="k">section</span>
794 </a>796 </a>
795 </li>797 </li>
796 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">798 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
797-<a href="/diffs/releases" tabindex="-1">799+<a role="presentation" data-href="/diffs/releases">
798 <span class="lbl">releases</span>800 <span class="lbl">releases</span>
799 <span class="k">section</span>801 <span class="k">section</span>
800 </a>802 </a>
801 </li>803 </li>
802 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">804 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
803-<a href="/diffs/actions" tabindex="-1">805+<a role="presentation" data-href="/diffs/actions">
804 <span class="lbl">actions</span>806 <span class="lbl">actions</span>
805 <span class="k">section</span>807 <span class="k">section</span>
806 </a>808 </a>
807 </li>809 </li>
808 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">810 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
809-<a href="/diffs/tree/main" tabindex="-1">811+<a role="presentation" data-href="/diffs/tree/main">
810 <span class="lbl">main</span>812 <span class="lbl">main</span>
811 <span class="k">branch</span>813 <span class="k">branch</span>
812 </a>814 </a>
813 </li>815 </li>
814 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">816 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
815-<a href="/diffs/tree/side" tabindex="-1">817+<a role="presentation" data-href="/diffs/tree/side">
816 <span class="lbl">side</span>818 <span class="lbl">side</span>
817 <span class="k">branch</span>819 <span class="k">branch</span>
818 </a>820 </a>
819 </li>821 </li>
820 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">822 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
821-<a href="/diffs/tree/v1.0.0" tabindex="-1">823+<a role="presentation" data-href="/diffs/tree/v1.0.0">
822 <span class="lbl">v1.0.0</span>824 <span class="lbl">v1.0.0</span>
823 <span class="k">tag</span>825 <span class="k">tag</span>
824 </a>826 </a>
825 </li>827 </li>
826 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">828 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
827-<a href="#" data-fire="keys" tabindex="-1">829+<a role="presentation" data-fire="keys">
828 <span class="lbl">turn single-key shortcuts off</span>830 <span class="lbl">turn single-key shortcuts off</span>
829 <span class="k">action</span>831 <span class="k">action</span>
830 </a>832 </a>
M internal/app/testdata/web/commit-trojan.html +19 -17
@@ -401,18 +401,20 @@
401401 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
402402 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
403403 </footer>
404-<div class="hint" role="status" aria-live="polite">
405-<span class="hint-nav" :text="document.body.dataset.nav || ''">
404+<div class="hint">
405+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
406406 </span>
407+<span role="status" aria-live="polite">
407408 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
408409 </span>
409410 <span class="hint-flash" :text="document.body.dataset.flash || ''">
410411 </span>
412+</span>
411413 </div>
412414 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
413415 <div class="panel-head">
414416 <h2>Keyboard shortcuts</h2>
415-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
417+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
416418 <kbd>esc</kbd> close</button>
417419 </div>
418420 <div class="keys-pref">
@@ -546,7 +548,7 @@
546548 <div class="panel-head">
547549 <label for="refs-filter" class="sr">filter branches and tags</label>
548550 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
549-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
551+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
550552 <kbd>esc</kbd>
551553 </button>
552554 </div>
@@ -581,79 +583,79 @@
581583 <div class="panel-head">
582584 <label for="cmd-q" class="sr">go to</label>
583585 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
584-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
586+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
585587 <kbd>esc</kbd>
586588 </button>
587589 </div>
588590 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
589591 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
590-<a href="/" tabindex="-1">
592+<a role="presentation" data-href="/">
591593 <span class="lbl">home</span>
592594 <span class="k">go</span>
593595 </a>
594596 </li>
595597 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
596-<a href="/diffs" tabindex="-1">
598+<a role="presentation" data-href="/diffs">
597599 <span class="lbl">summary</span>
598600 <span class="k">section</span>
599601 </a>
600602 </li>
601603 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
602-<a href="/diffs/tree/main" tabindex="-1">
604+<a role="presentation" data-href="/diffs/tree/main">
603605 <span class="lbl">files</span>
604606 <span class="k">section</span>
605607 </a>
606608 </li>
607609 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
608-<a href="/diffs/commits/main" tabindex="-1">
610+<a role="presentation" data-href="/diffs/commits/main">
609611 <span class="lbl">commits</span>
610612 <span class="k">section</span>
611613 </a>
612614 </li>
613615 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
614-<a href="/diffs/refs" tabindex="-1">
616+<a role="presentation" data-href="/diffs/refs">
615617 <span class="lbl">branches &amp; tags</span>
616618 <span class="k">section</span>
617619 </a>
618620 </li>
619621 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
620-<a href="/diffs/merge-requests" tabindex="-1">
622+<a role="presentation" data-href="/diffs/merge-requests">
621623 <span class="lbl">merge requests</span>
622624 <span class="k">section</span>
623625 </a>
624626 </li>
625627 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
626-<a href="/diffs/releases" tabindex="-1">
628+<a role="presentation" data-href="/diffs/releases">
627629 <span class="lbl">releases</span>
628630 <span class="k">section</span>
629631 </a>
630632 </li>
631633 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
632-<a href="/diffs/actions" tabindex="-1">
634+<a role="presentation" data-href="/diffs/actions">
633635 <span class="lbl">actions</span>
634636 <span class="k">section</span>
635637 </a>
636638 </li>
637639 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
638-<a href="/diffs/tree/main" tabindex="-1">
640+<a role="presentation" data-href="/diffs/tree/main">
639641 <span class="lbl">main</span>
640642 <span class="k">branch</span>
641643 </a>
642644 </li>
643645 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
644-<a href="/diffs/tree/side" tabindex="-1">
646+<a role="presentation" data-href="/diffs/tree/side">
645647 <span class="lbl">side</span>
646648 <span class="k">branch</span>
647649 </a>
648650 </li>
649651 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
650-<a href="/diffs/tree/v1.0.0" tabindex="-1">
652+<a role="presentation" data-href="/diffs/tree/v1.0.0">
651653 <span class="lbl">v1.0.0</span>
652654 <span class="k">tag</span>
653655 </a>
654656 </li>
655657 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
656-<a href="#" data-fire="keys" tabindex="-1">
658+<a role="presentation" data-fire="keys">
657659 <span class="lbl">turn single-key shortcuts off</span>
658660 <span class="k">action</span>
659661 </a>
@@ -401,18 +401,20 @@
401 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">401 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
402 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>402 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
403 </footer>403 </footer>
404-<div class="hint" role="status" aria-live="polite">404+<div class="hint">
405-<span class="hint-nav" :text="document.body.dataset.nav || ''">405+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
406 </span>406 </span>
407+<span role="status" aria-live="polite">
407 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">408 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
408 </span>409 </span>
409 <span class="hint-flash" :text="document.body.dataset.flash || ''">410 <span class="hint-flash" :text="document.body.dataset.flash || ''">
410 </span>411 </span>
412+</span>
411 </div>413 </div>
412 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">414 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
413 <div class="panel-head">415 <div class="panel-head">
414 <h2>Keyboard shortcuts</h2>416 <h2>Keyboard shortcuts</h2>
415-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">417+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
416 <kbd>esc</kbd> close</button>418 <kbd>esc</kbd> close</button>
417 </div>419 </div>
418 <div class="keys-pref">420 <div class="keys-pref">
@@ -546,7 +548,7 @@
546 <div class="panel-head">548 <div class="panel-head">
547 <label for="refs-filter" class="sr">filter branches and tags</label>549 <label for="refs-filter" class="sr">filter branches and tags</label>
548 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">550 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
549-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">551+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
550 <kbd>esc</kbd>552 <kbd>esc</kbd>
551 </button>553 </button>
552 </div>554 </div>
@@ -581,79 +583,79 @@
581 <div class="panel-head">583 <div class="panel-head">
582 <label for="cmd-q" class="sr">go to</label>584 <label for="cmd-q" class="sr">go to</label>
583 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">585 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
584-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">586+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
585 <kbd>esc</kbd>587 <kbd>esc</kbd>
586 </button>588 </button>
587 </div>589 </div>
588 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">590 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
589 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>591 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
590-<a href="/" tabindex="-1">592+<a role="presentation" data-href="/">
591 <span class="lbl">home</span>593 <span class="lbl">home</span>
592 <span class="k">go</span>594 <span class="k">go</span>
593 </a>595 </a>
594 </li>596 </li>
595 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">597 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
596-<a href="/diffs" tabindex="-1">598+<a role="presentation" data-href="/diffs">
597 <span class="lbl">summary</span>599 <span class="lbl">summary</span>
598 <span class="k">section</span>600 <span class="k">section</span>
599 </a>601 </a>
600 </li>602 </li>
601 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">603 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
602-<a href="/diffs/tree/main" tabindex="-1">604+<a role="presentation" data-href="/diffs/tree/main">
603 <span class="lbl">files</span>605 <span class="lbl">files</span>
604 <span class="k">section</span>606 <span class="k">section</span>
605 </a>607 </a>
606 </li>608 </li>
607 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">609 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
608-<a href="/diffs/commits/main" tabindex="-1">610+<a role="presentation" data-href="/diffs/commits/main">
609 <span class="lbl">commits</span>611 <span class="lbl">commits</span>
610 <span class="k">section</span>612 <span class="k">section</span>
611 </a>613 </a>
612 </li>614 </li>
613 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">615 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
614-<a href="/diffs/refs" tabindex="-1">616+<a role="presentation" data-href="/diffs/refs">
615 <span class="lbl">branches &amp; tags</span>617 <span class="lbl">branches &amp; tags</span>
616 <span class="k">section</span>618 <span class="k">section</span>
617 </a>619 </a>
618 </li>620 </li>
619 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">621 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
620-<a href="/diffs/merge-requests" tabindex="-1">622+<a role="presentation" data-href="/diffs/merge-requests">
621 <span class="lbl">merge requests</span>623 <span class="lbl">merge requests</span>
622 <span class="k">section</span>624 <span class="k">section</span>
623 </a>625 </a>
624 </li>626 </li>
625 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">627 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
626-<a href="/diffs/releases" tabindex="-1">628+<a role="presentation" data-href="/diffs/releases">
627 <span class="lbl">releases</span>629 <span class="lbl">releases</span>
628 <span class="k">section</span>630 <span class="k">section</span>
629 </a>631 </a>
630 </li>632 </li>
631 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">633 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
632-<a href="/diffs/actions" tabindex="-1">634+<a role="presentation" data-href="/diffs/actions">
633 <span class="lbl">actions</span>635 <span class="lbl">actions</span>
634 <span class="k">section</span>636 <span class="k">section</span>
635 </a>637 </a>
636 </li>638 </li>
637 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">639 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
638-<a href="/diffs/tree/main" tabindex="-1">640+<a role="presentation" data-href="/diffs/tree/main">
639 <span class="lbl">main</span>641 <span class="lbl">main</span>
640 <span class="k">branch</span>642 <span class="k">branch</span>
641 </a>643 </a>
642 </li>644 </li>
643 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">645 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
644-<a href="/diffs/tree/side" tabindex="-1">646+<a role="presentation" data-href="/diffs/tree/side">
645 <span class="lbl">side</span>647 <span class="lbl">side</span>
646 <span class="k">branch</span>648 <span class="k">branch</span>
647 </a>649 </a>
648 </li>650 </li>
649 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">651 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
650-<a href="/diffs/tree/v1.0.0" tabindex="-1">652+<a role="presentation" data-href="/diffs/tree/v1.0.0">
651 <span class="lbl">v1.0.0</span>653 <span class="lbl">v1.0.0</span>
652 <span class="k">tag</span>654 <span class="k">tag</span>
653 </a>655 </a>
654 </li>656 </li>
655 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">657 <li id="cmd-o11" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
656-<a href="#" data-fire="keys" tabindex="-1">658+<a role="presentation" data-fire="keys">
657 <span class="lbl">turn single-key shortcuts off</span>659 <span class="lbl">turn single-key shortcuts off</span>
658 <span class="k">action</span>660 <span class="k">action</span>
659 </a>661 </a>
M internal/app/testdata/web/commits-page2.html +18 -16
@@ -168,18 +168,20 @@
168168 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
169169 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
170170 </footer>
171-<div class="hint" role="status" aria-live="polite">
172-<span class="hint-nav" :text="document.body.dataset.nav || ''">
171+<div class="hint">
172+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
173173 </span>
174+<span role="status" aria-live="polite">
174175 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
175176 </span>
176177 <span class="hint-flash" :text="document.body.dataset.flash || ''">
177178 </span>
179+</span>
178180 </div>
179181 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
180182 <div class="panel-head">
181183 <h2>Keyboard shortcuts</h2>
182-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
184+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
183185 <kbd>esc</kbd> close</button>
184186 </div>
185187 <div class="keys-pref">
@@ -313,7 +315,7 @@
313315 <div class="panel-head">
314316 <label for="refs-filter" class="sr">filter branches and tags</label>
315317 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
316-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
318+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
317319 <kbd>esc</kbd>
318320 </button>
319321 </div>
@@ -340,73 +342,73 @@
340342 <div class="panel-head">
341343 <label for="cmd-q" class="sr">go to</label>
342344 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
343-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
345+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
344346 <kbd>esc</kbd>
345347 </button>
346348 </div>
347349 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
348350 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
349-<a href="/" tabindex="-1">
351+<a role="presentation" data-href="/">
350352 <span class="lbl">home</span>
351353 <span class="k">go</span>
352354 </a>
353355 </li>
354356 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
355-<a href="/long" tabindex="-1">
357+<a role="presentation" data-href="/long">
356358 <span class="lbl">summary</span>
357359 <span class="k">section</span>
358360 </a>
359361 </li>
360362 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
361-<a href="/long/tree/main" tabindex="-1">
363+<a role="presentation" data-href="/long/tree/main">
362364 <span class="lbl">files</span>
363365 <span class="k">section</span>
364366 </a>
365367 </li>
366368 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
367-<a href="/long/commits/main" tabindex="-1">
369+<a role="presentation" data-href="/long/commits/main">
368370 <span class="lbl">commits</span>
369371 <span class="k">section</span>
370372 </a>
371373 </li>
372374 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
373-<a href="/long/refs" tabindex="-1">
375+<a role="presentation" data-href="/long/refs">
374376 <span class="lbl">branches &amp; tags</span>
375377 <span class="k">section</span>
376378 </a>
377379 </li>
378380 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
379-<a href="/long/merge-requests" tabindex="-1">
381+<a role="presentation" data-href="/long/merge-requests">
380382 <span class="lbl">merge requests</span>
381383 <span class="k">section</span>
382384 </a>
383385 </li>
384386 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
385-<a href="/long/releases" tabindex="-1">
387+<a role="presentation" data-href="/long/releases">
386388 <span class="lbl">releases</span>
387389 <span class="k">section</span>
388390 </a>
389391 </li>
390392 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
391-<a href="/long/actions" tabindex="-1">
393+<a role="presentation" data-href="/long/actions">
392394 <span class="lbl">actions</span>
393395 <span class="k">section</span>
394396 </a>
395397 </li>
396398 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
397-<a href="/long/tree/main" tabindex="-1">
399+<a role="presentation" data-href="/long/tree/main">
398400 <span class="lbl">main</span>
399401 <span class="k">branch</span>
400402 </a>
401403 </li>
402404 <li id="cmd-o9" role="option" aria-selected="false" data-k="repo diffs">
403-<a href="/diffs" tabindex="-1">
405+<a role="presentation" data-href="/diffs">
404406 <span class="lbl">diffs</span>
405407 <span class="k">repo</span>
406408 </a>
407409 </li>
408410 <li id="cmd-o10" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
409-<a href="#" data-fire="keys" tabindex="-1">
411+<a role="presentation" data-fire="keys">
410412 <span class="lbl">turn single-key shortcuts off</span>
411413 <span class="k">action</span>
412414 </a>
@@ -168,18 +168,20 @@
168 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">168 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
169 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>169 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
170 </footer>170 </footer>
171-<div class="hint" role="status" aria-live="polite">171+<div class="hint">
172-<span class="hint-nav" :text="document.body.dataset.nav || ''">172+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
173 </span>173 </span>
174+<span role="status" aria-live="polite">
174 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">175 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
175 </span>176 </span>
176 <span class="hint-flash" :text="document.body.dataset.flash || ''">177 <span class="hint-flash" :text="document.body.dataset.flash || ''">
177 </span>178 </span>
179+</span>
178 </div>180 </div>
179 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">181 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
180 <div class="panel-head">182 <div class="panel-head">
181 <h2>Keyboard shortcuts</h2>183 <h2>Keyboard shortcuts</h2>
182-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">184+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
183 <kbd>esc</kbd> close</button>185 <kbd>esc</kbd> close</button>
184 </div>186 </div>
185 <div class="keys-pref">187 <div class="keys-pref">
@@ -313,7 +315,7 @@
313 <div class="panel-head">315 <div class="panel-head">
314 <label for="refs-filter" class="sr">filter branches and tags</label>316 <label for="refs-filter" class="sr">filter branches and tags</label>
315 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">317 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
316-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">318+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
317 <kbd>esc</kbd>319 <kbd>esc</kbd>
318 </button>320 </button>
319 </div>321 </div>
@@ -340,73 +342,73 @@
340 <div class="panel-head">342 <div class="panel-head">
341 <label for="cmd-q" class="sr">go to</label>343 <label for="cmd-q" class="sr">go to</label>
342 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">344 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
343-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">345+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
344 <kbd>esc</kbd>346 <kbd>esc</kbd>
345 </button>347 </button>
346 </div>348 </div>
347 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">349 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
348 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>350 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
349-<a href="/" tabindex="-1">351+<a role="presentation" data-href="/">
350 <span class="lbl">home</span>352 <span class="lbl">home</span>
351 <span class="k">go</span>353 <span class="k">go</span>
352 </a>354 </a>
353 </li>355 </li>
354 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">356 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
355-<a href="/long" tabindex="-1">357+<a role="presentation" data-href="/long">
356 <span class="lbl">summary</span>358 <span class="lbl">summary</span>
357 <span class="k">section</span>359 <span class="k">section</span>
358 </a>360 </a>
359 </li>361 </li>
360 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">362 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
361-<a href="/long/tree/main" tabindex="-1">363+<a role="presentation" data-href="/long/tree/main">
362 <span class="lbl">files</span>364 <span class="lbl">files</span>
363 <span class="k">section</span>365 <span class="k">section</span>
364 </a>366 </a>
365 </li>367 </li>
366 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">368 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
367-<a href="/long/commits/main" tabindex="-1">369+<a role="presentation" data-href="/long/commits/main">
368 <span class="lbl">commits</span>370 <span class="lbl">commits</span>
369 <span class="k">section</span>371 <span class="k">section</span>
370 </a>372 </a>
371 </li>373 </li>
372 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">374 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
373-<a href="/long/refs" tabindex="-1">375+<a role="presentation" data-href="/long/refs">
374 <span class="lbl">branches &amp; tags</span>376 <span class="lbl">branches &amp; tags</span>
375 <span class="k">section</span>377 <span class="k">section</span>
376 </a>378 </a>
377 </li>379 </li>
378 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">380 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
379-<a href="/long/merge-requests" tabindex="-1">381+<a role="presentation" data-href="/long/merge-requests">
380 <span class="lbl">merge requests</span>382 <span class="lbl">merge requests</span>
381 <span class="k">section</span>383 <span class="k">section</span>
382 </a>384 </a>
383 </li>385 </li>
384 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">386 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
385-<a href="/long/releases" tabindex="-1">387+<a role="presentation" data-href="/long/releases">
386 <span class="lbl">releases</span>388 <span class="lbl">releases</span>
387 <span class="k">section</span>389 <span class="k">section</span>
388 </a>390 </a>
389 </li>391 </li>
390 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">392 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
391-<a href="/long/actions" tabindex="-1">393+<a role="presentation" data-href="/long/actions">
392 <span class="lbl">actions</span>394 <span class="lbl">actions</span>
393 <span class="k">section</span>395 <span class="k">section</span>
394 </a>396 </a>
395 </li>397 </li>
396 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">398 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
397-<a href="/long/tree/main" tabindex="-1">399+<a role="presentation" data-href="/long/tree/main">
398 <span class="lbl">main</span>400 <span class="lbl">main</span>
399 <span class="k">branch</span>401 <span class="k">branch</span>
400 </a>402 </a>
401 </li>403 </li>
402 <li id="cmd-o9" role="option" aria-selected="false" data-k="repo diffs">404 <li id="cmd-o9" role="option" aria-selected="false" data-k="repo diffs">
403-<a href="/diffs" tabindex="-1">405+<a role="presentation" data-href="/diffs">
404 <span class="lbl">diffs</span>406 <span class="lbl">diffs</span>
405 <span class="k">repo</span>407 <span class="k">repo</span>
406 </a>408 </a>
407 </li>409 </li>
408 <li id="cmd-o10" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">410 <li id="cmd-o10" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
409-<a href="#" data-fire="keys" tabindex="-1">411+<a role="presentation" data-fire="keys">
410 <span class="lbl">turn single-key shortcuts off</span>412 <span class="lbl">turn single-key shortcuts off</span>
411 <span class="k">action</span>413 <span class="k">action</span>
412 </a>414 </a>
M internal/app/testdata/web/commits-path.html +18 -16
@@ -183,18 +183,20 @@
183183 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
184184 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
185185 </footer>
186-<div class="hint" role="status" aria-live="polite">
187-<span class="hint-nav" :text="document.body.dataset.nav || ''">
186+<div class="hint">
187+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
188188 </span>
189+<span role="status" aria-live="polite">
189190 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
190191 </span>
191192 <span class="hint-flash" :text="document.body.dataset.flash || ''">
192193 </span>
194+</span>
193195 </div>
194196 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
195197 <div class="panel-head">
196198 <h2>Keyboard shortcuts</h2>
197-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
199+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
198200 <kbd>esc</kbd> close</button>
199201 </div>
200202 <div class="keys-pref">
@@ -328,7 +330,7 @@
328330 <div class="panel-head">
329331 <label for="refs-filter" class="sr">filter branches and tags</label>
330332 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
331-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
333+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
332334 <kbd>esc</kbd>
333335 </button>
334336 </div>
@@ -355,73 +357,73 @@
355357 <div class="panel-head">
356358 <label for="cmd-q" class="sr">go to</label>
357359 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
358-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
360+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
359361 <kbd>esc</kbd>
360362 </button>
361363 </div>
362364 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
363365 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
364-<a href="/" tabindex="-1">
366+<a role="presentation" data-href="/">
365367 <span class="lbl">home</span>
366368 <span class="k">go</span>
367369 </a>
368370 </li>
369371 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
370-<a href="/long" tabindex="-1">
372+<a role="presentation" data-href="/long">
371373 <span class="lbl">summary</span>
372374 <span class="k">section</span>
373375 </a>
374376 </li>
375377 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
376-<a href="/long/tree/main" tabindex="-1">
378+<a role="presentation" data-href="/long/tree/main">
377379 <span class="lbl">files</span>
378380 <span class="k">section</span>
379381 </a>
380382 </li>
381383 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
382-<a href="/long/commits/main" tabindex="-1">
384+<a role="presentation" data-href="/long/commits/main">
383385 <span class="lbl">commits</span>
384386 <span class="k">section</span>
385387 </a>
386388 </li>
387389 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
388-<a href="/long/refs" tabindex="-1">
390+<a role="presentation" data-href="/long/refs">
389391 <span class="lbl">branches &amp; tags</span>
390392 <span class="k">section</span>
391393 </a>
392394 </li>
393395 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
394-<a href="/long/merge-requests" tabindex="-1">
396+<a role="presentation" data-href="/long/merge-requests">
395397 <span class="lbl">merge requests</span>
396398 <span class="k">section</span>
397399 </a>
398400 </li>
399401 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
400-<a href="/long/releases" tabindex="-1">
402+<a role="presentation" data-href="/long/releases">
401403 <span class="lbl">releases</span>
402404 <span class="k">section</span>
403405 </a>
404406 </li>
405407 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
406-<a href="/long/actions" tabindex="-1">
408+<a role="presentation" data-href="/long/actions">
407409 <span class="lbl">actions</span>
408410 <span class="k">section</span>
409411 </a>
410412 </li>
411413 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
412-<a href="/long/tree/main" tabindex="-1">
414+<a role="presentation" data-href="/long/tree/main">
413415 <span class="lbl">main</span>
414416 <span class="k">branch</span>
415417 </a>
416418 </li>
417419 <li id="cmd-o9" role="option" aria-selected="false" data-k="repo diffs">
418-<a href="/diffs" tabindex="-1">
420+<a role="presentation" data-href="/diffs">
419421 <span class="lbl">diffs</span>
420422 <span class="k">repo</span>
421423 </a>
422424 </li>
423425 <li id="cmd-o10" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
424-<a href="#" data-fire="keys" tabindex="-1">
426+<a role="presentation" data-fire="keys">
425427 <span class="lbl">turn single-key shortcuts off</span>
426428 <span class="k">action</span>
427429 </a>
@@ -183,18 +183,20 @@
183 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">183 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
184 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>184 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
185 </footer>185 </footer>
186-<div class="hint" role="status" aria-live="polite">186+<div class="hint">
187-<span class="hint-nav" :text="document.body.dataset.nav || ''">187+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
188 </span>188 </span>
189+<span role="status" aria-live="polite">
189 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">190 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
190 </span>191 </span>
191 <span class="hint-flash" :text="document.body.dataset.flash || ''">192 <span class="hint-flash" :text="document.body.dataset.flash || ''">
192 </span>193 </span>
194+</span>
193 </div>195 </div>
194 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">196 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
195 <div class="panel-head">197 <div class="panel-head">
196 <h2>Keyboard shortcuts</h2>198 <h2>Keyboard shortcuts</h2>
197-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">199+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
198 <kbd>esc</kbd> close</button>200 <kbd>esc</kbd> close</button>
199 </div>201 </div>
200 <div class="keys-pref">202 <div class="keys-pref">
@@ -328,7 +330,7 @@
328 <div class="panel-head">330 <div class="panel-head">
329 <label for="refs-filter" class="sr">filter branches and tags</label>331 <label for="refs-filter" class="sr">filter branches and tags</label>
330 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">332 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
331-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">333+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
332 <kbd>esc</kbd>334 <kbd>esc</kbd>
333 </button>335 </button>
334 </div>336 </div>
@@ -355,73 +357,73 @@
355 <div class="panel-head">357 <div class="panel-head">
356 <label for="cmd-q" class="sr">go to</label>358 <label for="cmd-q" class="sr">go to</label>
357 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">359 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
358-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">360+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
359 <kbd>esc</kbd>361 <kbd>esc</kbd>
360 </button>362 </button>
361 </div>363 </div>
362 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">364 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
363 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>365 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
364-<a href="/" tabindex="-1">366+<a role="presentation" data-href="/">
365 <span class="lbl">home</span>367 <span class="lbl">home</span>
366 <span class="k">go</span>368 <span class="k">go</span>
367 </a>369 </a>
368 </li>370 </li>
369 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">371 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
370-<a href="/long" tabindex="-1">372+<a role="presentation" data-href="/long">
371 <span class="lbl">summary</span>373 <span class="lbl">summary</span>
372 <span class="k">section</span>374 <span class="k">section</span>
373 </a>375 </a>
374 </li>376 </li>
375 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">377 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
376-<a href="/long/tree/main" tabindex="-1">378+<a role="presentation" data-href="/long/tree/main">
377 <span class="lbl">files</span>379 <span class="lbl">files</span>
378 <span class="k">section</span>380 <span class="k">section</span>
379 </a>381 </a>
380 </li>382 </li>
381 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">383 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
382-<a href="/long/commits/main" tabindex="-1">384+<a role="presentation" data-href="/long/commits/main">
383 <span class="lbl">commits</span>385 <span class="lbl">commits</span>
384 <span class="k">section</span>386 <span class="k">section</span>
385 </a>387 </a>
386 </li>388 </li>
387 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">389 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
388-<a href="/long/refs" tabindex="-1">390+<a role="presentation" data-href="/long/refs">
389 <span class="lbl">branches &amp; tags</span>391 <span class="lbl">branches &amp; tags</span>
390 <span class="k">section</span>392 <span class="k">section</span>
391 </a>393 </a>
392 </li>394 </li>
393 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">395 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
394-<a href="/long/merge-requests" tabindex="-1">396+<a role="presentation" data-href="/long/merge-requests">
395 <span class="lbl">merge requests</span>397 <span class="lbl">merge requests</span>
396 <span class="k">section</span>398 <span class="k">section</span>
397 </a>399 </a>
398 </li>400 </li>
399 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">401 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
400-<a href="/long/releases" tabindex="-1">402+<a role="presentation" data-href="/long/releases">
401 <span class="lbl">releases</span>403 <span class="lbl">releases</span>
402 <span class="k">section</span>404 <span class="k">section</span>
403 </a>405 </a>
404 </li>406 </li>
405 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">407 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
406-<a href="/long/actions" tabindex="-1">408+<a role="presentation" data-href="/long/actions">
407 <span class="lbl">actions</span>409 <span class="lbl">actions</span>
408 <span class="k">section</span>410 <span class="k">section</span>
409 </a>411 </a>
410 </li>412 </li>
411 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">413 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
412-<a href="/long/tree/main" tabindex="-1">414+<a role="presentation" data-href="/long/tree/main">
413 <span class="lbl">main</span>415 <span class="lbl">main</span>
414 <span class="k">branch</span>416 <span class="k">branch</span>
415 </a>417 </a>
416 </li>418 </li>
417 <li id="cmd-o9" role="option" aria-selected="false" data-k="repo diffs">419 <li id="cmd-o9" role="option" aria-selected="false" data-k="repo diffs">
418-<a href="/diffs" tabindex="-1">420+<a role="presentation" data-href="/diffs">
419 <span class="lbl">diffs</span>421 <span class="lbl">diffs</span>
420 <span class="k">repo</span>422 <span class="k">repo</span>
421 </a>423 </a>
422 </li>424 </li>
423 <li id="cmd-o10" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">425 <li id="cmd-o10" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
424-<a href="#" data-fire="keys" tabindex="-1">426+<a role="presentation" data-fire="keys">
425 <span class="lbl">turn single-key shortcuts off</span>427 <span class="lbl">turn single-key shortcuts off</span>
426 <span class="k">action</span>428 <span class="k">action</span>
427 </a>429 </a>
M internal/app/testdata/web/commits-root.html +19 -17
@@ -965,14 +965,16 @@
965965 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
966966 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
967967 </footer>
968-<div class="hint" role="status" aria-live="polite">
969-<span class="hint-nav" :text="document.body.dataset.nav || ''">
968+<div class="hint">
969+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
970970 </span>
971+<span role="status" aria-live="polite">
971972 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
972973 </span>
973974 <span class="hint-flash" :text="document.body.dataset.flash || ''">
974975 </span>
975-<span class="hint-live" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Along&amp;view=commits&amp;ref=main&amp;head=SHA40" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
976+</span>
977+<span class="hint-live" role="status" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Along&amp;view=commits&amp;ref=main&amp;head=SHA40" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
976978 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();
977979 htmx:sse:error -> ermiteLive.error(event.detail.status);
978980 htmx:sse:before:connection -> ermiteLive.gate(event);
@@ -984,7 +986,7 @@
984986 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
985987 <div class="panel-head">
986988 <h2>Keyboard shortcuts</h2>
987-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
989+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
988990 <kbd>esc</kbd> close</button>
989991 </div>
990992 <div class="keys-pref">
@@ -1118,7 +1120,7 @@
11181120 <div class="panel-head">
11191121 <label for="refs-filter" class="sr">filter branches and tags</label>
11201122 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
1121-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
1123+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
11221124 <kbd>esc</kbd>
11231125 </button>
11241126 </div>
@@ -1145,73 +1147,73 @@
11451147 <div class="panel-head">
11461148 <label for="cmd-q" class="sr">go to</label>
11471149 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
1148-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
1150+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
11491151 <kbd>esc</kbd>
11501152 </button>
11511153 </div>
11521154 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
11531155 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
1154-<a href="/" tabindex="-1">
1156+<a role="presentation" data-href="/">
11551157 <span class="lbl">home</span>
11561158 <span class="k">go</span>
11571159 </a>
11581160 </li>
11591161 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
1160-<a href="/long" tabindex="-1">
1162+<a role="presentation" data-href="/long">
11611163 <span class="lbl">summary</span>
11621164 <span class="k">section</span>
11631165 </a>
11641166 </li>
11651167 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
1166-<a href="/long/tree/main" tabindex="-1">
1168+<a role="presentation" data-href="/long/tree/main">
11671169 <span class="lbl">files</span>
11681170 <span class="k">section</span>
11691171 </a>
11701172 </li>
11711173 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
1172-<a href="/long/commits/main" tabindex="-1">
1174+<a role="presentation" data-href="/long/commits/main">
11731175 <span class="lbl">commits</span>
11741176 <span class="k">section</span>
11751177 </a>
11761178 </li>
11771179 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
1178-<a href="/long/refs" tabindex="-1">
1180+<a role="presentation" data-href="/long/refs">
11791181 <span class="lbl">branches &amp; tags</span>
11801182 <span class="k">section</span>
11811183 </a>
11821184 </li>
11831185 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
1184-<a href="/long/merge-requests" tabindex="-1">
1186+<a role="presentation" data-href="/long/merge-requests">
11851187 <span class="lbl">merge requests</span>
11861188 <span class="k">section</span>
11871189 </a>
11881190 </li>
11891191 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
1190-<a href="/long/releases" tabindex="-1">
1192+<a role="presentation" data-href="/long/releases">
11911193 <span class="lbl">releases</span>
11921194 <span class="k">section</span>
11931195 </a>
11941196 </li>
11951197 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
1196-<a href="/long/actions" tabindex="-1">
1198+<a role="presentation" data-href="/long/actions">
11971199 <span class="lbl">actions</span>
11981200 <span class="k">section</span>
11991201 </a>
12001202 </li>
12011203 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
1202-<a href="/long/tree/main" tabindex="-1">
1204+<a role="presentation" data-href="/long/tree/main">
12031205 <span class="lbl">main</span>
12041206 <span class="k">branch</span>
12051207 </a>
12061208 </li>
12071209 <li id="cmd-o9" role="option" aria-selected="false" data-k="repo diffs">
1208-<a href="/diffs" tabindex="-1">
1210+<a role="presentation" data-href="/diffs">
12091211 <span class="lbl">diffs</span>
12101212 <span class="k">repo</span>
12111213 </a>
12121214 </li>
12131215 <li id="cmd-o10" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
1214-<a href="#" data-fire="keys" tabindex="-1">
1216+<a role="presentation" data-fire="keys">
12151217 <span class="lbl">turn single-key shortcuts off</span>
12161218 <span class="k">action</span>
12171219 </a>
@@ -965,14 +965,16 @@
965 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">965 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
966 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>966 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
967 </footer>967 </footer>
968-<div class="hint" role="status" aria-live="polite">968+<div class="hint">
969-<span class="hint-nav" :text="document.body.dataset.nav || ''">969+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
970 </span>970 </span>
971+<span role="status" aria-live="polite">
971 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">972 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
972 </span>973 </span>
973 <span class="hint-flash" :text="document.body.dataset.flash || ''">974 <span class="hint-flash" :text="document.body.dataset.flash || ''">
974 </span>975 </span>
975-<span class="hint-live" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Along&amp;view=commits&amp;ref=main&amp;head=SHA40" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();976+</span>
977+<span class="hint-live" role="status" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Along&amp;view=commits&amp;ref=main&amp;head=SHA40" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
976 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();978 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();
977 htmx:sse:error -> ermiteLive.error(event.detail.status);979 htmx:sse:error -> ermiteLive.error(event.detail.status);
978 htmx:sse:before:connection -> ermiteLive.gate(event);980 htmx:sse:before:connection -> ermiteLive.gate(event);
@@ -984,7 +986,7 @@
984 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">986 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
985 <div class="panel-head">987 <div class="panel-head">
986 <h2>Keyboard shortcuts</h2>988 <h2>Keyboard shortcuts</h2>
987-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">989+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
988 <kbd>esc</kbd> close</button>990 <kbd>esc</kbd> close</button>
989 </div>991 </div>
990 <div class="keys-pref">992 <div class="keys-pref">
@@ -1118,7 +1120,7 @@
1118 <div class="panel-head">1120 <div class="panel-head">
1119 <label for="refs-filter" class="sr">filter branches and tags</label>1121 <label for="refs-filter" class="sr">filter branches and tags</label>
1120 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">1122 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
1121-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">1123+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
1122 <kbd>esc</kbd>1124 <kbd>esc</kbd>
1123 </button>1125 </button>
1124 </div>1126 </div>
@@ -1145,73 +1147,73 @@
1145 <div class="panel-head">1147 <div class="panel-head">
1146 <label for="cmd-q" class="sr">go to</label>1148 <label for="cmd-q" class="sr">go to</label>
1147 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">1149 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
1148-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">1150+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
1149 <kbd>esc</kbd>1151 <kbd>esc</kbd>
1150 </button>1152 </button>
1151 </div>1153 </div>
1152 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">1154 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
1153 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>1155 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
1154-<a href="/" tabindex="-1">1156+<a role="presentation" data-href="/">
1155 <span class="lbl">home</span>1157 <span class="lbl">home</span>
1156 <span class="k">go</span>1158 <span class="k">go</span>
1157 </a>1159 </a>
1158 </li>1160 </li>
1159 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">1161 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
1160-<a href="/long" tabindex="-1">1162+<a role="presentation" data-href="/long">
1161 <span class="lbl">summary</span>1163 <span class="lbl">summary</span>
1162 <span class="k">section</span>1164 <span class="k">section</span>
1163 </a>1165 </a>
1164 </li>1166 </li>
1165 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">1167 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
1166-<a href="/long/tree/main" tabindex="-1">1168+<a role="presentation" data-href="/long/tree/main">
1167 <span class="lbl">files</span>1169 <span class="lbl">files</span>
1168 <span class="k">section</span>1170 <span class="k">section</span>
1169 </a>1171 </a>
1170 </li>1172 </li>
1171 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">1173 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
1172-<a href="/long/commits/main" tabindex="-1">1174+<a role="presentation" data-href="/long/commits/main">
1173 <span class="lbl">commits</span>1175 <span class="lbl">commits</span>
1174 <span class="k">section</span>1176 <span class="k">section</span>
1175 </a>1177 </a>
1176 </li>1178 </li>
1177 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">1179 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
1178-<a href="/long/refs" tabindex="-1">1180+<a role="presentation" data-href="/long/refs">
1179 <span class="lbl">branches &amp; tags</span>1181 <span class="lbl">branches &amp; tags</span>
1180 <span class="k">section</span>1182 <span class="k">section</span>
1181 </a>1183 </a>
1182 </li>1184 </li>
1183 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">1185 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
1184-<a href="/long/merge-requests" tabindex="-1">1186+<a role="presentation" data-href="/long/merge-requests">
1185 <span class="lbl">merge requests</span>1187 <span class="lbl">merge requests</span>
1186 <span class="k">section</span>1188 <span class="k">section</span>
1187 </a>1189 </a>
1188 </li>1190 </li>
1189 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">1191 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
1190-<a href="/long/releases" tabindex="-1">1192+<a role="presentation" data-href="/long/releases">
1191 <span class="lbl">releases</span>1193 <span class="lbl">releases</span>
1192 <span class="k">section</span>1194 <span class="k">section</span>
1193 </a>1195 </a>
1194 </li>1196 </li>
1195 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">1197 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
1196-<a href="/long/actions" tabindex="-1">1198+<a role="presentation" data-href="/long/actions">
1197 <span class="lbl">actions</span>1199 <span class="lbl">actions</span>
1198 <span class="k">section</span>1200 <span class="k">section</span>
1199 </a>1201 </a>
1200 </li>1202 </li>
1201 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">1203 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
1202-<a href="/long/tree/main" tabindex="-1">1204+<a role="presentation" data-href="/long/tree/main">
1203 <span class="lbl">main</span>1205 <span class="lbl">main</span>
1204 <span class="k">branch</span>1206 <span class="k">branch</span>
1205 </a>1207 </a>
1206 </li>1208 </li>
1207 <li id="cmd-o9" role="option" aria-selected="false" data-k="repo diffs">1209 <li id="cmd-o9" role="option" aria-selected="false" data-k="repo diffs">
1208-<a href="/diffs" tabindex="-1">1210+<a role="presentation" data-href="/diffs">
1209 <span class="lbl">diffs</span>1211 <span class="lbl">diffs</span>
1210 <span class="k">repo</span>1212 <span class="k">repo</span>
1211 </a>1213 </a>
1212 </li>1214 </li>
1213 <li id="cmd-o10" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">1215 <li id="cmd-o10" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
1214-<a href="#" data-fire="keys" tabindex="-1">1216+<a role="presentation" data-fire="keys">
1215 <span class="lbl">turn single-key shortcuts off</span>1217 <span class="lbl">turn single-key shortcuts off</span>
1216 <span class="k">action</span>1218 <span class="k">action</span>
1217 </a>1219 </a>
M internal/app/testdata/web/commits-small.html +21 -19
@@ -310,14 +310,16 @@
310310 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
311311 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
312312 </footer>
313-<div class="hint" role="status" aria-live="polite">
314-<span class="hint-nav" :text="document.body.dataset.nav || ''">
313+<div class="hint">
314+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
315315 </span>
316+<span role="status" aria-live="polite">
316317 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
317318 </span>
318319 <span class="hint-flash" :text="document.body.dataset.flash || ''">
319320 </span>
320-<span class="hint-live" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Adiffs&amp;view=commits&amp;ref=main&amp;head=SHA40" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
321+</span>
322+<span class="hint-live" role="status" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Adiffs&amp;view=commits&amp;ref=main&amp;head=SHA40" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
321323 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();
322324 htmx:sse:error -> ermiteLive.error(event.detail.status);
323325 htmx:sse:before:connection -> ermiteLive.gate(event);
@@ -329,7 +331,7 @@
329331 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
330332 <div class="panel-head">
331333 <h2>Keyboard shortcuts</h2>
332-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
334+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
333335 <kbd>esc</kbd> close</button>
334336 </div>
335337 <div class="keys-pref">
@@ -463,7 +465,7 @@
463465 <div class="panel-head">
464466 <label for="refs-filter" class="sr">filter branches and tags</label>
465467 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
466-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
468+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
467469 <kbd>esc</kbd>
468470 </button>
469471 </div>
@@ -498,85 +500,85 @@
498500 <div class="panel-head">
499501 <label for="cmd-q" class="sr">go to</label>
500502 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
501-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
503+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
502504 <kbd>esc</kbd>
503505 </button>
504506 </div>
505507 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
506508 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
507-<a href="/" tabindex="-1">
509+<a role="presentation" data-href="/">
508510 <span class="lbl">home</span>
509511 <span class="k">go</span>
510512 </a>
511513 </li>
512514 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
513-<a href="/diffs" tabindex="-1">
515+<a role="presentation" data-href="/diffs">
514516 <span class="lbl">summary</span>
515517 <span class="k">section</span>
516518 </a>
517519 </li>
518520 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
519-<a href="/diffs/tree/main" tabindex="-1">
521+<a role="presentation" data-href="/diffs/tree/main">
520522 <span class="lbl">files</span>
521523 <span class="k">section</span>
522524 </a>
523525 </li>
524526 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
525-<a href="/diffs/commits/main" tabindex="-1">
527+<a role="presentation" data-href="/diffs/commits/main">
526528 <span class="lbl">commits</span>
527529 <span class="k">section</span>
528530 </a>
529531 </li>
530532 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
531-<a href="/diffs/refs" tabindex="-1">
533+<a role="presentation" data-href="/diffs/refs">
532534 <span class="lbl">branches &amp; tags</span>
533535 <span class="k">section</span>
534536 </a>
535537 </li>
536538 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
537-<a href="/diffs/merge-requests" tabindex="-1">
539+<a role="presentation" data-href="/diffs/merge-requests">
538540 <span class="lbl">merge requests</span>
539541 <span class="k">section</span>
540542 </a>
541543 </li>
542544 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
543-<a href="/diffs/releases" tabindex="-1">
545+<a role="presentation" data-href="/diffs/releases">
544546 <span class="lbl">releases</span>
545547 <span class="k">section</span>
546548 </a>
547549 </li>
548550 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
549-<a href="/diffs/actions" tabindex="-1">
551+<a role="presentation" data-href="/diffs/actions">
550552 <span class="lbl">actions</span>
551553 <span class="k">section</span>
552554 </a>
553555 </li>
554556 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
555-<a href="/diffs/tree/main" tabindex="-1">
557+<a role="presentation" data-href="/diffs/tree/main">
556558 <span class="lbl">main</span>
557559 <span class="k">branch</span>
558560 </a>
559561 </li>
560562 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
561-<a href="/diffs/tree/side" tabindex="-1">
563+<a role="presentation" data-href="/diffs/tree/side">
562564 <span class="lbl">side</span>
563565 <span class="k">branch</span>
564566 </a>
565567 </li>
566568 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
567-<a href="/diffs/tree/v1.0.0" tabindex="-1">
569+<a role="presentation" data-href="/diffs/tree/v1.0.0">
568570 <span class="lbl">v1.0.0</span>
569571 <span class="k">tag</span>
570572 </a>
571573 </li>
572574 <li id="cmd-o11" role="option" aria-selected="false" data-k="repo long">
573-<a href="/long" tabindex="-1">
575+<a role="presentation" data-href="/long">
574576 <span class="lbl">long</span>
575577 <span class="k">repo</span>
576578 </a>
577579 </li>
578580 <li id="cmd-o12" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
579-<a href="#" data-fire="keys" tabindex="-1">
581+<a role="presentation" data-fire="keys">
580582 <span class="lbl">turn single-key shortcuts off</span>
581583 <span class="k">action</span>
582584 </a>
@@ -310,14 +310,16 @@
310 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">310 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
311 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>311 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
312 </footer>312 </footer>
313-<div class="hint" role="status" aria-live="polite">313+<div class="hint">
314-<span class="hint-nav" :text="document.body.dataset.nav || ''">314+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
315 </span>315 </span>
316+<span role="status" aria-live="polite">
316 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">317 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
317 </span>318 </span>
318 <span class="hint-flash" :text="document.body.dataset.flash || ''">319 <span class="hint-flash" :text="document.body.dataset.flash || ''">
319 </span>320 </span>
320-<span class="hint-live" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Adiffs&amp;view=commits&amp;ref=main&amp;head=SHA40" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();321+</span>
322+<span class="hint-live" role="status" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Adiffs&amp;view=commits&amp;ref=main&amp;head=SHA40" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
321 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();323 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();
322 htmx:sse:error -> ermiteLive.error(event.detail.status);324 htmx:sse:error -> ermiteLive.error(event.detail.status);
323 htmx:sse:before:connection -> ermiteLive.gate(event);325 htmx:sse:before:connection -> ermiteLive.gate(event);
@@ -329,7 +331,7 @@
329 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">331 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
330 <div class="panel-head">332 <div class="panel-head">
331 <h2>Keyboard shortcuts</h2>333 <h2>Keyboard shortcuts</h2>
332-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">334+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
333 <kbd>esc</kbd> close</button>335 <kbd>esc</kbd> close</button>
334 </div>336 </div>
335 <div class="keys-pref">337 <div class="keys-pref">
@@ -463,7 +465,7 @@
463 <div class="panel-head">465 <div class="panel-head">
464 <label for="refs-filter" class="sr">filter branches and tags</label>466 <label for="refs-filter" class="sr">filter branches and tags</label>
465 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">467 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
466-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">468+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
467 <kbd>esc</kbd>469 <kbd>esc</kbd>
468 </button>470 </button>
469 </div>471 </div>
@@ -498,85 +500,85 @@
498 <div class="panel-head">500 <div class="panel-head">
499 <label for="cmd-q" class="sr">go to</label>501 <label for="cmd-q" class="sr">go to</label>
500 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">502 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
501-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">503+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
502 <kbd>esc</kbd>504 <kbd>esc</kbd>
503 </button>505 </button>
504 </div>506 </div>
505 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">507 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
506 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>508 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
507-<a href="/" tabindex="-1">509+<a role="presentation" data-href="/">
508 <span class="lbl">home</span>510 <span class="lbl">home</span>
509 <span class="k">go</span>511 <span class="k">go</span>
510 </a>512 </a>
511 </li>513 </li>
512 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">514 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
513-<a href="/diffs" tabindex="-1">515+<a role="presentation" data-href="/diffs">
514 <span class="lbl">summary</span>516 <span class="lbl">summary</span>
515 <span class="k">section</span>517 <span class="k">section</span>
516 </a>518 </a>
517 </li>519 </li>
518 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">520 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
519-<a href="/diffs/tree/main" tabindex="-1">521+<a role="presentation" data-href="/diffs/tree/main">
520 <span class="lbl">files</span>522 <span class="lbl">files</span>
521 <span class="k">section</span>523 <span class="k">section</span>
522 </a>524 </a>
523 </li>525 </li>
524 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">526 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
525-<a href="/diffs/commits/main" tabindex="-1">527+<a role="presentation" data-href="/diffs/commits/main">
526 <span class="lbl">commits</span>528 <span class="lbl">commits</span>
527 <span class="k">section</span>529 <span class="k">section</span>
528 </a>530 </a>
529 </li>531 </li>
530 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">532 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
531-<a href="/diffs/refs" tabindex="-1">533+<a role="presentation" data-href="/diffs/refs">
532 <span class="lbl">branches &amp; tags</span>534 <span class="lbl">branches &amp; tags</span>
533 <span class="k">section</span>535 <span class="k">section</span>
534 </a>536 </a>
535 </li>537 </li>
536 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">538 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
537-<a href="/diffs/merge-requests" tabindex="-1">539+<a role="presentation" data-href="/diffs/merge-requests">
538 <span class="lbl">merge requests</span>540 <span class="lbl">merge requests</span>
539 <span class="k">section</span>541 <span class="k">section</span>
540 </a>542 </a>
541 </li>543 </li>
542 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">544 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
543-<a href="/diffs/releases" tabindex="-1">545+<a role="presentation" data-href="/diffs/releases">
544 <span class="lbl">releases</span>546 <span class="lbl">releases</span>
545 <span class="k">section</span>547 <span class="k">section</span>
546 </a>548 </a>
547 </li>549 </li>
548 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">550 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
549-<a href="/diffs/actions" tabindex="-1">551+<a role="presentation" data-href="/diffs/actions">
550 <span class="lbl">actions</span>552 <span class="lbl">actions</span>
551 <span class="k">section</span>553 <span class="k">section</span>
552 </a>554 </a>
553 </li>555 </li>
554 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">556 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch main">
555-<a href="/diffs/tree/main" tabindex="-1">557+<a role="presentation" data-href="/diffs/tree/main">
556 <span class="lbl">main</span>558 <span class="lbl">main</span>
557 <span class="k">branch</span>559 <span class="k">branch</span>
558 </a>560 </a>
559 </li>561 </li>
560 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">562 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch side">
561-<a href="/diffs/tree/side" tabindex="-1">563+<a role="presentation" data-href="/diffs/tree/side">
562 <span class="lbl">side</span>564 <span class="lbl">side</span>
563 <span class="k">branch</span>565 <span class="k">branch</span>
564 </a>566 </a>
565 </li>567 </li>
566 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">568 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v1.0.0">
567-<a href="/diffs/tree/v1.0.0" tabindex="-1">569+<a role="presentation" data-href="/diffs/tree/v1.0.0">
568 <span class="lbl">v1.0.0</span>570 <span class="lbl">v1.0.0</span>
569 <span class="k">tag</span>571 <span class="k">tag</span>
570 </a>572 </a>
571 </li>573 </li>
572 <li id="cmd-o11" role="option" aria-selected="false" data-k="repo long">574 <li id="cmd-o11" role="option" aria-selected="false" data-k="repo long">
573-<a href="/long" tabindex="-1">575+<a role="presentation" data-href="/long">
574 <span class="lbl">long</span>576 <span class="lbl">long</span>
575 <span class="k">repo</span>577 <span class="k">repo</span>
576 </a>578 </a>
577 </li>579 </li>
578 <li id="cmd-o12" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">580 <li id="cmd-o12" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
579-<a href="#" data-fire="keys" tabindex="-1">581+<a role="presentation" data-fire="keys">
580 <span class="lbl">turn single-key shortcuts off</span>582 <span class="lbl">turn single-key shortcuts off</span>
581 <span class="k">action</span>583 <span class="k">action</span>
582 </a>584 </a>
M internal/app/testdata/web/empty.html +9 -7
@@ -86,18 +86,20 @@
8686 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
8787 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
8888 </footer>
89-<div class="hint" role="status" aria-live="polite">
90-<span class="hint-nav" :text="document.body.dataset.nav || ''">
89+<div class="hint">
90+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
9191 </span>
92+<span role="status" aria-live="polite">
9293 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
9394 </span>
9495 <span class="hint-flash" :text="document.body.dataset.flash || ''">
9596 </span>
97+</span>
9698 </div>
9799 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
98100 <div class="panel-head">
99101 <h2>Keyboard shortcuts</h2>
100-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
102+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
101103 <kbd>esc</kbd> close</button>
102104 </div>
103105 <div class="keys-pref">
@@ -231,25 +233,25 @@
231233 <div class="panel-head">
232234 <label for="cmd-q" class="sr">go to</label>
233235 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
234-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
236+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
235237 <kbd>esc</kbd>
236238 </button>
237239 </div>
238240 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
239241 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
240-<a href="/" tabindex="-1">
242+<a role="presentation" data-href="/">
241243 <span class="lbl">home</span>
242244 <span class="k">go</span>
243245 </a>
244246 </li>
245247 <li id="cmd-o1" role="option" aria-selected="false" data-k="repo demo">
246-<a href="/demo" tabindex="-1">
248+<a role="presentation" data-href="/demo">
247249 <span class="lbl">demo</span>
248250 <span class="k">repo</span>
249251 </a>
250252 </li>
251253 <li id="cmd-o2" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
252-<a href="#" data-fire="keys" tabindex="-1">
254+<a role="presentation" data-fire="keys">
253255 <span class="lbl">turn single-key shortcuts off</span>
254256 <span class="k">action</span>
255257 </a>
@@ -86,18 +86,20 @@
86 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">86 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
87 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>87 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
88 </footer>88 </footer>
89-<div class="hint" role="status" aria-live="polite">89+<div class="hint">
90-<span class="hint-nav" :text="document.body.dataset.nav || ''">90+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
91 </span>91 </span>
92+<span role="status" aria-live="polite">
92 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">93 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
93 </span>94 </span>
94 <span class="hint-flash" :text="document.body.dataset.flash || ''">95 <span class="hint-flash" :text="document.body.dataset.flash || ''">
95 </span>96 </span>
97+</span>
96 </div>98 </div>
97 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">99 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
98 <div class="panel-head">100 <div class="panel-head">
99 <h2>Keyboard shortcuts</h2>101 <h2>Keyboard shortcuts</h2>
100-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">102+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
101 <kbd>esc</kbd> close</button>103 <kbd>esc</kbd> close</button>
102 </div>104 </div>
103 <div class="keys-pref">105 <div class="keys-pref">
@@ -231,25 +233,25 @@
231 <div class="panel-head">233 <div class="panel-head">
232 <label for="cmd-q" class="sr">go to</label>234 <label for="cmd-q" class="sr">go to</label>
233 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">235 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
234-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">236+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
235 <kbd>esc</kbd>237 <kbd>esc</kbd>
236 </button>238 </button>
237 </div>239 </div>
238 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">240 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
239 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>241 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
240-<a href="/" tabindex="-1">242+<a role="presentation" data-href="/">
241 <span class="lbl">home</span>243 <span class="lbl">home</span>
242 <span class="k">go</span>244 <span class="k">go</span>
243 </a>245 </a>
244 </li>246 </li>
245 <li id="cmd-o1" role="option" aria-selected="false" data-k="repo demo">247 <li id="cmd-o1" role="option" aria-selected="false" data-k="repo demo">
246-<a href="/demo" tabindex="-1">248+<a role="presentation" data-href="/demo">
247 <span class="lbl">demo</span>249 <span class="lbl">demo</span>
248 <span class="k">repo</span>250 <span class="k">repo</span>
249 </a>251 </a>
250 </li>252 </li>
251 <li id="cmd-o2" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">253 <li id="cmd-o2" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
252-<a href="#" data-fire="keys" tabindex="-1">254+<a role="presentation" data-fire="keys">
253 <span class="lbl">turn single-key shortcuts off</span>255 <span class="lbl">turn single-key shortcuts off</span>
254 <span class="k">action</span>256 <span class="k">action</span>
255 </a>257 </a>
M internal/app/testdata/web/home.html +11 -9
@@ -182,14 +182,16 @@
182182 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
183183 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
184184 </footer>
185-<div class="hint" role="status" aria-live="polite">
186-<span class="hint-nav" :text="document.body.dataset.nav || ''">
185+<div class="hint">
186+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
187187 </span>
188+<span role="status" aria-live="polite">
188189 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
189190 </span>
190191 <span class="hint-flash" :text="document.body.dataset.flash || ''">
191192 </span>
192-<span class="hint-live" data-state="connecting" hx-sse:connect="/-/events?topic=home" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
193+</span>
194+<span class="hint-live" role="status" data-state="connecting" hx-sse:connect="/-/events?topic=home" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
193195 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();
194196 htmx:sse:error -> ermiteLive.error(event.detail.status);
195197 htmx:sse:before:connection -> ermiteLive.gate(event);
@@ -201,7 +203,7 @@
201203 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
202204 <div class="panel-head">
203205 <h2>Keyboard shortcuts</h2>
204-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
206+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
205207 <kbd>esc</kbd> close</button>
206208 </div>
207209 <div class="keys-pref">
@@ -335,31 +337,31 @@
335337 <div class="panel-head">
336338 <label for="cmd-q" class="sr">go to</label>
337339 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
338-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
340+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
339341 <kbd>esc</kbd>
340342 </button>
341343 </div>
342344 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
343345 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
344-<a href="/" tabindex="-1">
346+<a role="presentation" data-href="/">
345347 <span class="lbl">home</span>
346348 <span class="k">go</span>
347349 </a>
348350 </li>
349351 <li id="cmd-o1" role="option" aria-selected="false" data-k="repo quiet">
350-<a href="/quiet" tabindex="-1">
352+<a role="presentation" data-href="/quiet">
351353 <span class="lbl">quiet</span>
352354 <span class="k">repo</span>
353355 </a>
354356 </li>
355357 <li id="cmd-o2" role="option" aria-selected="false" data-k="repo demo">
356-<a href="/demo" tabindex="-1">
358+<a role="presentation" data-href="/demo">
357359 <span class="lbl">demo</span>
358360 <span class="k">repo</span>
359361 </a>
360362 </li>
361363 <li id="cmd-o3" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
362-<a href="#" data-fire="keys" tabindex="-1">
364+<a role="presentation" data-fire="keys">
363365 <span class="lbl">turn single-key shortcuts off</span>
364366 <span class="k">action</span>
365367 </a>
@@ -182,14 +182,16 @@
182 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">182 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
183 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>183 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
184 </footer>184 </footer>
185-<div class="hint" role="status" aria-live="polite">185+<div class="hint">
186-<span class="hint-nav" :text="document.body.dataset.nav || ''">186+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
187 </span>187 </span>
188+<span role="status" aria-live="polite">
188 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">189 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
189 </span>190 </span>
190 <span class="hint-flash" :text="document.body.dataset.flash || ''">191 <span class="hint-flash" :text="document.body.dataset.flash || ''">
191 </span>192 </span>
192-<span class="hint-live" data-state="connecting" hx-sse:connect="/-/events?topic=home" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();193+</span>
194+<span class="hint-live" role="status" data-state="connecting" hx-sse:connect="/-/events?topic=home" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
193 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();195 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();
194 htmx:sse:error -> ermiteLive.error(event.detail.status);196 htmx:sse:error -> ermiteLive.error(event.detail.status);
195 htmx:sse:before:connection -> ermiteLive.gate(event);197 htmx:sse:before:connection -> ermiteLive.gate(event);
@@ -201,7 +203,7 @@
201 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">203 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
202 <div class="panel-head">204 <div class="panel-head">
203 <h2>Keyboard shortcuts</h2>205 <h2>Keyboard shortcuts</h2>
204-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">206+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
205 <kbd>esc</kbd> close</button>207 <kbd>esc</kbd> close</button>
206 </div>208 </div>
207 <div class="keys-pref">209 <div class="keys-pref">
@@ -335,31 +337,31 @@
335 <div class="panel-head">337 <div class="panel-head">
336 <label for="cmd-q" class="sr">go to</label>338 <label for="cmd-q" class="sr">go to</label>
337 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">339 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
338-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">340+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
339 <kbd>esc</kbd>341 <kbd>esc</kbd>
340 </button>342 </button>
341 </div>343 </div>
342 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">344 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
343 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>345 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
344-<a href="/" tabindex="-1">346+<a role="presentation" data-href="/">
345 <span class="lbl">home</span>347 <span class="lbl">home</span>
346 <span class="k">go</span>348 <span class="k">go</span>
347 </a>349 </a>
348 </li>350 </li>
349 <li id="cmd-o1" role="option" aria-selected="false" data-k="repo quiet">351 <li id="cmd-o1" role="option" aria-selected="false" data-k="repo quiet">
350-<a href="/quiet" tabindex="-1">352+<a role="presentation" data-href="/quiet">
351 <span class="lbl">quiet</span>353 <span class="lbl">quiet</span>
352 <span class="k">repo</span>354 <span class="k">repo</span>
353 </a>355 </a>
354 </li>356 </li>
355 <li id="cmd-o2" role="option" aria-selected="false" data-k="repo demo">357 <li id="cmd-o2" role="option" aria-selected="false" data-k="repo demo">
356-<a href="/demo" tabindex="-1">358+<a role="presentation" data-href="/demo">
357 <span class="lbl">demo</span>359 <span class="lbl">demo</span>
358 <span class="k">repo</span>360 <span class="k">repo</span>
359 </a>361 </a>
360 </li>362 </li>
361 <li id="cmd-o3" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">363 <li id="cmd-o3" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
362-<a href="#" data-fire="keys" tabindex="-1">364+<a role="presentation" data-fire="keys">
363 <span class="lbl">turn single-key shortcuts off</span>365 <span class="lbl">turn single-key shortcuts off</span>
364 <span class="k">action</span>366 <span class="k">action</span>
365 </a>367 </a>
M internal/app/testdata/web/not-found-page.html +8 -6
@@ -75,18 +75,20 @@
7575 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
7676 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
7777 </footer>
78-<div class="hint" role="status" aria-live="polite">
79-<span class="hint-nav" :text="document.body.dataset.nav || ''">
78+<div class="hint">
79+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
8080 </span>
81+<span role="status" aria-live="polite">
8182 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
8283 </span>
8384 <span class="hint-flash" :text="document.body.dataset.flash || ''">
8485 </span>
86+</span>
8587 </div>
8688 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
8789 <div class="panel-head">
8890 <h2>Keyboard shortcuts</h2>
89-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
91+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
9092 <kbd>esc</kbd> close</button>
9193 </div>
9294 <div class="keys-pref">
@@ -220,19 +222,19 @@
220222 <div class="panel-head">
221223 <label for="cmd-q" class="sr">go to</label>
222224 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
223-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
225+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
224226 <kbd>esc</kbd>
225227 </button>
226228 </div>
227229 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
228230 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
229-<a href="/" tabindex="-1">
231+<a role="presentation" data-href="/">
230232 <span class="lbl">home</span>
231233 <span class="k">go</span>
232234 </a>
233235 </li>
234236 <li id="cmd-o1" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
235-<a href="#" data-fire="keys" tabindex="-1">
237+<a role="presentation" data-fire="keys">
236238 <span class="lbl">turn single-key shortcuts off</span>
237239 <span class="k">action</span>
238240 </a>
@@ -75,18 +75,20 @@
75 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">75 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
76 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>76 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
77 </footer>77 </footer>
78-<div class="hint" role="status" aria-live="polite">78+<div class="hint">
79-<span class="hint-nav" :text="document.body.dataset.nav || ''">79+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
80 </span>80 </span>
81+<span role="status" aria-live="polite">
81 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">82 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
82 </span>83 </span>
83 <span class="hint-flash" :text="document.body.dataset.flash || ''">84 <span class="hint-flash" :text="document.body.dataset.flash || ''">
84 </span>85 </span>
86+</span>
85 </div>87 </div>
86 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">88 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
87 <div class="panel-head">89 <div class="panel-head">
88 <h2>Keyboard shortcuts</h2>90 <h2>Keyboard shortcuts</h2>
89-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">91+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
90 <kbd>esc</kbd> close</button>92 <kbd>esc</kbd> close</button>
91 </div>93 </div>
92 <div class="keys-pref">94 <div class="keys-pref">
@@ -220,19 +222,19 @@
220 <div class="panel-head">222 <div class="panel-head">
221 <label for="cmd-q" class="sr">go to</label>223 <label for="cmd-q" class="sr">go to</label>
222 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">224 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
223-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">225+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
224 <kbd>esc</kbd>226 <kbd>esc</kbd>
225 </button>227 </button>
226 </div>228 </div>
227 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">229 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
228 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>230 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
229-<a href="/" tabindex="-1">231+<a role="presentation" data-href="/">
230 <span class="lbl">home</span>232 <span class="lbl">home</span>
231 <span class="k">go</span>233 <span class="k">go</span>
232 </a>234 </a>
233 </li>235 </li>
234 <li id="cmd-o1" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">236 <li id="cmd-o1" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
235-<a href="#" data-fire="keys" tabindex="-1">237+<a role="presentation" data-fire="keys">
236 <span class="lbl">turn single-key shortcuts off</span>238 <span class="lbl">turn single-key shortcuts off</span>
237 <span class="k">action</span>239 <span class="k">action</span>
238 </a>240 </a>
M internal/app/testdata/web/not-found.html +8 -6
@@ -75,18 +75,20 @@
7575 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
7676 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
7777 </footer>
78-<div class="hint" role="status" aria-live="polite">
79-<span class="hint-nav" :text="document.body.dataset.nav || ''">
78+<div class="hint">
79+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
8080 </span>
81+<span role="status" aria-live="polite">
8182 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
8283 </span>
8384 <span class="hint-flash" :text="document.body.dataset.flash || ''">
8485 </span>
86+</span>
8587 </div>
8688 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
8789 <div class="panel-head">
8890 <h2>Keyboard shortcuts</h2>
89-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
91+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
9092 <kbd>esc</kbd> close</button>
9193 </div>
9294 <div class="keys-pref">
@@ -220,19 +222,19 @@
220222 <div class="panel-head">
221223 <label for="cmd-q" class="sr">go to</label>
222224 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
223-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
225+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
224226 <kbd>esc</kbd>
225227 </button>
226228 </div>
227229 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
228230 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
229-<a href="/" tabindex="-1">
231+<a role="presentation" data-href="/">
230232 <span class="lbl">home</span>
231233 <span class="k">go</span>
232234 </a>
233235 </li>
234236 <li id="cmd-o1" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
235-<a href="#" data-fire="keys" tabindex="-1">
237+<a role="presentation" data-fire="keys">
236238 <span class="lbl">turn single-key shortcuts off</span>
237239 <span class="k">action</span>
238240 </a>
@@ -75,18 +75,20 @@
75 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">75 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
76 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>76 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
77 </footer>77 </footer>
78-<div class="hint" role="status" aria-live="polite">78+<div class="hint">
79-<span class="hint-nav" :text="document.body.dataset.nav || ''">79+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
80 </span>80 </span>
81+<span role="status" aria-live="polite">
81 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">82 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
82 </span>83 </span>
83 <span class="hint-flash" :text="document.body.dataset.flash || ''">84 <span class="hint-flash" :text="document.body.dataset.flash || ''">
84 </span>85 </span>
86+</span>
85 </div>87 </div>
86 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">88 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
87 <div class="panel-head">89 <div class="panel-head">
88 <h2>Keyboard shortcuts</h2>90 <h2>Keyboard shortcuts</h2>
89-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">91+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
90 <kbd>esc</kbd> close</button>92 <kbd>esc</kbd> close</button>
91 </div>93 </div>
92 <div class="keys-pref">94 <div class="keys-pref">
@@ -220,19 +222,19 @@
220 <div class="panel-head">222 <div class="panel-head">
221 <label for="cmd-q" class="sr">go to</label>223 <label for="cmd-q" class="sr">go to</label>
222 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">224 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
223-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">225+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
224 <kbd>esc</kbd>226 <kbd>esc</kbd>
225 </button>227 </button>
226 </div>228 </div>
227 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">229 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
228 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>230 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
229-<a href="/" tabindex="-1">231+<a role="presentation" data-href="/">
230 <span class="lbl">home</span>232 <span class="lbl">home</span>
231 <span class="k">go</span>233 <span class="k">go</span>
232 </a>234 </a>
233 </li>235 </li>
234 <li id="cmd-o1" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">236 <li id="cmd-o1" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
235-<a href="#" data-fire="keys" tabindex="-1">237+<a role="presentation" data-fire="keys">
236 <span class="lbl">turn single-key shortcuts off</span>238 <span class="lbl">turn single-key shortcuts off</span>
237 <span class="k">action</span>239 <span class="k">action</span>
238 </a>240 </a>
M internal/app/testdata/web/refs.html +22 -20
@@ -192,14 +192,16 @@
192192 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
193193 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
194194 </footer>
195-<div class="hint" role="status" aria-live="polite">
196-<span class="hint-nav" :text="document.body.dataset.nav || ''">
195+<div class="hint">
196+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
197197 </span>
198+<span role="status" aria-live="polite">
198199 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
199200 </span>
200201 <span class="hint-flash" :text="document.body.dataset.flash || ''">
201202 </span>
202-<span class="hint-live" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Ademo&amp;view=refs" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
203+</span>
204+<span class="hint-live" role="status" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Ademo&amp;view=refs" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
203205 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();
204206 htmx:sse:error -> ermiteLive.error(event.detail.status);
205207 htmx:sse:before:connection -> ermiteLive.gate(event);
@@ -211,7 +213,7 @@
211213 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
212214 <div class="panel-head">
213215 <h2>Keyboard shortcuts</h2>
214-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
216+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
215217 <kbd>esc</kbd> close</button>
216218 </div>
217219 <div class="keys-pref">
@@ -345,7 +347,7 @@
345347 <div class="panel-head">
346348 <label for="refs-filter" class="sr">filter branches and tags</label>
347349 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
348-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
350+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
349351 <kbd>esc</kbd>
350352 </button>
351353 </div>
@@ -384,91 +386,91 @@
384386 <div class="panel-head">
385387 <label for="cmd-q" class="sr">go to</label>
386388 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
387-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">
389+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
388390 <kbd>esc</kbd>
389391 </button>
390392 </div>
391393 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
392394 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
393-<a href="/" tabindex="-1">
395+<a role="presentation" data-href="/">
394396 <span class="lbl">home</span>
395397 <span class="k">go</span>
396398 </a>
397399 </li>
398400 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
399-<a href="/demo" tabindex="-1">
401+<a role="presentation" data-href="/demo">
400402 <span class="lbl">summary</span>
401403 <span class="k">section</span>
402404 </a>
403405 </li>
404406 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
405-<a href="/demo/tree/main" tabindex="-1">
407+<a role="presentation" data-href="/demo/tree/main">
406408 <span class="lbl">files</span>
407409 <span class="k">section</span>
408410 </a>
409411 </li>
410412 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
411-<a href="/demo/commits/main" tabindex="-1">
413+<a role="presentation" data-href="/demo/commits/main">
412414 <span class="lbl">commits</span>
413415 <span class="k">section</span>
414416 </a>
415417 </li>
416418 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
417-<a href="/demo/refs" tabindex="-1">
419+<a role="presentation" data-href="/demo/refs">
418420 <span class="lbl">branches &amp; tags</span>
419421 <span class="k">section</span>
420422 </a>
421423 </li>
422424 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
423-<a href="/demo/merge-requests" tabindex="-1">
425+<a role="presentation" data-href="/demo/merge-requests">
424426 <span class="lbl">merge requests</span>
425427 <span class="k">section</span>
426428 </a>
427429 </li>
428430 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
429-<a href="/demo/releases" tabindex="-1">
431+<a role="presentation" data-href="/demo/releases">
430432 <span class="lbl">releases</span>
431433 <span class="k">section</span>
432434 </a>
433435 </li>
434436 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
435-<a href="/demo/actions" tabindex="-1">
437+<a role="presentation" data-href="/demo/actions">
436438 <span class="lbl">actions</span>
437439 <span class="k">section</span>
438440 </a>
439441 </li>
440442 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
441-<a href="/demo/tree/feature/x" tabindex="-1">
443+<a role="presentation" data-href="/demo/tree/feature/x">
442444 <span class="lbl">feature/x</span>
443445 <span class="k">branch</span>
444446 </a>
445447 </li>
446448 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
447-<a href="/demo/tree/main" tabindex="-1">
449+<a role="presentation" data-href="/demo/tree/main">
448450 <span class="lbl">main</span>
449451 <span class="k">branch</span>
450452 </a>
451453 </li>
452454 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v0.1.0">
453-<a href="/demo/tree/v0.1.0" tabindex="-1">
455+<a role="presentation" data-href="/demo/tree/v0.1.0">
454456 <span class="lbl">v0.1.0</span>
455457 <span class="k">tag</span>
456458 </a>
457459 </li>
458460 <li id="cmd-o11" role="option" aria-selected="false" data-k="tag v0.2.0">
459-<a href="/demo/tree/v0.2.0" tabindex="-1">
461+<a role="presentation" data-href="/demo/tree/v0.2.0">
460462 <span class="lbl">v0.2.0</span>
461463 <span class="k">tag</span>
462464 </a>
463465 </li>
464466 <li id="cmd-o12" role="option" aria-selected="false" data-k="repo quiet">
465-<a href="/quiet" tabindex="-1">
467+<a role="presentation" data-href="/quiet">
466468 <span class="lbl">quiet</span>
467469 <span class="k">repo</span>
468470 </a>
469471 </li>
470472 <li id="cmd-o13" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
471-<a href="#" data-fire="keys" tabindex="-1">
473+<a role="presentation" data-fire="keys">
472474 <span class="lbl">turn single-key shortcuts off</span>
473475 <span class="k">action</span>
474476 </a>
@@ -192,14 +192,16 @@
192 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">192 <button type="button" class="foot-keys" data-js data-fire="help" aria-haspopup="dialog" aria-controls="panel-help" aria-keyshortcuts="?">
193 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>193 <kbd aria-hidden="true">?</kbd> keyboard shortcuts</button>
194 </footer>194 </footer>
195-<div class="hint" role="status" aria-live="polite">195+<div class="hint">
196-<span class="hint-nav" :text="document.body.dataset.nav || ''">196+<span aria-hidden="true" class="hint-nav" :text="document.body.dataset.nav || ''">
197 </span>197 </span>
198+<span role="status" aria-live="polite">
198 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">199 <span class="hint-sel" :text="document.body.dataset.sel ? document.body.dataset.sel + ' · y permalink' : ''">
199 </span>200 </span>
200 <span class="hint-flash" :text="document.body.dataset.flash || ''">201 <span class="hint-flash" :text="document.body.dataset.flash || ''">
201 </span>202 </span>
202-<span class="hint-live" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Ademo&amp;view=refs" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();203+</span>
204+<span class="hint-live" role="status" data-state="connecting" hx-sse:connect="/-/events?topic=repo%3Ademo&amp;view=refs" hx-swap="none" :text="data.state === 'offline' ? 'live updates paused' : ''" hx-on="htmx:sse:after:connection -> ermiteLive.back();
203 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();205 htmx:sse:close, htmx:sse:error -> ermiteLive.lost();
204 htmx:sse:error -> ermiteLive.error(event.detail.status);206 htmx:sse:error -> ermiteLive.error(event.detail.status);
205 htmx:sse:before:connection -> ermiteLive.gate(event);207 htmx:sse:before:connection -> ermiteLive.gate(event);
@@ -211,7 +213,7 @@
211 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">213 <dialog id="panel-help" class="panel modal" aria-label="Keyboard shortcuts" hx-on:keydown="event.key === 'Escape' && (event.preventDefault(), this.close())" hx-on:click="event.target === this && this.close()">
212 <div class="panel-head">214 <div class="panel-head">
213 <h2>Keyboard shortcuts</h2>215 <h2>Keyboard shortcuts</h2>
214-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">216+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
215 <kbd>esc</kbd> close</button>217 <kbd>esc</kbd> close</button>
216 </div>218 </div>
217 <div class="keys-pref">219 <div class="keys-pref">
@@ -345,7 +347,7 @@
345 <div class="panel-head">347 <div class="panel-head">
346 <label for="refs-filter" class="sr">filter branches and tags</label>348 <label for="refs-filter" class="sr">filter branches and tags</label>
347 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">349 <input id="refs-filter" type="search" placeholder="Switch branch or tag…" autocomplete="off" data-pick="#panel-refs li" hx-on:input="ermite.filter(this)">
348-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">350+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
349 <kbd>esc</kbd>351 <kbd>esc</kbd>
350 </button>352 </button>
351 </div>353 </div>
@@ -384,91 +386,91 @@
384 <div class="panel-head">386 <div class="panel-head">
385 <label for="cmd-q" class="sr">go to</label>387 <label for="cmd-q" class="sr">go to</label>
386 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">388 <input id="cmd-q" type="search" placeholder="Go to a section, branch, tag, file or repository…" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-controls="cmd-list" aria-activedescendant="cmd-o0" hx-on:input="ermite.cmdFilter(this); ermiteFinder.palette(this)" hx-on:keydown="ermite.cmdKey(event)">
387-<button type="button" class="panel-x" aria-label="Close" hx-on:click="closest('dialog').close()">389+<button type="button" class="panel-x" aria-label="Close (esc)" hx-on:click="closest('dialog').close()">
388 <kbd>esc</kbd>390 <kbd>esc</kbd>
389 </button>391 </button>
390 </div>392 </div>
391 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">393 <ul id="cmd-list" class="cmd-list" role="listbox" aria-label="Targets">
392 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>394 <li id="cmd-o0" role="option" aria-selected="true" data-k="go home" data-cursor>
393-<a href="/" tabindex="-1">395+<a role="presentation" data-href="/">
394 <span class="lbl">home</span>396 <span class="lbl">home</span>
395 <span class="k">go</span>397 <span class="k">go</span>
396 </a>398 </a>
397 </li>399 </li>
398 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">400 <li id="cmd-o1" role="option" aria-selected="false" data-k="section summary">
399-<a href="/demo" tabindex="-1">401+<a role="presentation" data-href="/demo">
400 <span class="lbl">summary</span>402 <span class="lbl">summary</span>
401 <span class="k">section</span>403 <span class="k">section</span>
402 </a>404 </a>
403 </li>405 </li>
404 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">406 <li id="cmd-o2" role="option" aria-selected="false" data-k="section files">
405-<a href="/demo/tree/main" tabindex="-1">407+<a role="presentation" data-href="/demo/tree/main">
406 <span class="lbl">files</span>408 <span class="lbl">files</span>
407 <span class="k">section</span>409 <span class="k">section</span>
408 </a>410 </a>
409 </li>411 </li>
410 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">412 <li id="cmd-o3" role="option" aria-selected="false" data-k="section commits">
411-<a href="/demo/commits/main" tabindex="-1">413+<a role="presentation" data-href="/demo/commits/main">
412 <span class="lbl">commits</span>414 <span class="lbl">commits</span>
413 <span class="k">section</span>415 <span class="k">section</span>
414 </a>416 </a>
415 </li>417 </li>
416 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">418 <li id="cmd-o4" role="option" aria-selected="false" data-k="section branches &amp; tags">
417-<a href="/demo/refs" tabindex="-1">419+<a role="presentation" data-href="/demo/refs">
418 <span class="lbl">branches &amp; tags</span>420 <span class="lbl">branches &amp; tags</span>
419 <span class="k">section</span>421 <span class="k">section</span>
420 </a>422 </a>
421 </li>423 </li>
422 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">424 <li id="cmd-o5" role="option" aria-selected="false" data-k="section merge requests">
423-<a href="/demo/merge-requests" tabindex="-1">425+<a role="presentation" data-href="/demo/merge-requests">
424 <span class="lbl">merge requests</span>426 <span class="lbl">merge requests</span>
425 <span class="k">section</span>427 <span class="k">section</span>
426 </a>428 </a>
427 </li>429 </li>
428 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">430 <li id="cmd-o6" role="option" aria-selected="false" data-k="section releases">
429-<a href="/demo/releases" tabindex="-1">431+<a role="presentation" data-href="/demo/releases">
430 <span class="lbl">releases</span>432 <span class="lbl">releases</span>
431 <span class="k">section</span>433 <span class="k">section</span>
432 </a>434 </a>
433 </li>435 </li>
434 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">436 <li id="cmd-o7" role="option" aria-selected="false" data-k="section actions">
435-<a href="/demo/actions" tabindex="-1">437+<a role="presentation" data-href="/demo/actions">
436 <span class="lbl">actions</span>438 <span class="lbl">actions</span>
437 <span class="k">section</span>439 <span class="k">section</span>
438 </a>440 </a>
439 </li>441 </li>
440 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">442 <li id="cmd-o8" role="option" aria-selected="false" data-k="branch feature/x">
441-<a href="/demo/tree/feature/x" tabindex="-1">443+<a role="presentation" data-href="/demo/tree/feature/x">
442 <span class="lbl">feature/x</span>444 <span class="lbl">feature/x</span>
443 <span class="k">branch</span>445 <span class="k">branch</span>
444 </a>446 </a>
445 </li>447 </li>
446 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">448 <li id="cmd-o9" role="option" aria-selected="false" data-k="branch main">
447-<a href="/demo/tree/main" tabindex="-1">449+<a role="presentation" data-href="/demo/tree/main">
448 <span class="lbl">main</span>450 <span class="lbl">main</span>
449 <span class="k">branch</span>451 <span class="k">branch</span>
450 </a>452 </a>
451 </li>453 </li>
452 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v0.1.0">454 <li id="cmd-o10" role="option" aria-selected="false" data-k="tag v0.1.0">
453-<a href="/demo/tree/v0.1.0" tabindex="-1">455+<a role="presentation" data-href="/demo/tree/v0.1.0">
454 <span class="lbl">v0.1.0</span>456 <span class="lbl">v0.1.0</span>
455 <span class="k">tag</span>457 <span class="k">tag</span>
456 </a>458 </a>
457 </li>459 </li>
458 <li id="cmd-o11" role="option" aria-selected="false" data-k="tag v0.2.0">460 <li id="cmd-o11" role="option" aria-selected="false" data-k="tag v0.2.0">
459-<a href="/demo/tree/v0.2.0" tabindex="-1">461+<a role="presentation" data-href="/demo/tree/v0.2.0">
460 <span class="lbl">v0.2.0</span>462 <span class="lbl">v0.2.0</span>
461 <span class="k">tag</span>463 <span class="k">tag</span>
462 </a>464 </a>
463 </li>465 </li>
464 <li id="cmd-o12" role="option" aria-selected="false" data-k="repo quiet">466 <li id="cmd-o12" role="option" aria-selected="false" data-k="repo quiet">
465-<a href="/quiet" tabindex="-1">467+<a role="presentation" data-href="/quiet">
466 <span class="lbl">quiet</span>468 <span class="lbl">quiet</span>
467 <span class="k">repo</span>469 <span class="k">repo</span>
468 </a>470 </a>
469 </li>471 </li>
470 <li id="cmd-o13" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">472 <li id="cmd-o13" role="option" aria-selected="false" data-k="action turn single-key shortcuts on off keyboard">
471-<a href="#" data-fire="keys" tabindex="-1">473+<a role="presentation" data-fire="keys">
472 <span class="lbl">turn single-key shortcuts off</span>474 <span class="lbl">turn single-key shortcuts off</span>
473 <span class="k">action</span>475 <span class="k">action</span>
474 </a>476 </a>
M internal/app/testdata/web/summary.html +22 -20
M internal/app/testdata/web/tree-nested.html +21 -19
M internal/app/testdata/web/tree-root.html +21 -19
M internal/app/testdata/web/tree-slash-ref.html +21 -19
M internal/app/testdata/web/tree-subdir.html +21 -19

Comments0 open / 0

no comments yet.

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
l
merge request: the list of files (j k move, enter opens, esc back)
M
merge request: the merge menu; there 1–3 pick the mode, D deletes the branch, enter merges
R
merge request: mark the head read
esc
close a dialog, leave a field

Branches 2

Tags 41

↑↓ moveenter openesc close