Skip to content

Accessibility: audit findings needing design or product decisions #156

Description

@heyoub

A full accessibility pass over apps/web (every source file read; WCAG 2.1 AA + ARIA APG) produced 62 findings. The ARIA-correctness layer is already addressed in PR #154 and PR #155, and a follow-up PR covers the mechanical remainder. This issue holds the findings that are real WCAG failures but carry a visual, content, or product dimension that shouldn't be decided unilaterally by a volunteer — each needs a maintainer call (and, per the specops workflow, a spec touch where noted).


1. Green Volunteer CTA fails contrast — Serious (WCAG 1.4.3)

White on green-600 (#16a34a) ≈ 3.05:1; normal-size text needs 4.5:1. It's the site's primary CTA in three places. green-700 is borderline (≈ 4.5:1); green-800 passes comfortably. A one-class change — but it's the brand green, and there's no success button variant or green token, so this magic color is also a design-system gap.
AppHeader.tsx · Home.tsx:92 · Volunteer.tsx:37

2. Links distinguished by color alone, and the colors are nearly identical — Serious (WCAG 1.4.1)

--primary and --foreground are both near-black neutrals (≈ 1.4:1 against each other vs the 3:1 required when color is the only differentiator). Some screens add underline, many don't. Either underline inline links by default or give --primary a real hue — a theme decision.
index.css:53,58 · ~20 screens

3. Every route shares one document title — Serious (WCAG 2.4.2)

Nothing sets document.title per route; every page is "Code for Philly" to screen readers and tab-switchers. Needs a small per-route title convention (and a spec touch, since screens are spec-governed).
index.html:8 · App.tsx

4. Hero slideshow auto-advances with no pause control — Serious (WCAG 2.2.2)

aria-hidden hides it from AT, but the criterion is about motion in the viewport: auto-advancing (8s crossfades) needs a visible pause/stop affordance.
HeroSlideshow.tsx

5. Whole pages have no headings because CardTitle is a <div>Serious (WCAG 1.3.1 / 2.4.6)

All account-claim and password-reset pages are built from cards only, so they render zero headings and no <h1>. Fix is per-page heading placement (or a heading-level prop pattern), not necessarily changing the shadcn primitive.
ui/card.tsx:36 · pages/AccountClaim*.tsx · PasswordReset*.tsx

6. Blog/buzz images are unconditionally alt=\"\"Serious (WCAG 1.1.1)

Authors have no way to supply alt text for featured images. Needs a content-model decision: an alt field on posts/updates, or an explicit editorial policy that featured images are decorative.
BlogDetail.tsx:36 · BlogIndex.tsx:124 · ActivityCard.tsx:80

7. Client-side navigation never moves focus or announces the new page — Moderate (WCAG 2.4.3)

<main tabIndex={-1}> exists but nothing focuses it on route change. A small router-level focus/announce hook — worth pairing with the document-title work (item 3).
AppShell.tsx:24 · App.tsx

8. Filter/search result updates are silent — Moderate (WCAG 4.1.3)

Index screens re-render their lists after the debounce with no status announcement. A shared "N results" role=\"status\" line would cover them; copy and placement are design calls.
ProjectsIndex · PeopleIndex · HelpWantedIndex · TagsNamespace

9. Reduced-motion honored only by the hero's Ken Burns pan — Moderate

Spinners, sheet/dialog transitions, and scrollTo({behavior:'smooth'}) run regardless of prefers-reduced-motion. The usePrefersReducedMotion hook exists and is under-applied; a global @media (prefers-reduced-motion: reduce) block is the usual fix.
index.css · 5 screens' scrollTo · HeroSlideshow.tsx:70

10. Network-error banner says "Retry" but only dismisses — Moderate (spec↔code contradiction)

The spec (specs/behaviors/app-shell.md:162) prescribes [Retry], and the button's handler only calls clearError(). Surfaced during the ARIA pass and recorded in plans/aria-correctness.md follow-ups. Either the button should refetch or the spec's label should change — both need a spec edit first, so it's parked here rather than patched.
NetworkErrorBanner.tsx · specs/behaviors/app-shell.md:162


Happy to implement any of these once there's a direction — most are small once the decision is made.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions