Skip to content

Fix/accessibility issues#582

Open
ckouder wants to merge 33 commits intomainfrom
fix/accessibility-issues
Open

Fix/accessibility issues#582
ckouder wants to merge 33 commits intomainfrom
fix/accessibility-issues

Conversation

@ckouder
Copy link
Contributor

@ckouder ckouder commented Mar 9, 2026

Summary

Comprehensive WCAG 2.1 AA accessibility fixes for Illinois Chat, addressing Service Request #2149553. WCAG 2.1 AA compliance is required for Illinois courses.

Contrast & Visual

  • Fixed code block header contrast in both light and dark modes
  • Improved "Members" label contrast in Access Control

ARIA & Semantic HTML

  • Added aria-label to all interactive elements (buttons, inputs, links, tables) across the app
  • Added <nav> landmarks with descriptive labels to GlobalHeader and Navbar
  • Added aria-label to code block download/copy buttons
  • Dynamic logo alt text using course name (e.g., "CS101 logo")
  • Added skip navigation link in _app.tsx
  • Added role and ARIA attributes to SVG elements
  • Fixed heading hierarchy (proper H1 on every page)
  • Added document titles and <main> landmarks to all pages

Keyboard Navigation

  • ProjectTable rows respond to Enter/Space with role="button" and tabIndex=0
  • SourcesSidebar: Escape closes panel, proper focus management prevents focus trapping
  • Message action buttons (copy, thumbs, retry) are keyboard-focusable
  • Scrollable regions made keyboard-accessible
  • Added listbox role and keyboard nav to PromptList
  • Added keyboard nav and aria-expanded to menu toggles
  • Added global focus-visible indicators

Bug Fixes

  • Clipboard paste (EmailListAccordion.tsx): preventDefault() was called before checking clipboard data, blocking paste on Chrome/macOS
  • Privacy status (ProjectTable.tsx): Now shows 3 distinct labels — "Public", "Logged-in Users", "Private" — based on both is_private and allow_logged_in_users

Other Fixes

  • Removed user-scalable=no from viewport meta tags
  • Used native disabled attribute instead of aria-disabled
  • Added labels to all form controls
  • Removed role="button" from <Link> and <Menu.Item> elements
  • Wrapped icon-only controls in <button> elements
  • Renamed "Share Chatbot" to "Sharing and Access"

Test Infrastructure

  • 13 new .a11y.test.tsx files with dedicated accessibility assertions
  • axe-audit.a11y.test.tsx: axe-core scans of 11 key components (~80 WCAG rules each)
  • GitHub Action (.github/workflows/a11y-on-pr.yml): runs npm run test:a11y on every PR
  • Added jest-axe and @types/jest-axe dev dependencies

Test Plan

  • npm run test:a11y — all accessibility tests pass
  • npx vitest run — no regressions
  • Tab through chat page — focus indicators visible on all interactive elements
  • Verify ProjectTable shows "Public", "Logged-in Users", "Private" correctly
  • Paste emails into admin/member input on Chrome/macOS
  • Screen reader spot-check with VoiceOver on the chat page

virakasprova and others added 29 commits March 9, 2026 12:18
Add role="img" and aria-hidden="true" to Spinner SVG. Add role="img"
with descriptive aria-labels to checkmark and error SVGs in ChatInput.
…, 7, 13)

- Change landing page h2 to h1 for proper heading hierarchy
- Replace invalid <p> inside heading with <span class="block">
- Change h4 "About Us" to h2 for proper nesting
- Add visually hidden H1 to chat page for screen readers
…sue 6)

- Add aria-label to sidebar open/close buttons
- Add aria-hidden to sidebar overlay div
- Wrap Search clear icon in a proper button element with aria-label
Add aria-label to Tools and Document Groups configuration tables
so screen readers can identify the purpose of each table.
Add aria-label to Search input, API Key input, and VariableModal
textarea so screen readers can identify each form control.
…, 20)

- Add role="listbox" and aria-label to prompt list container
- Add role="option", aria-selected, and tabIndex to list items
- Add onKeyDown (Enter/Space) and onFocus handlers for keyboard access
…sue 11)

Replace aria-disabled="true" with native HTML disabled attribute on
the admin dashboard Button in the sidebar for proper semantics.
Remove user-scalable=no from both landing page and chat page viewport
meta tags to allow pinch-to-zoom on mobile devices.
Add tabIndex={0}, role="region", and aria-label to scrollable
conversation list and chat messages containers so keyboard users
can scroll content.
Change <title> from "UIUC.chat" to "Illinois Chat" to match the
H1 element and provide a clear, descriptive page title.
Add 3px solid orange outline on :focus-visible for all elements to
ensure keyboard focus is clearly visible. Suppress outline on mouse
clicks via :focus:not(:focus-visible).
…ue 19)

