From 655038581ecc57e482bec226824292eebef4d02a Mon Sep 17 00:00:00 2001 From: Krusty Date: Sun, 8 Feb 2026 08:06:45 -0800 Subject: [PATCH] a11y: comprehensive accessibility review and fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add skip-to-main-content link for keyboard navigation (App.tsx) - Fix heading hierarchy: h2→h1 on Home and PriorityFocus pages - Add labels to form inputs: AddItemInput, SearchInput, RenameListDialog, ShareModal invite link - Add sr-only labels for screen readers on search and add-item inputs - Add role='search' to search container - Change search input type from 'text' to 'search' for semantics - Add role='dialog', aria-modal, aria-labelledby to RenameListDialog - Add aria-expanded to collapsible sections: CategoryHeader, ProvenanceSection, VerificationBadge - Add aria-label to toggle switches in Settings (dark mode, haptics, notifications) - Add aria-label to BatchOperations toolbar buttons (check, uncheck, delete, clear) - Add aria-label to ListCard links for screen reader context - Add aria-label to tag color picker buttons - Add aria-label to collaborator role selector - Add aria-label to ProvenanceInfo copy buttons - Add role='alert' and aria-live='assertive' to OfflineIndicator - Add id='main-content' to main element for skip link target --- src/App.tsx | 10 +++++++++- src/components/AddItemInput.tsx | 4 +++- src/components/BatchOperations.tsx | 4 ++++ src/components/ListCard.tsx | 1 + src/components/ProvenanceInfo.tsx | 2 ++ src/components/RenameListDialog.tsx | 7 ++++++- src/components/Settings.tsx | 3 +++ src/components/ShareModal.tsx | 3 ++- src/components/TagSelector.tsx | 1 + src/components/lists/CategoryHeader.tsx | 1 + src/components/offline/OfflineIndicator.tsx | 2 +- src/components/publish/VerificationBadge.tsx | 2 ++ src/components/sharing/CollaboratorList.tsx | 1 + src/components/ui/SearchInput.tsx | 6 ++++-- src/pages/Home.tsx | 4 ++-- src/pages/PriorityFocus.tsx | 4 ++-- 16 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index fa494ef..a373f19 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -32,6 +32,14 @@ function AuthenticatedLayout({ children }: { children: React.ReactNode }) { return (
+ {/* Skip to main content link */} + + Skip to main content + + {/* Header */}
@@ -88,7 +96,7 @@ function AuthenticatedLayout({ children }: { children: React.ReactNode }) {
{/* Main content */} -
+
{children}
diff --git a/src/components/AddItemInput.tsx b/src/components/AddItemInput.tsx index f92022f..1d8bc24 100644 --- a/src/components/AddItemInput.tsx +++ b/src/components/AddItemInput.tsx @@ -61,10 +61,12 @@ export const AddItemInput = forwardRef(func }; return ( -
+
+ setName(e.target.value)} diff --git a/src/components/BatchOperations.tsx b/src/components/BatchOperations.tsx index d2866ea..a8cfa39 100644 --- a/src/components/BatchOperations.tsx +++ b/src/components/BatchOperations.tsx @@ -109,6 +109,7 @@ export function BatchOperations({ disabled={isProcessing} className="p-2 hover:bg-gray-700 dark:hover:bg-gray-300 rounded-lg transition-colors disabled:opacity-50" title="Check all" + aria-label="Check all selected items" > @@ -120,6 +121,7 @@ export function BatchOperations({ disabled={isProcessing} className="p-2 hover:bg-gray-700 dark:hover:bg-gray-300 rounded-lg transition-colors disabled:opacity-50" title="Uncheck all" + aria-label="Uncheck all selected items" > @@ -134,6 +136,7 @@ export function BatchOperations({ disabled={isProcessing} className="p-2 text-red-400 hover:bg-red-900/30 rounded-lg transition-colors disabled:opacity-50" title="Delete all" + aria-label="Delete all selected items" > @@ -149,6 +152,7 @@ export function BatchOperations({ }} className="p-2 hover:bg-gray-700 dark:hover:bg-gray-300 rounded-lg transition-colors" title="Clear selection" + aria-label="Clear selection" > diff --git a/src/components/ListCard.tsx b/src/components/ListCard.tsx index da4164c..f51ec6e 100644 --- a/src/components/ListCard.tsx +++ b/src/components/ListCard.tsx @@ -53,6 +53,7 @@ export const ListCard = memo(function ListCard({ list, currentUserDid, showOwner to={`/list/${list._id}`} onClick={() => haptic('light')} className="group block bg-white dark:bg-gray-800 rounded-2xl shadow-lg hover:shadow-xl dark:shadow-gray-900/50 transition-all duration-200 p-5 card-hover border border-gray-100 dark:border-gray-700 hover:border-amber-200 dark:hover:border-amber-600" + aria-label={`Open list: ${list.name}`} >
{/* Emoji icon */} diff --git a/src/components/ProvenanceInfo.tsx b/src/components/ProvenanceInfo.tsx index 3709a54..4135e0b 100644 --- a/src/components/ProvenanceInfo.tsx +++ b/src/components/ProvenanceInfo.tsx @@ -128,6 +128,7 @@ function DidRow({ : "hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" }`} title={copied ? "Copied!" : "Copy full DID"} + aria-label={copied ? "Copied!" : `Copy ${label}`} > {copied ? ( @@ -178,6 +179,7 @@ function ProvenanceSection({
-

+

Rename list

+ setName(e.target.value)} diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx index 50d0a98..1823034 100644 --- a/src/components/Settings.tsx +++ b/src/components/Settings.tsx @@ -94,6 +94,7 @@ export function Settings({ onClose }: SettingsProps) { }`} role="switch" aria-checked={darkMode} + aria-label="Toggle dark mode" >
-