diff --git a/docs/ACCESSIBILITY_TESTING_CHECKLIST.md b/docs/ACCESSIBILITY_TESTING_CHECKLIST.md index 3106f973..5bebd959 100644 --- a/docs/ACCESSIBILITY_TESTING_CHECKLIST.md +++ b/docs/ACCESSIBILITY_TESTING_CHECKLIST.md @@ -1,7 +1,26 @@ -# Accessibility Testing Checklist - Issue #160 +# Accessibility Testing Checklist ## Overview -Use this checklist to verify that aria-describedby attributes are working correctly across all form components. +This checklist covers accessibility testing for form components (Issue #160) and icon-only buttons (Issue #158). + +## Issue #158: Icon-Only Buttons ARIA Labels + +### Components Fixed +- [x] ShareModal - Social share buttons +- [x] MobileBottomSheet - Snap point buttons +- [x] DrawingToolsPanel - Tool action buttons +- [x] NotificationCenter - Filter and close buttons +- [x] CreateProposalModal - Close button +- [x] PoolPositionRow - Liquidity action buttons + +### Testing Requirements +- [ ] All icon-only buttons have descriptive aria-label +- [ ] Toggle buttons have aria-pressed state +- [ ] Decorative icons have aria-hidden="true" +- [ ] Screen readers announce button purpose clearly +- [ ] Button labels are concise and descriptive + +## Issue #160: Form Error Announcements ## General Testing diff --git a/frontend/docs/ACCESSIBILITY_ARIA_LABELS.md b/frontend/docs/ACCESSIBILITY_ARIA_LABELS.md new file mode 100644 index 00000000..d020cf0e --- /dev/null +++ b/frontend/docs/ACCESSIBILITY_ARIA_LABELS.md @@ -0,0 +1,95 @@ +# ARIA Labels for Icon-Only Buttons + +## Overview + +This document outlines the accessibility improvements made to icon-only buttons throughout the application. All icon-only buttons now include descriptive `aria-label` attributes to ensure screen reader users can understand their purpose. + +## WCAG Compliance + +These changes address WCAG 2.1 Level A compliance, specifically: +- **1.1.1 Non-text Content**: All non-text content has a text alternative that serves the equivalent purpose +- **4.1.2 Name, Role, Value**: User interface components have names that can be programmatically determined + +## Components Updated + +### ShareModal.tsx +- Twitter share button: `aria-label="Share on Twitter"` +- Discord share button: `aria-label="Share on Discord"` +- Telegram share button: `aria-label="Share on Telegram"` +- Reddit share button: `aria-label="Share on Reddit"` + +### MobileBottomSheet.tsx +- Snap point buttons: `aria-label="Snap to position {n}"` with `aria-pressed` state +- Close button: Already had proper `aria-label="Close"` + +### DrawingToolsPanel.tsx +- Clear all button: `aria-label="Clear all drawings"` +- Remove drawing button: `aria-label="Remove {type} drawing"` +- Stop drawing button: `aria-label="Stop drawing"` +- Undo button: `aria-label="Undo last action"` +- Redo button: `aria-label="Redo last action"` + +### NotificationCenter.tsx +- Close button: `aria-label="Close notifications"` +- Filter buttons: + - All: `aria-label="Show all notifications"` with `aria-pressed` + - Unread: `aria-label="Show unread notifications"` with `aria-pressed` + - Read: `aria-label="Show read notifications"` with `aria-pressed` + +### CreateProposalModal.tsx +- Close button: `aria-label="Close modal"` + +### PoolPositionRow.tsx +- Add liquidity button: `aria-label="Add liquidity to pool"` +- Remove liquidity button: `aria-label="Remove liquidity from pool"` + +## Best Practices + +### When to Use aria-label + +Use `aria-label` when: +1. A button contains only an icon (no visible text) +2. A button contains only a symbol (×, +, −, etc.) +3. The visible text is not descriptive enough + +### When to Use aria-pressed + +Use `aria-pressed` for toggle buttons that have an on/off state: +```tsx + +``` + +### When to Use aria-hidden + +Use `aria-hidden="true"` on decorative icons within buttons that have text labels: +```tsx + +``` + +## Testing + +### Manual Testing +1. Use a screen reader (NVDA, JAWS, VoiceOver) to navigate the application +2. Tab through all interactive elements +3. Verify that each button announces its purpose clearly + +### Automated Testing +Run accessibility audits using: +- axe DevTools +- Lighthouse accessibility audit +- WAVE browser extension + +## Future Improvements + +1. Add keyboard shortcuts for common actions +2. Implement focus management for modals +3. Add live regions for dynamic content updates +4. Ensure all interactive elements have visible focus indicators diff --git a/frontend/src/components/CreateProposalModal.tsx b/frontend/src/components/CreateProposalModal.tsx index bb2b9825..c17f67c7 100644 --- a/frontend/src/components/CreateProposalModal.tsx +++ b/frontend/src/components/CreateProposalModal.tsx @@ -148,6 +148,7 @@ export function CreateProposalModal({ cursor: 'pointer', padding: '4px', }} + aria-label="Close modal" > × diff --git a/frontend/src/components/DrawingToolsPanel.tsx b/frontend/src/components/DrawingToolsPanel.tsx index f86111bc..11c02cc4 100644 --- a/frontend/src/components/DrawingToolsPanel.tsx +++ b/frontend/src/components/DrawingToolsPanel.tsx @@ -35,7 +35,7 @@ export function DrawingToolsPanel({