Links should retain their default link role, not be marked as buttons.
Remove role="button" from all Link elements in GlobalHeader, Navbar,
and from Menu.Item elements in AuthMenu (which already have menuitem role).
- Add onKeyDown handler (Enter/Space) to hamburger menu div
- Add aria-expanded to hamburger menu and Burger component
- Enables keyboard users to open/close navigation menus
Wrap IconCheck and IconX in ClearConversations and Key components
with proper <button> elements and aria-labels so they are keyboard
accessible and announced by screen readers.
Add title attribute to the course name div in the sidebar so users
can see the full text on hover when it's truncated by line-clamp.
…uest #2149553)

Address 13 frontend accessibility issues for WCAG 2.1 AA compliance:

- Issue 1: Add explicit dark backgrounds to code blocks for contrast
- Issue 2: Replace opacity animation with explicit muted text colors in ShareSettingsModal
- Issue 3: Add aria-pressed to thumbs buttons, aria-live to assistant messages
- Issue 4: Use semantic <nav> landmarks in Navbar
- Issue 5: Add aria-label to code block download button
- Issue 7: Add skip navigation link and main-content targets
- Issue 8: Add keyboard navigation (Enter/Space) to project table rows
- Issue 9: Add high-contrast text selection styles for chat input
- Issue 10: Implement focus trap, Escape key, and focus restore in SourcesSidebar
- Issue 11: Add group-focus-within for keyboard-visible action buttons
- Issue 14: Fix Save button by removing empty onClick blocking form submission
- Issue 16: Refactor ProjectTable to useQuery for cache-synced privacy updates
- Issue 17: Rename "Share Chatbot" to "Sharing and Access"

Additional axe-core fixes:
- Fix color-contrast on faded text (darken --foreground-faded)
- Fix color-contrast on orange links over light card backgrounds
- Add underlines to inline links for non-color distinction
- Add role="button" to Avatar menu trigger for valid aria-expanded
…ks to all pages

Ensure every page passes axe-core document-title, page-has-heading-one,
landmark-one-main, and skip-link rules:

- Add id="main-content" to all <main> elements (skip-nav target)
- Add <Head><title> with "— Illinois Chat" suffix to pages missing it
- Add <h1> (sr-only where no visible heading exists) to all pages
- Fix PermissionGate, Dashboard, Explore, MakeNewCoursePage,
  MakeOldCoursePage, MakeQueryAnalysisPage, N8NPage, LLMsApiKeyInputForm
- Fix utility pages: CannotEditGPT4, CanViewOnlyCourse, CannotViewCourse,
  MainPageBackground, Maintenance, KeycloakProvider auth callback
Add aria-label attributes to 26+ unlabeled form inputs across the
codebase (Selects, TextInputs, Textareas, MultiSelects, Inputs) that
were failing Lighthouse's "label" audit. Also fix heading hierarchy
in Maintenance page (h2→h1, demote duplicate h1 to h2) and add
aria-label to ShareSettingsModal close button.
…nd additional WCAG fixes

Addresses remaining items from Service Request #2149553:
- Issue 1: Light/dark theme switching for code blocks (oneLight/oneDark)
- Issue 2: Members text contrast in ShareSettingsModal
- Issue 5: aria-labels on code block buttons
- Issue 9: Chat input text selection visibility
- Issue 11: Hover-only action buttons now visible on keyboard focus
- Issue 17: Rename "Share Chatbot" to "Sharing and Access"

