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

@@ -4,7 +4,7 @@ import Modal from '../components/Modal.astro';
---
<BaseLayout title="Agents" description="Specialized agents that enhance GitHub Copilot for specific technologies, workflows, and domains" activeNav="agents">
<main>
<main id="main-content">
<div class="page-header">
<div class="container">
<h1>🤖 Custom Agents</h1>
@@ -15,6 +15,7 @@ import Modal from '../components/Modal.astro';
<div class="page-content">
<div class="container">
<div class="search-bar">
<label for="search-input" class="sr-only">Search agents</label>
<input type="text" id="search-input" placeholder="Search agents..." autocomplete="off">
</div>
@@ -22,11 +23,11 @@ import Modal from '../components/Modal.astro';
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-model">Model:</label>
<select id="filter-model" multiple></select>
<select id="filter-model" multiple aria-label="Filter by model"></select>
</div>
<div class="filter-group">
<label for="filter-tool">Tool:</label>
<select id="filter-tool" multiple></select>
<select id="filter-tool" multiple aria-label="Filter by tool"></select>
</div>
<div class="filter-group">
<label class="checkbox-label">
@@ -37,9 +38,9 @@ import Modal from '../components/Modal.astro';
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count"></div>
<div class="resource-list" id="resource-list">
<div class="loading">Loading agents...</div>
<div class="results-count" id="results-count" aria-live="polite"></div>
<div class="resource-list" id="resource-list" role="list">
<div class="loading" aria-live="polite">Loading agents...</div>
</div>
</div>
</div>

View File

@@ -4,7 +4,7 @@ import Modal from '../components/Modal.astro';
---
<BaseLayout title="Collections" description="Curated collections of prompts, instructions, and agents for specific workflows" activeNav="collections">
<main>
<main id="main-content">
<div class="page-header">
<div class="container">
<h1>📦 Collections</h1>
@@ -15,13 +15,14 @@ import Modal from '../components/Modal.astro';
<div class="page-content">
<div class="container">
<div class="search-bar">
<label for="search-input" class="sr-only">Search collections</label>
<input type="text" id="search-input" placeholder="Search collections..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-tag">Tag:</label>
<select id="filter-tag" multiple></select>
<select id="filter-tag" multiple aria-label="Filter by tag"></select>
</div>
<div class="filter-group">
<label class="checkbox-label">
@@ -32,9 +33,9 @@ import Modal from '../components/Modal.astro';
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count"></div>
<div class="resource-list" id="resource-list">
<div class="loading">Loading collections...</div>
<div class="results-count" id="results-count" aria-live="polite"></div>
<div class="resource-list" id="resource-list" role="list">
<div class="loading" aria-live="polite">Loading collections...</div>
</div>
</div>
</div>

View File

