feat: add dark mode and audit viewer-frontend accessibility
CI / skip-ci-check (pull_request) Successful in 4s
CI / docker-ci (pull_request) Successful in 6s
CI / secret-scan (pull_request) Successful in 11s

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.
This commit is contained in:
2026-07-14 16:24:51 -04:00
parent e54c60912c
commit c011c8078e
32 changed files with 371 additions and 146 deletions
+4 -4
View File
@@ -146,8 +146,8 @@ export function SearchContent({ people, tags }: SearchContentProps) {
{/* Results */}
<div className="lg:col-span-3">
{loading ? (
<div className="flex items-center justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-gray-400" />
<div role="status" aria-label="Loading photos" className="flex items-center justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-gray-400 dark:text-gray-500" />
</div>
) : (
<>
@@ -192,11 +192,11 @@ export function SearchContent({ people, tags }: SearchContentProps) {
</>
) : hasActiveFilters ? (
<div className="flex items-center justify-center py-12">
<p className="text-gray-500">No photos found matching your filters</p>
<p className="text-gray-500 dark:text-gray-400">No photos found matching your filters</p>
</div>
) : (
<div className="flex items-center justify-center py-12">
<p className="text-gray-500">Select filters to search photos</p>
<p className="text-gray-500 dark:text-gray-400">Select filters to search photos</p>
</div>
)}
</>
+3 -3
View File
@@ -97,7 +97,7 @@ export default async function SearchPage() {
]);
return (
<main className="w-full px-4 py-8">
<main id="main-content" className="w-full px-4 py-8">
<div className="mb-8">
<h1 className="text-4xl font-bold text-secondary dark:text-gray-50">
Search Photos
@@ -108,8 +108,8 @@ export default async function SearchPage() {
</div>
<Suspense fallback={
<div className="flex items-center justify-center py-12">
<div className="text-gray-500">Loading search...</div>
<div role="status" className="flex items-center justify-center py-12">
<div className="text-gray-500 dark:text-gray-400">Loading search...</div>
</div>
}>
<SearchContent people={people} tags={tags} />