Additional WCAG improvements:
- Form input labels across ingest forms and provider inputs
- Think tag hover colors toned down for less visual aggression
- Model selector keyboard accessible (Enter/Space)
- Sidebar settings button visibility fix (disabled attr vs aria-disabled)
- N8N/Tools page heading hierarchy, link contrast, aria fixes
- API page heading order and link underlines
- Privacy/Terms/Disclaimer pages: document titles and main landmarks
- Loading placeholder: title, h1, and main-content landmark
- Homepage link contrast (#b5390d) and underlines for distinguishability
- GlobalHeader and Navbar semantic improvements
@ckouder ckouder requested a review from lmarini March 9, 2026 17:25
@vercel
Copy link

vercel bot commented Mar 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
uiuc-chat-frontend Ready Ready Preview, Comment Mar 10, 2026 1:42pm

Request Review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements broad WCAG 2.1 AA accessibility improvements across the Illinois Chat Next.js frontend (landmarks, labels, keyboard navigation, focus visibility), and introduces a dedicated accessibility test suite + CI workflow to prevent regressions.

Changes:

  • Adds semantic landmarks/skip navigation, improved headings/titles, and comprehensive ARIA labeling across pages and components.
  • Improves keyboard accessibility (focus-visible styling, keyboard operability, focus management for sidebar/modal, keyboard nav for lists/rows).
  • Adds/updates accessibility-focused tests (incl. axe audits) and a PR GitHub Action to run them.

Reviewed changes

Copilot reviewed 97 out of 98 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/styles/globals.css Skip-link + global focus-visible styles
src/providers/KeycloakProvider.tsx Add main-content target + H1
src/pages/terms.tsx Add document title + text color
src/pages/privacy.tsx Add document title + text color
src/pages/index.tsx Viewport change + main landmark + heading fixes
src/pages/disclaimer.tsx Add document title
src/pages/api/home/home.tsx Title/viewport tweaks + main landmark + sr-only H1
src/pages/_app.tsx Global skip navigation link
src/pages/[course_name]/upload.tsx Title + main landmark + sr-only H1
src/pages/[course_name]/prompt.tsx Title + main landmark + sr-only H1
src/pages/[course_name]/api.tsx Title + main landmark (+ tabIndex) + sr-only H1
src/components/UIUC-Components/navbars/tests/GlobalHeader.a11y.test.tsx New nav landmark test
src/components/UIUC-Components/navbars/tests/ChatNavbar.test.tsx Update logo accessible name assertion
src/components/UIUC-Components/navbars/tests/ChatNavbar.a11y.test.tsx New ChatNavbar a11y tests
src/components/UIUC-Components/navbars/Navbar.tsx Use <nav>/<header> + labels + burger aria-expanded
src/components/UIUC-Components/navbars/GlobalHeader.tsx Remove incorrect roles; add aria-expanded + key handling
src/components/UIUC-Components/navbars/ChatNavbar.tsx Dynamic logo alt/label + formatting
src/components/UIUC-Components/navbars/AuthMenu.tsx Remove roles from Menu.Item; add target semantics
src/components/UIUC-Components/api-inputs/providers/WebLLMProviderInput.tsx Focus-visible styles + dimmed text tweak
src/components/UIUC-Components/api-inputs/providers/SambaNovaProviderInput.tsx Focus-visible styles on external link
src/components/UIUC-Components/api-inputs/providers/OpenAIProviderInput.tsx Focus-visible styles on external link
src/components/UIUC-Components/api-inputs/providers/OllamaProviderInput.tsx Focus-visible styles + dimmed text tweak
src/components/UIUC-Components/api-inputs/providers/NCSAHostedVLMProviderInput.tsx Focus-visible styles + dimmed text tweak
src/components/UIUC-Components/api-inputs/providers/NCSAHostedProviderInput.tsx Focus-visible styles + dimmed text tweak
src/components/UIUC-Components/api-inputs/providers/GeminiProviderInput.tsx Focus-visible styles on external link
src/components/UIUC-Components/api-inputs/providers/BedrockProviderInput.tsx Focus-visible styles on external link
src/components/UIUC-Components/api-inputs/providers/AzureProviderInput.tsx Focus-visible styles on external link
src/components/UIUC-Components/api-inputs/providers/AnthropicProviderInput.tsx Focus-visible styles on external link
src/components/UIUC-Components/api-inputs/LLMsApiKeyInputForm.tsx Title/main landmark + heading order + contrast tweaks
src/components/UIUC-Components/tests/UploadCard.test.tsx Accept renamed “Sharing and Access” label
src/components/UIUC-Components/tests/SourcesSidebar.a11y.test.tsx New sidebar a11y/focus tests
src/components/UIUC-Components/tests/ShareSettingsModal.a11y.test.tsx New modal title a11y test
src/components/UIUC-Components/tests/SetExampleQuestions.a11y.test.tsx New a11y regression test
src/components/UIUC-Components/tests/ProjectTable.test.tsx Privacy label cases test update
src/components/UIUC-Components/tests/ProjectTable.a11y.test.tsx New keyboard-accessible row test
src/components/UIUC-Components/WebsiteIngestForm.tsx Card keyboard activation + input aria-labels
src/components/UIUC-Components/WebScrape.tsx Input aria-labels + focus-visible styles
src/components/UIUC-Components/UploadCard.tsx Rename share button + add aria-labels
src/components/UIUC-Components/SupportedFileUploadTypes.tsx Contrast tweak (gray-500)
src/components/UIUC-Components/SourcesSidebar.tsx Escape close + focus trap + complementary landmark
src/components/UIUC-Components/ShareSettingsModal.tsx Focus trap + dialog semantics + cache invalidation
src/components/UIUC-Components/SetExampleQuestions.tsx Remove no-op onClick handler
src/components/UIUC-Components/PromptEditor.tsx aria-expanded + keyboard toggle + aria-labels
src/components/UIUC-Components/ProjectTable.tsx React Query fetch + keyboard row activation + privacy labels
src/components/UIUC-Components/ProjectFilesTable.tsx DOM patch for DataTable aria + focus-visible styles
src/components/UIUC-Components/PermissionGate.tsx Title + main landmark + H1
src/components/UIUC-Components/N8nWorkflowsTable.tsx Patch invalid aria + add switch aria-label
src/components/UIUC-Components/N8NPage.tsx Title/main landmark + heading order + aria-labels
src/components/UIUC-Components/MakeQueryAnalysisPage.tsx Title/main landmark + filter aria-labels
src/components/UIUC-Components/MakeOldCoursePage.tsx Title/main landmark + sr-only H1
src/components/UIUC-Components/MakeNewCoursePageSteps/HeaderStepNavigation.tsx Heading level correction
src/components/UIUC-Components/MakeNewCoursePage.tsx Title/main landmark + sr-only H1
src/components/UIUC-Components/Maintenance.tsx Main landmark + heading order
src/components/UIUC-Components/MainPageBackground.tsx Main landmark + sr-only H1 + loading title
src/components/UIUC-Components/MITIngestForm.tsx Card keyboard activation + input aria-label
src/components/UIUC-Components/GitHubIngestForm.tsx Card keyboard activation + input aria-label
src/components/UIUC-Components/Explore.tsx Title/main landmark + sr-only H1
src/components/UIUC-Components/EmailListAccordion.tsx Fix paste logic + keyboard focus visibility
src/components/UIUC-Components/DocGroupsTable.tsx Search input aria-label
src/components/UIUC-Components/Dashboard.tsx Title/main landmark + heading order
src/components/UIUC-Components/CourseraIngestForm.tsx Card keyboard activation + input aria-label
src/components/UIUC-Components/CanvasIngestForm.tsx Card keyboard activation + input aria-label
src/components/UIUC-Components/CannotViewCourse.tsx Main landmark + H1
src/components/UIUC-Components/CannotEditGPT4.tsx Main landmark + H1
src/components/UIUC-Components/CanViewOnlyCourse.tsx Main landmark + H1
src/components/UIUC-Components/BrandingForm.tsx Add greeting aria-label
src/components/UIUC-Components/ApiKeyManagament.tsx aria-expanded + focus-visible + aria-labels + underline links
src/components/UIUC-Components/APIRequestBuilder.tsx aria-labels + focus-visible + underline link
src/components/Spinner/Spinner.tsx SVG ARIA attributes
src/components/Sidebar/components/OpenCloseButton.tsx aria-labels + hide overlay from SR
src/components/Sidebar/Sidebar.tsx Tooltip title + scroll region landmark/label
src/components/Sidebar/NavigationSidebar.tsx <aside> landmark + contrast tweak
src/components/Settings/Key.tsx Replace icons with labeled buttons
src/components/Search/Search.tsx Add aria-label + clear button semantics
src/components/Markdown/tests/CodeBlock.a11y.test.tsx New CodeBlock a11y tests
src/components/Markdown/CodeBlock.tsx Dark/light theme switching + download aria-label
src/components/Layout/SettingsLayout.tsx Wrapper semantics adjustment
src/components/Dialog.tsx Close button focus-visible + DOM order tweak
src/components/Chatbar/components/tests/Conversation.a11y.test.tsx New conversation a11y tests
src/components/Chatbar/components/ClearConversations.tsx Replace icons with labeled buttons
src/components/Chat/tests/MessageActions.a11y.test.tsx New MessageActions a11y tests
src/components/Chat/tests/ChatMessage.a11y.test.tsx New live-region a11y test
src/components/Chat/tests/ChatLoader.a11y.test.tsx New ChatLoader a11y test
src/components/Chat/tests/ChatInput.a11y.test.tsx New ChatInput a11y tests
src/components/Chat/VariableModal.tsx Add textarea aria-label
src/components/Chat/ToolsItem.tsx Add input/table aria-labels
src/components/Chat/PromptList.tsx listbox/option roles + keyboard selection
src/components/Chat/ModelSelect.tsx Avoid throwing on unknown model type + aria-label
src/components/Chat/MessageActions.tsx aria-pressed + focus-within visibility
src/components/Chat/DocumentGroupsItem.tsx Add input/table aria-labels
src/components/Chat/ChatMessage.tsx Add aria-live for streaming region
src/components/Chat/ChatInput.tsx SVG roles/labels + focus-visible + keyboard handler
src/components/Chat/Chat.tsx Make messages area a labeled region
src/tests/axe-audit.a11y.test.tsx Comprehensive axe audit test suite
package.json Add test:a11y script + deps
package-lock.json Lockfile updates for new deps
CLAUDE.md Repo dev/testing guidance (Claude)
.github/workflows/a11y-on-pr.yml Run a11y tests on PRs

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants