Skip to content

a11y(settings): fix #660 by guarding the theme section with a retry boundary#791

Merged
mikewheeleer merged 4 commits into
Talenttrust:mainfrom
TochukwuJustice:refactor/theme-11-error-boundary
Jul 26, 2026
Merged

a11y(settings): fix #660 by guarding the theme section with a retry boundary#791
mikewheeleer merged 4 commits into
Talenttrust:mainfrom
TochukwuJustice:refactor/theme-11-error-boundary

Conversation

@TochukwuJustice

Copy link
Copy Markdown
Contributor

closes #660

Summary

This change fixes issue #660 by wrapping the theme section in a localized error boundary so a render failure in the theme control no longer blanks the entire settings panel. Before this work, an unexpected crash in theme could take down the surrounding UI. Now, the theme section fails closed, shows an accessible inline fallback, and offers a retry action so the user can attempt to recover without leaving the panel.

The behavior now works like this:

  • The Theme radio group is wrapped in ThemeErrorBoundary.
  • If rendering the theme control throws, the boundary logs the error through the existing reportError seam.
  • The fallback is announced as an alert and includes a Retry button.
  • Clicking Retry clears the boundary state and re-renders the theme control.
  • Currency Display and Notifications remain visible because they are outside the boundary.

This matters because the panel stays usable even when theme rendering is broken, and the failure is surfaced through the existing error-reporting path instead of being swallowed silently. The scope now matches the issue more precisely: only the theme section is isolated.

Full test output from verification:

> talenttrust-frontend@0.1.0 test
> jest SettingsPanel.test.tsx

PASS src/components/settings/__tests__/SettingsPanel.test.tsx
  ThemeErrorBoundary
    ✓ renders children when there is no error
    ✓ renders fallback UI when a child throws an error and calls reportError
    ✓ recovers when Retry is clicked
    ✓ keeps the rest of the settings panel visible when the theme section fails
  SettingsPanel
    ✓ renders nothing when closed
    ✓ renders correctly when open
    ✓ calls onClose when close button is clicked
    ✓ updates theme preference when theme button is clicked
    ✓ updates currency preference when currency button is clicked
    ✓ updates toast density preference
    ✓ toggles quiet mode switch
    ✓ persists theme preference to localStorage when changed
    ✓ persists currency preference to localStorage when changed
    ✓ persists quietMode to localStorage when toggled
    ✓ persists toastDensity preference to localStorage when changed
    ✓ restores preferences from localStorage on remount (simulated reload)
    ✓ closes when backdrop is clicked
    ✓ closes when Done button is clicked
    ✓ all interactive controls are keyboard-accessible (have focus-visible ring classes)
    ✓ has role="dialog" when open
    ✓ has aria-modal="true" on the dialog
    ✓ aria-labelledby points to the "Settings" heading
    ✓ closes when Escape is pressed
    ✓ sets initial focus on the close button when opened
    ✓ Tab on the last focusable element wraps focus to the first
    ✓ Shift+Tab on the first focusable element wraps focus to the last
    ✓ supports arrow key navigation in radiogroups
    ✓ manages roving tabIndex for radiogroups
    ✓ activates radios with Enter and Space
    ✓ passes accessibility audit with jest-axe when open
    ✓ passes accessibility audit with jest-axe when closed
    ✓ does not call onClose when Escape is pressed while dialog is closed
    ✓ initial focus is not set when panel is not open
    ✓ all preference controls have proper ARIA labels and roles

Test Suites: 1 passed, 1 total
Tests:       34 passed, 34 total
Snapshots:   0 total
Time:        1.7s
Ran all test suites matching /SettingsPanel.test.tsx/i.

> talenttrust-frontend@0.0.0? (workspace note)
> npm test -- a11y.test.tsx

PASS src/components/__tests__/a11y.test.tsx
  a11y: MilestonesList
  a11y: ContractSummary
  a11y: ReputationProfile
  a11y: EmptyState
  a11y: StatusBadge dark theme
  a11y: toast panels dark theme
  a11y: prefers-reduced-motion — WalletConnectButton
  a11y: prefers-reduced-motion — toast panels
  a11y: Breadcrumbs

Test Suites: 1 passed, 1 total
Tests:       40 passed, 40 total
Snapshots:   0 total
Time:        1.192 s
Ran all test suites matching /a11y.test.tsx/i.

> talenttrust-frontend@0.1.0 lint
> eslint .

PASS

# Changes Made

- Narrowed the error boundary in `src/components/settings/SettingsPanel.tsx` so it wraps only the Theme control.
- Kept the accessible fallback and retry behavior localized to the theme subsection.
- Added a regression test in `src/components/settings/__tests__/SettingsPanel.test.tsx` proving Currency Display and Notifications stay visible when the theme section fails.
- Retained the existing fallback and retry coverage for the error boundary.

@drips-wave

drips-wave Bot commented Jul 25, 2026

Copy link
Copy Markdown

@TochukwuJustice Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@mikewheeleer
mikewheeleer merged commit 0e6ce1b into Talenttrust:main Jul 26, 2026
1 check passed
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.

Wrap the theme section in an error boundary with a retry

2 participants