@@ -6,102 +6,104 @@ const base = import.meta.env.BASE_URL;
---
<BaseLayout title="Home" activeNav="">
<main>
<main id="main-content">
<!-- Hero Section -->
<section class="hero">
<section class="hero" aria-labelledby="hero-heading">
<div class="container">
<h1>Awesome GitHub Copilot</h1>
<h1 id="hero-heading">Awesome GitHub Copilot</h1>
<p class="hero-subtitle">Community-contributed instructions, prompts, agents, and skills to enhance your GitHub Copilot experience</p>
<div class="hero-search">
<input type="text" id="global-search" placeholder="Search all resources..." autocomplete="off">
<div id="search-results" class="search-results hidden"></div>
<label for="global-search" class="sr-only">Search all resources</label>
<input type="text" id="global-search" placeholder="Search all resources..." autocomplete="off" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-controls="search-results">
<div id="search-results" class="search-results hidden" role="listbox" aria-label="Search results"></div>
</div>
</div>
</section>
<!-- Quick Links -->
<section class="quick-links">
<section class="quick-links" aria-labelledby="quick-links-heading">
<h2 id="quick-links-heading" class="sr-only">Browse Resources</h2>
<div class="container">
<div class="cards-grid">
<a href={`${base}agents/`} class="card card-with-count" id="card-agents">
<div class="card-icon">🤖</div>
<div class="card-icon" aria-hidden="true">🤖</div>
<div class="card-content">
<h3>Agents</h3>
<p>Custom agents for specialized Copilot experiences</p>
</div>
<div class="card-count" data-count="agents">-</div>
<div class="card-count" data-count="agents" aria-label="Agent count">-</div>
</a>
<a href={`${base}prompts/`} class="card card-with-count" id="card-prompts">
<div class="card-icon">🎯</div>
<div class="card-icon" aria-hidden="true">🎯</div>
<div class="card-content">
<h3>Prompts</h3>
<p>Ready-to-use prompt templates for development tasks</p>
</div>
<div class="card-count" data-count="prompts">-</div>
<div class="card-count" data-count="prompts" aria-label="Prompt count">-</div>
</a>
<a href={`${base}instructions/`} class="card card-with-count" id="card-instructions">
<div class="card-icon">📋</div>
<div class="card-icon" aria-hidden="true">📋</div>
<div class="card-content">
<h3>Instructions</h3>
<p>Coding standards and best practices for Copilot</p>
</div>
<div class="card-count" data-count="instructions">-</div>
<div class="card-count" data-count="instructions" aria-label="Instruction count">-</div>
</a>
<a href={`${base}skills/`} class="card card-with-count" id="card-skills">
<div class="card-icon">⚡</div>
<div class="card-icon" aria-hidden="true">⚡</div>
<div class="card-content">
<h3>Skills</h3>
<p>Self-contained folders with instructions and resources</p>
</div>
<div class="card-count" data-count="skills">-</div>
<div class="card-count" data-count="skills" aria-label="Skill count">-</div>
</a>
<a href={`${base}collections/`} class="card card-with-count" id="card-collections">
<div class="card-icon">📦</div>
<div class="card-icon" aria-hidden="true">📦</div>
<div class="card-content">
<h3>Collections</h3>
<p>Curated collections organized by themes</p>
</div>
<div class="card-count" data-count="collections">-</div>
<div class="card-count" data-count="collections" aria-label="Collection count">-</div>
</a>
<a href={`${base}tools/`} class="card card-with-count" id="card-tools">
<div class="card-icon">🔧</div>
<div class="card-icon" aria-hidden="true">🔧</div>
<div class="card-content">
<h3>Tools</h3>
<p>MCP servers and developer tools</p>
</div>
<div class="card-count" data-count="tools">-</div>
<div class="card-count" data-count="tools" aria-label="Tool count">-</div>
</a>
</div>
</div>
</section>
<!-- Featured Collections -->
<section class="featured">
<section class="featured" aria-labelledby="featured-heading">
<div class="container">
<h2>Featured Collections</h2>
<div id="featured-collections" class="cards-grid">
<h2 id="featured-heading">Featured Collections</h2>
<div id="featured-collections" class="cards-grid" aria-live="polite">
<!-- Populated by JS -->
</div>
</div>
</section>
<!-- Getting Started -->
<section class="getting-started">
<section class="getting-started" aria-labelledby="getting-started-heading">
<div class="container">
<h2>Getting Started</h2>
<h2 id="getting-started-heading">Getting Started</h2>
<div class="steps">
<div class="step">
<div class="step-number">1</div>
<div class="step-number" aria-hidden="true">1</div>
<h3>Browse</h3>
<p>Explore agents, prompts, instructions, and skills</p>
</div>
<div class="step">
<div class="step-number">2</div>
<div class="step-number" aria-hidden="true">2</div>
<h3>Preview</h3>
<p>Click any item to view its full content</p>
</div>
<div class="step">
<div class="step-number">3</div>
<div class="step-number" aria-hidden="true">3</div>
<h3>Install</h3>
<p>One-click install to VS Code or copy to clipboard</p>
</div>

View File

@@ -4,7 +4,7 @@ import Modal from '../components/Modal.astro';
---
<BaseLayout title="Instructions" description="Coding standards and best practices for GitHub Copilot" activeNav="instructions">
<main>
<main id="main-content">
<div class="page-header">
<div class="container">
<h1>📋 Instructions</h1>
@@ -15,20 +15,21 @@ import Modal from '../components/Modal.astro';
<div class="page-content">
<div class="container">
<div class="search-bar">
<label for="search-input" class="sr-only">Search instructions</label>
<input type="text" id="search-input" placeholder="Search instructions..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-extension">File Extension:</label>
<select id="filter-extension" multiple></select>
<select id="filter-extension" multiple aria-label="Filter by file extension"></select>
</div>
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count"></div>
<div class="resource-list" id="resource-list">
<div class="loading">Loading instructions...</div>
<div class="results-count" id="results-count" aria-live="polite"></div>
<div class="resource-list" id="resource-list" role="list">
<div class="loading" aria-live="polite">Loading instructions...</div>
</div>
</div>
</div>

View File

