audit pass 7: ARIA, focus management, and label fixes

CSS:
- Add :focus-visible to sortable th, breadcrumb links, list links, cmd-item,
  combobox-option, typeahead-item, sidebar-sub-link, split-divider, stat-card
- Fix .lt-skip-link:focus to also include :focus-visible for spec compliance

JS:
- Mobile nav: add focus trap (_trapFocus), save/restore trigger focus, fix
  aria-hidden="false" to removeAttribute pattern, add document.contains guard
- Combobox: add aria-activedescendant on _moveFocus; add unique IDs to options;
  clear aria-activedescendant on close; wrap querySelectorAll in Array.from
- Typeahead: add aria-activedescendant on _moveFocus; add unique IDs to items;
  add aria-busy during async search; clear aria-activedescendant on select;
  wrap querySelectorAll in Array.from
- Command palette: add unique IDs to items; set/clear aria-activedescendant
  on move and mouseenter; clear on close
- Lightbox: add document.contains guard on focus setTimeout
- Stats filter: add Enter/Space keyboard handler for role="button" cards

HTML:
- Stat cards: add role="button" tabindex="0" aria-label (interactive divs)
- Advanced filter selects: add id/for associations to all 3 label+select pairs
- Accordion SVG icons: add aria-hidden="true" (decorative)
- Range input: add aria-label, aria-valuemin/max/now
- Wizard form controls: add id/for to all 4 label+input/select pairs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-26 20:02:15 -04:00
parent d08007cdd7
commit b84d71dd7a
3 changed files with 76 additions and 38 deletions
+15 -5
View File
@@ -1058,6 +1058,7 @@ select option:checked {
color: var(--accent-orange);
text-shadow: var(--glow-orange);
}
.lt-table th[data-sort-key]:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: -2px; }
.lt-table td {
padding: 0.55rem 0.85rem;
@@ -1495,11 +1496,13 @@ select option:checked {
}
.lt-stat-card:hover,
.lt-stat-card.active {
.lt-stat-card.active,
.lt-stat-card:focus-visible {
background: var(--bg-tertiary);
border-color: var(--accent-cyan-border);
box-shadow: var(--box-glow-cyan);
}
.lt-stat-card:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; }
.lt-stat-card:hover::before,
.lt-stat-card.active::before { height: 100%; }
@@ -2306,7 +2309,7 @@ select option:checked {
z-index: var(--z-toast);
transition: top 0.1s;
}
.lt-skip-link:focus { top: var(--space-sm); }
.lt-skip-link:focus, .lt-skip-link:focus-visible { top: var(--space-sm); }
.lt-sr-only {
position: absolute;
@@ -2519,6 +2522,7 @@ select option:checked {
transition: color 0.15s;
}
.lt-breadcrumb-item a:hover { color: var(--accent-cyan); }
.lt-breadcrumb-item a:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; border-radius: 2px; }
.lt-breadcrumb-item.active { color: var(--accent-orange); }
.lt-breadcrumb-sep { color: var(--border-dim); }
.lt-breadcrumb-sep::before { content: '/'; }
@@ -2867,7 +2871,8 @@ input[type="range"].lt-range::-moz-range-thumb {
transition: background 0.1s;
}
.lt-cmd-item:hover,
.lt-cmd-item.is-selected {
.lt-cmd-item.is-selected,
.lt-cmd-item:focus-visible {
background: rgba(0,212,255,0.08);
color: var(--accent-cyan);
}
@@ -3115,6 +3120,7 @@ input[type="range"].lt-range::-moz-range-thumb {
flex: 1;
}
.lt-list-item a:hover { color: var(--accent-cyan); }
.lt-list-item a:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; border-radius: 2px; }
.lt-list-item-meta { color: var(--text-dim); font-size: 0.7rem; margin-left: auto; }
.lt-list-item--active { background: rgba(255,107,0,0.06); border-left: 2px solid var(--accent-orange); }
@@ -4258,7 +4264,8 @@ html[data-theme="light"] ::-webkit-scrollbar-thumb:hover { background: var(--acc
transition: background 0.1s;
}
.lt-combobox-option:hover,
.lt-combobox-option.is-focused { background: var(--accent-cyan-dim); color: var(--accent-cyan); }
.lt-combobox-option.is-focused,
.lt-combobox-option:focus-visible { background: var(--accent-cyan-dim); color: var(--accent-cyan); }
.lt-combobox-option.is-selected::before {
content: '✓';
color: var(--accent-green);
@@ -4515,6 +4522,7 @@ body.lt-is-offline .lt-main { margin-top: 2rem; transition: margin-top 0.25s eas
}
.lt-split-divider:hover,
.lt-split-divider.is-dragging { background: var(--accent-cyan); }
.lt-split-divider:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; }
.lt-split--vertical .lt-split-divider::before { top: -6px; bottom: -6px; left: 0; right: 0; cursor: row-resize; }
.lt-split--vertical .lt-split-divider { cursor: row-resize; }
/* On mobile, stack vertically and hide divider */
@@ -4659,7 +4667,8 @@ body.lt-is-offline .lt-main { margin-top: 2rem; transition: margin-top 0.25s eas
transition: background 0.1s;
}
.lt-typeahead-item:hover,
.lt-typeahead-item.is-focused { background: var(--accent-cyan-dim); color: var(--accent-cyan); }
.lt-typeahead-item.is-focused,
.lt-typeahead-item:focus-visible { background: var(--accent-cyan-dim); color: var(--accent-cyan); }
.lt-typeahead-item mark {
background: none;
color: var(--accent-orange);
@@ -5010,6 +5019,7 @@ body.lt-is-offline .lt-main { margin-top: 2rem; transition: margin-top 0.25s eas
white-space: nowrap;
}
.lt-sidebar-sub-link:hover { color: var(--accent-cyan); background: var(--accent-cyan-dim); }
.lt-sidebar-sub-link:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 1px; border-radius: 2px; }
.lt-sidebar-sub-link.active,
.lt-sidebar-sub-link[aria-current="page"] {
color: var(--accent-orange);