From b47b3d2eb574b75f67569dcdc75bf4524c677e3e Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 17 May 2026 16:11:44 +0000 Subject: [PATCH] fix: resolve all 48 WCAG 2.2 AA accessibility issues Critical fixes: - Add aria-label to all unlabeled inputs/selects in draft dialogs (ParticipantSelectionDialog, TimeBankAdjustmentDialog, AvailableParticipantsSection) - Add role="dialog" + aria-modal + focus trap to ConnectionOverlay and AuthRecoveryOverlay - Add aria-live region and connection status announcement to ConnectionOverlay Serious fixes: - Add skip-to-content link in root.tsx with id="main-content" on
- Add aria-label to UserMenu trigger button - Add aria-describedby + role="alert" to all auth form error messages (login, register, onboarding, forgot-password, reset-password) - Replace emoji column headers in StandingsTable with aria-label + aria-hidden spans - Add aria-live="assertive" to "It's your turn" desktop and mobile on-clock indicators - Add aria-live="polite" to draft room countdown timer - Add pause button to SportTicker (WCAG 2.2.2); add aria-hidden to ticker content - Fix Footer text contrast (changed from 28% to text-muted-foreground) - Fix OvernightPauseSettings: add htmlFor/id pairs and role="radiogroup"+aria-checked to mode buttons - Fix DraftSetupSection: replace broken htmlFor with aria-label on date picker button - Add aria-label to PeopleSection owner and commissioner selects - Add labels to ScoringPresetPicker score inputs; add role="radiogroup"+aria-checked to preset buttons - Add role="radiogroup"+aria-checked to AutodraftSettings option buttons - Add accessible names, aria-current="step", and
    list semantics to WizardStepper Moderate fixes: - Add aria-controls to RecentPicksFeed toggle button; wrap picks list in aria-live region - Add role="tab"+aria-selected+aria-controls to mobile board sub-tabs + role="tabpanel" - Add role="radiogroup"+aria-checked to TimerModeSelector - Add aria-current="page" + aria-label to SettingsDesktopNav - Add aria-label="Admin navigation" to admin sidebar nav - Add scope="col" + to StandingsTable and ScoringTables - Add ARIA table roles (role="table/rowgroup/row/columnheader/rowheader/cell") to DraftSummaryView CSS grid Minor fixes: - Add aria-hidden="true" to decorative trend icons in StandingsTable - Add aria-hidden="true" to desktop column header labels row in AvailableParticipantsSection - Replace title with aria-label on all icon-only buttons (watchlist, queue) in AvailableParticipantsSection - Add aria-label to NotificationSettings switchOnly Switch - Add prefers-reduced-motion check to SlotMachineHeadline JS animation - Bump --muted-foreground from 55% to 62% opacity for improved contrast margin https://claude.ai/code/session_01JXajpFxhqLf8aPCncP81k3 --- app/app.css | 2 +- app/components/AutodraftSettings.tsx | 12 ++-- app/components/NotificationSettings.tsx | 1 + app/components/StandingsTable.tsx | 34 +++++----- app/components/UserMenu.tsx | 2 +- app/components/draft/AuthRecoveryOverlay.tsx | 40 ++++++++++- .../draft/AvailableParticipantsSection.tsx | 58 ++++++++-------- app/components/draft/ConnectionOverlay.tsx | 66 +++++++++++++++---- app/components/draft/DraftSummaryView.tsx | 21 ++++-- .../draft/ParticipantSelectionDialog.tsx | 5 ++ app/components/draft/RecentPicksFeed.tsx | 3 +- .../draft/TimeBankAdjustmentDialog.tsx | 9 ++- .../league/OvernightPauseSettings.tsx | 14 ++-- app/components/league/ScoringPresetPicker.tsx | 6 +- app/components/league/TimerModeSelector.tsx | 4 +- app/components/league/WizardStepper.tsx | 42 ++++++------ .../league/settings/DraftSetupSection.tsx | 5 +- .../league/settings/PeopleSection.tsx | 4 +- .../league/settings/SettingsNavigation.tsx | 5 +- app/components/marketing/Footer.tsx | 3 +- app/components/marketing/LandingPage.tsx | 23 ++++++- app/components/marketing/ScoringTables.tsx | 10 +-- app/root.tsx | 8 ++- app/routes/admin.tsx | 2 +- app/routes/forgot-password.tsx | 4 +- .../leagues/$leagueId.draft.$seasonId.tsx | 16 +++-- app/routes/login.tsx | 6 +- app/routes/onboarding.tsx | 5 +- app/routes/register.tsx | 8 +-- app/routes/reset-password.tsx | 4 +- 30 files changed, 289 insertions(+), 133 deletions(-) diff --git a/app/app.css b/app/app.css index 531d075..9bc1f29 100644 --- a/app/app.css +++ b/app/app.css @@ -69,7 +69,7 @@ html { --secondary: #1c1f26; --secondary-foreground: #ffffff; --muted: #1c1f26; - --muted-foreground: rgb(255 255 255 / 55%); + --muted-foreground: rgb(255 255 255 / 62%); --accent: #2ce1c1; --accent-foreground: #14171e; --destructive: oklch(0.65 0.22 25); diff --git a/app/components/AutodraftSettings.tsx b/app/components/AutodraftSettings.tsx index d033216..1587573 100644 --- a/app/components/AutodraftSettings.tsx +++ b/app/components/AutodraftSettings.tsx @@ -201,7 +201,7 @@ function AutodraftOptions({ const isDisabled = isMyTurn; return ( -
    +
    {OPTION_ORDER.map((state) => { const { label } = OPTIONS[state]; const isActive = localState === state; @@ -209,6 +209,8 @@ function AutodraftOptions({ ); @@ -417,7 +419,7 @@ export function AutodraftSettings({
    -
    +
    {OPTION_ORDER.map((state) => { const { label } = OPTIONS[state]; const isActive = localState === state; @@ -425,6 +427,8 @@ export function AutodraftSettings({ ); diff --git a/app/components/NotificationSettings.tsx b/app/components/NotificationSettings.tsx index 51d9225..3bf1d8f 100644 --- a/app/components/NotificationSettings.tsx +++ b/app/components/NotificationSettings.tsx @@ -28,6 +28,7 @@ export function NotificationSettings({ return ( <> 0) { return (
    - +
    ); } else if (change < 0) { return (
    - +
    ); } else { return (
    - +
    ); @@ -101,26 +101,26 @@ export function StandingsTable({ }; return ( - +
    - Rank - {showMovement && Change} - Team - Total Points + Rank + {showMovement && Change} + Team + Total Points {showPlacementBreakdown && ( <> - 🥇 - 🥈 - 🥉 - 4th - 5th - 6th - 7th - 8th + + + + 4th + 5th + 6th + 7th + 8th )} - Remaining + Remaining diff --git a/app/components/UserMenu.tsx b/app/components/UserMenu.tsx index 76763d6..7eed617 100644 --- a/app/components/UserMenu.tsx +++ b/app/components/UserMenu.tsx @@ -32,7 +32,7 @@ export function UserMenu({ return ( - {!isInQueue ? ( ) : ( )} {!isInQueue ? ( ) : ( )} +
  1. + +
  2. ); })} - -
    + + -
    + ); } diff --git a/app/components/league/settings/DraftSetupSection.tsx b/app/components/league/settings/DraftSetupSection.tsx index d56577e..e34b16a 100644 --- a/app/components/league/settings/DraftSetupSection.tsx +++ b/app/components/league/settings/DraftSetupSection.tsx @@ -122,11 +122,12 @@ export function DraftSetupSection({
    - +
    ))} diff --git a/app/components/marketing/Footer.tsx b/app/components/marketing/Footer.tsx index a50f889..06f977e 100644 --- a/app/components/marketing/Footer.tsx +++ b/app/components/marketing/Footer.tsx @@ -11,8 +11,7 @@ const FOOTER_LINKS = [ export function Footer() { return (
    © 2026 Brackt. All rights reserved.
    + - - + + @@ -29,10 +30,11 @@ export function QualifyingPointsTable({ className }: TableProps) { return (
    Scoring points by finish position
    FinishPointsFinishPoints
    + - - + + diff --git a/app/root.tsx b/app/root.tsx index d9dc04d..4ddd0d4 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -77,6 +77,12 @@ export function Layout({ children }: { children: React.ReactNode }) { + + Skip to main content + {children} @@ -103,7 +109,7 @@ export default function App({ loaderData }: Route.ComponentProps) { ) : ( <> -
    +
    diff --git a/app/routes/admin.tsx b/app/routes/admin.tsx index 1fb88f5..a7338f8 100644 --- a/app/routes/admin.tsx +++ b/app/routes/admin.tsx @@ -43,7 +43,7 @@ export default function AdminLayout() {

    Admin Panel

    -
    Qualifying points by major finish position
    Major FinishQualifying PointsMajor FinishQualifying Points