@@ -4,7 +4,7 @@ import Modal from '../components/Modal.astro';
---
<BaseLayout title="Prompts" description="Ready-to-use prompt templates for development tasks with GitHub Copilot" activeNav="prompts">
<main>
<main id="main-content">
<div class="page-header">
<div class="container">
<h1>🎯 Prompts</h1>
@@ -15,20 +15,21 @@ import Modal from '../components/Modal.astro';
<div class="page-content">
<div class="container">
<div class="search-bar">
<label for="search-input" class="sr-only">Search prompts</label>
<input type="text" id="search-input" placeholder="Search prompts..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-tool">Tool:</label>
<select id="filter-tool" multiple></select>
<select id="filter-tool" multiple aria-label="Filter by tool"></select>
</div>
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count"></div>
<div class="resource-list" id="resource-list">
<div class="loading">Loading prompts...</div>
<div class="results-count" id="results-count" aria-live="polite"></div>
<div class="resource-list" id="resource-list" role="list">
<div class="loading" aria-live="polite">Loading prompts...</div>
</div>
</div>
</div>

View File

@@ -5,7 +5,7 @@ const base = import.meta.env.BASE_URL;
---
<BaseLayout title="Samples" description="Code samples and examples for building with GitHub Copilot" activeNav="samples">
<main>
<main id="main-content">
<div class="page-header">
<div class="container">
<h1>📚 Samples</h1>
@@ -16,7 +16,7 @@ const base = import.meta.env.BASE_URL;
<div class="page-content">
<div class="container">
<div class="coming-soon">
<div class="coming-soon-icon">🚧</div>
<div class="coming-soon-icon" aria-hidden="true">🚧</div>
<h2>Coming Soon</h2>
<p>We're migrating code samples from the <a href="https://github.com/github/copilot-sdk/tree/main/cookbook" target="_blank" rel="noopener">Copilot SDK Cookbook</a> to this repository.</p>
<p>Check back soon for examples including:</p>

View File

@@ -4,7 +4,7 @@ import Modal from '../components/Modal.astro';
---
<BaseLayout title="Skills" description="Self-contained agent skills with instructions and bundled resources" activeNav="skills">
<main>
<main id="main-content">
<div class="page-header">
<div class="container">
<h1>⚡ Skills</h1>
@@ -15,13 +15,14 @@ import Modal from '../components/Modal.astro';
<div class="page-content">
<div class="container">
<div class="search-bar">
<label for="search-input" class="sr-only">Search skills</label>
<input type="text" id="search-input" placeholder="Search skills..." autocomplete="off">
</div>
<div class="filters-bar" id="filters-bar">
<div class="filter-group">
<label for="filter-category">Category:</label>
<select id="filter-category" multiple></select>
<select id="filter-category" multiple aria-label="Filter by category"></select>
</div>
<div class="filter-group">
<label class="checkbox-label">
@@ -32,9 +33,9 @@ import Modal from '../components/Modal.astro';
<button id="clear-filters" class="btn btn-secondary btn-small">Clear Filters</button>
</div>
<div class="results-count" id="results-count"></div>
<div class="resource-list" id="resource-list">
<div class="loading">Loading skills...</div>
<div class="results-count" id="results-count" aria-live="polite"></div>
<div class="resource-list" id="resource-list" role="list">
<div class="loading" aria-live="polite">Loading skills...</div>
</div>
</div>
</div>

View File

@@ -7,7 +7,7 @@ import BaseLayout from "../layouts/BaseLayout.astro";
description="MCP servers and developer tools for GitHub Copilot"
activeNav="tools"
>
<main>
<main id="main-content">
<div class="page-header">
<div class="container">
<h1>🔧 Tools</h1>
@@ -19,6 +19,7 @@ import BaseLayout from "../layouts/BaseLayout.astro";
<div class="container">
<div class="search-section">
<div class="search-bar">
<label for="search-input" class="sr-only">Search tools</label>
<input
type="text"
id="search-input"
@@ -27,17 +28,18 @@ import BaseLayout from "../layouts/BaseLayout.astro";
/>
</div>
<div class="filters">
<select id="filter-category" class="filter-select">
<label for="filter-category" class="sr-only">Filter by category</label>
<select id="filter-category" class="filter-select" aria-label="Filter by category">
<option value="">All Categories</option>
</select>
<button id="clear-filters" class="btn btn-secondary btn-small"
>Clear</button
>
</div>
<div id="results-count" class="results-count"></div>
<div id="results-count" class="results-count" aria-live="polite"></div>
</div>
<div id="tools-list"></div>
<div id="tools-list" role="list"></div>
<div class="coming-soon">
<h2>More Tools Coming Soon</h2>