Drawing Tools

{tools.length > 0 && ( - )} @@ -98,6 +98,7 @@ export function DrawingToolsPanel({ e.stopPropagation(); onRemoveTool(tool.id); }} + aria-label={`Remove ${tool.type} drawing`} > × @@ -175,16 +176,16 @@ export function DrawingToolbar({ {isDrawing && (
- {onUndo && ( - )} {onRedo && ( - )} diff --git a/frontend/src/components/MobileBottomSheet.tsx b/frontend/src/components/MobileBottomSheet.tsx index b4dc1a55..a1f78011 100644 --- a/frontend/src/components/MobileBottomSheet.tsx +++ b/frontend/src/components/MobileBottomSheet.tsx @@ -85,6 +85,8 @@ export function MobileBottomSheet({ ? 'bg-blue-500' : 'bg-neutral-300 dark:bg-neutral-700' }`} + aria-label={`Snap to position ${index + 1}`} + aria-pressed={currentSnap === index} /> ))}
diff --git a/frontend/src/components/NotificationCenter.tsx b/frontend/src/components/NotificationCenter.tsx index d5b6fcb6..3c9842b6 100644 --- a/frontend/src/components/NotificationCenter.tsx +++ b/frontend/src/components/NotificationCenter.tsx @@ -82,6 +82,7 @@ export default function NotificationCenter({ @@ -100,6 +101,8 @@ export default function NotificationCenter({ ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }`} + aria-label="Show all notifications" + aria-pressed={filterStatus === 'all'} > All @@ -110,6 +113,8 @@ export default function NotificationCenter({ ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }`} + aria-label="Show unread notifications" + aria-pressed={filterStatus === 'unread'} > Unread @@ -120,6 +125,8 @@ export default function NotificationCenter({ ? 'bg-blue-600 text-white' : 'bg-gray-100 text-gray-700 hover:bg-gray-200' }`} + aria-label="Show read notifications" + aria-pressed={filterStatus === 'read'} > Read diff --git a/frontend/src/components/PoolPositionRow.tsx b/frontend/src/components/PoolPositionRow.tsx index ed039776..44bf7747 100644 --- a/frontend/src/components/PoolPositionRow.tsx +++ b/frontend/src/components/PoolPositionRow.tsx @@ -85,6 +85,7 @@ export function PoolPositionRow({ onClick={onAddLiquidity} className="px-3 py-1.5 text-xs font-medium text-emerald-400 bg-emerald-500/10 rounded-lg hover:bg-emerald-500/20 transition-colors" title="Add liquidity" + aria-label="Add liquidity to pool" > + @@ -94,6 +95,7 @@ export function PoolPositionRow({ onClick={onRemoveLiquidity} className="px-3 py-1.5 text-xs font-medium text-red-400 bg-red-500/10 rounded-lg hover:bg-red-500/20 transition-colors" title="Remove liquidity" + aria-label="Remove liquidity from pool" > − diff --git a/frontend/src/components/ShareModal.tsx b/frontend/src/components/ShareModal.tsx index 8271b934..8fd82746 100644 --- a/frontend/src/components/ShareModal.tsx +++ b/frontend/src/components/ShareModal.tsx @@ -113,6 +113,7 @@ export function ShareModal({