Add next-themes-powered light/dark/system theming with an accessible ThemeToggle in every header (home, upload, admin users, login, register, reset-password).
Add a skip-to-content link and <main id="main-content"> landmarks + correct heading hierarchy (h1) on every top-level route.
Convert custom modal viewers (PhotoViewerClient, PhotoViewer) into real dialogs: role="dialog", aria-modal, focus trap via new useFocusTrap hook.
Add role="alert"/role="status" live regions for errors, success messages, and loading spinners so screen readers announce dynamic content.
Fill in missing dark: variants for previously light-only text/border/background colors across search filters, dialogs, and the photo grid.
Tighten header vertical spacing (smaller logo/padding) on the home/upload/admin headers.
Test plan
npx eslint app components hooks --ext .ts,.tsx — no new errors/warnings vs. main (pre-existing any/unused-var issues untouched)
npx tsc --noEmit — clean
npm run build — production build succeeds
Manual smoke test in browser: toggle light/dark on each page, tab through skip link + photo viewer modal focus trap
## Summary
- Add `next-themes`-powered light/dark/system theming with an accessible `ThemeToggle` in every header (home, upload, admin users, login, register, reset-password).
- Add a skip-to-content link and `<main id="main-content">` landmarks + correct heading hierarchy (h1) on every top-level route.
- Convert custom modal viewers (`PhotoViewerClient`, `PhotoViewer`) into real dialogs: `role="dialog"`, `aria-modal`, focus trap via new `useFocusTrap` hook.
- Add `role="alert"`/`role="status"` live regions for errors, success messages, and loading spinners so screen readers announce dynamic content.
- Add missing `aria-label`s to icon-only buttons (close, edit, deactivate, collapse/expand filters).
- Fill in missing `dark:` variants for previously light-only text/border/background colors across search filters, dialogs, and the photo grid.
- Tighten header vertical spacing (smaller logo/padding) on the home/upload/admin headers.
## Test plan
- [x] `npx eslint app components hooks --ext .ts,.tsx` — no new errors/warnings vs. main (pre-existing `any`/unused-var issues untouched)
- [x] `npx tsc --noEmit` — clean
- [x] `npm run build` — production build succeeds
- [ ] Manual smoke test in browser: toggle light/dark on each page, tab through skip link + photo viewer modal focus trap
Add next-themes light/dark/system theming with an accessible toggle
in every header, and close out an a11y pass across the viewer app:
skip-to-content link, main landmarks and heading hierarchy on every
route, focus-trapped dialog semantics for the photo viewer modals,
aria-label/live-region coverage for dynamic messages and icon
buttons, and dark: variants for previously light-only colors.
ilia
merged commit 44f3d696e4 into dev2026-07-14 15:25:47 -05:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
next-themes-powered light/dark/system theming with an accessibleThemeTogglein every header (home, upload, admin users, login, register, reset-password).<main id="main-content">landmarks + correct heading hierarchy (h1) on every top-level route.PhotoViewerClient,PhotoViewer) into real dialogs:role="dialog",aria-modal, focus trap via newuseFocusTraphook.role="alert"/role="status"live regions for errors, success messages, and loading spinners so screen readers announce dynamic content.aria-labels to icon-only buttons (close, edit, deactivate, collapse/expand filters).dark:variants for previously light-only text/border/background colors across search filters, dialogs, and the photo grid.Test plan
npx eslint app components hooks --ext .ts,.tsx— no new errors/warnings vs. main (pre-existingany/unused-var issues untouched)npx tsc --noEmit— cleannpm run build— production build succeeds