feat(website): add comprehensive accessibility improvements

Phase 1 - Screen Reader Critical:
- Add aria-label to main navigation
- Add accessible names to icon-only buttons (GitHub, theme toggle, close)
- Add aria-hidden to decorative SVGs and emoji icons
- Add role=dialog, aria-modal, aria-labelledby to modal
- Add skip link with visible focus state

Phase 2 - Keyboard Navigation:
- Implement focus trap in modal (Tab/Shift+Tab cycles)
- Return focus to trigger element on modal close
- Replace outline:none with visible focus rings
- Add keyboard navigation to install dropdown (arrows, escape)
- Add aria-expanded to dropdown toggles

Phase 3 - Dynamic Content:
- Add aria-live=polite to results counts and loading states
- Add role=listbox to search results
- Add role=list to resource lists
- Add role=menu/menuitem to dropdown menus

Phase 4 - Forms & Labels:
- Add .sr-only utility class for screen reader text
- Add visually hidden labels to all search inputs
- Add aria-label to filter dropdowns

Files modified:
- BaseLayout.astro, Modal.astro (ARIA attributes)
- modal.ts (focus trap, keyboard navigation)
- global.css (sr-only, skip-link, focus styles)
- All page files (labels, live regions, roles)
This commit is contained in:
Aaron Powell
2026-02-02 11:52:31 +11:00
parent f99c99a5d4
commit 94a395dbe0
13 changed files with 272 additions and 92 deletions

View File

@@ -1,5 +1,5 @@
{
"generated": "2026-02-01T23:32:16.397Z",
"generated": "2026-02-01T23:35:23.497Z",
"counts": {
"agents": 140,
"prompts": 134,

View File

@@ -110,6 +110,39 @@ body {
min-height: 100vh;
}
/* Accessibility Utilities */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.skip-link {
position: absolute;
top: -100%;
left: 50%;
transform: translateX(-50%);
background: var(--color-accent);
color: var(--color-text-emphasis);
padding: 12px 24px;
border-radius: var(--border-radius);
font-weight: 600;
z-index: 10000;
transition: top var(--transition);
}
.skip-link:focus {
top: 12px;
outline: 2px solid var(--color-text-emphasis);
outline-offset: 2px;
}
.container {
max-width: var(--container-width);
margin: 0 auto;
@@ -348,7 +381,8 @@ a:hover {
}
.hero-search input:focus {
outline: none;
outline: 2px solid var(--color-accent);
outline-offset: 2px;
border-color: var(--color-accent);
box-shadow: var(--shadow-glow);
}
@@ -651,6 +685,20 @@ a:hover {
text-decoration: none;
}
.btn:focus {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
}
.btn:focus:not(:focus-visible) {
outline: none;
}
.btn:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
}
.btn-primary {
background: var(--gradient-primary);
color: white;
@@ -1024,7 +1072,8 @@ a:hover {
}
.search-bar input:focus {
outline: none;
outline: 2px solid var(--color-accent);
outline-offset: 2px;
border-color: var(--color-accent);
box-shadow: var(--shadow-glow);
}
@@ -1068,7 +1117,8 @@ a:hover {
}
.filter-group select:focus {
outline: none;
outline: 2px solid var(--color-accent);
outline-offset: 2px;
border-color: var(--color-accent);
}