From 2f1cc61c2c33c59e97eab25f849a90723b125b20 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Tue, 20 Jan 2026 18:15:42 +0000 Subject: [PATCH] Add test IDs and accessibility to editor and preview components Third iteration of comprehensive accessibility improvements: - Added test IDs to CodeEditorSection (preview checkbox, editor containers, error message) - Added test IDs and roles to ReactPreview component (loading, error, unsupported states) - Enhanced preview components with proper ARIA labels and status roles - Added test IDs to demo feature cards with region role - Improved error states with data-testid for error messages - Added aria-label attributes to preview state containers Component updates: - CodeEditorSection: Enable preview checkbox, editor/preview containers, error display - ReactPreview: Loading state, error state, unsupported language state - DemoFeatureCards: Feature cards grid with region role - Preview state management: Added proper ARIA roles (status, alert) These additions enable comprehensive testing of: - Code editor workflows (editing, preview toggling, error states) - Component preview rendering and error handling - Different preview states (loading, error, unsupported) - Demo feature cards navigation and display Co-Authored-By: Claude Haiku 4.5 --- ACCESSIBILITY_IMPROVEMENTS.md | 357 ++++++++++++++++++ jest.setup.ts | 13 + src/components/demo/DemoFeatureCards.tsx | 13 +- .../snippet-editor/CodeEditorSection.tsx | 20 +- .../features/snippet-editor/ReactPreview.tsx | 32 +- 5 files changed, 419 insertions(+), 16 deletions(-) create mode 100644 ACCESSIBILITY_IMPROVEMENTS.md diff --git a/ACCESSIBILITY_IMPROVEMENTS.md b/ACCESSIBILITY_IMPROVEMENTS.md new file mode 100644 index 0000000..592a795 --- /dev/null +++ b/ACCESSIBILITY_IMPROVEMENTS.md @@ -0,0 +1,357 @@ +# Accessibility & Testing Improvements + +## Overview +This document summarizes all accessibility enhancements and data-testid attributes added to the CodeSnippet application. These improvements make the application more accessible to screen reader users and easier to test programmatically. + +--- + +## Navigation Components + +### Navigation.tsx +- **Added:** `aria-expanded` - Indicates navigation menu state +- **Added:** `aria-controls="navigation-sidebar"` - Links button to controlled element +- **Added:** `data-testid="navigation-toggle-btn"` - Test identifier for menu toggle +- **Added:** `aria-hidden="true"` to icon - Hides decorative icon from screen readers + +### NavigationSidebar.tsx +✅ **Already had:** `data-testid` attributes on overlay and sidebar +- **Added:** `id="navigation-sidebar"` - Enables aria-controls reference +- **Added:** `role="navigation"` - Explicit semantic role +- **Added:** `aria-label="Main navigation menu"` - Descriptive label +- **Navigation items:** `data-testid={`nav-link-${item.path.replace(/\//g, '-')}`}` for dynamic test IDs +- **Sidebar close button:** `data-testid="navigation-sidebar-close-btn"` + +### PageLayout.tsx +- **Added:** `data-testid="page-layout"` to main container +- **Added:** `data-testid="page-header"` to header element +- **Added:** `data-testid="logo-text"` to logo +- **Added:** `data-testid="main-content"` to main element +- **Added:** `aria-hidden="true"` to decorative grid-pattern + +--- + +## Snippet Manager Components + +### SnippetManagerRedux.tsx +- **Added:** `data-testid="snippet-manager"` to main container +- **Added:** `data-testid="snippet-manager-loading"` to loading state + +### SnippetToolbar.tsx +✅ **Already had:** Comprehensive data-testid and aria attributes +- **Enhanced:** Added `data-testid` for template menu items: + - `snippet-template-react-${template.id}` + - `snippet-template-python-${template.id}` + - `snippet-template-javascript-${template.id}` +- **Already present:** + - `data-testid="snippet-search-input"` with `aria-label` + - `data-testid="snippet-selection-mode-btn"` with `aria-pressed` + - `data-testid="snippet-create-menu-trigger"` + +### SnippetCard.tsx +✅ **Already had:** `data-testid={`snippet-card-${snippet.id}`}` and `role="article"` + +### SnippetCardActions.tsx +✅ **Already had:** Comprehensive data-testid attributes: +- `snippet-card-view-btn` +- `snippet-card-copy-btn` +- `snippet-card-edit-btn` +- `snippet-card-actions-menu` (three-dot menu) +- `snippet-card-move-submenu` +- `move-to-namespace-${namespace.id}` +- `snippet-card-delete-btn` +- All buttons have appropriate `aria-label` attributes + +### SelectionControls.tsx +- **Added:** `data-testid="selection-controls"` to main container +- **Added:** `data-testid="select-all-btn"` with `aria-label` +- **Added:** `data-testid="selection-count"` to count display +- **Added:** `data-testid="bulk-move-menu-trigger"` with `aria-label` +- **Added:** `data-testid="bulk-move-menu"` to menu container +- **Added:** `data-testid={`bulk-move-to-namespace-${namespace.id}`}` for menu items +- **Added:** `aria-hidden="true"` to folder icon + +### SnippetGrid.tsx +✅ **Already had:** `data-testid="snippet-grid"` with `role="region"` and `aria-label` + +### NamespaceSelector.tsx +✅ **Already had:** Comprehensive data-testid: +- `namespace-selector-trigger` +- `namespace-selector-content` +- `namespace-option-${namespace.id}` + +--- + +## Form Components + +### SnippetFormFields.tsx +✅ **Already had:** Excellent accessibility implementation: +- **Title input:** + - `data-testid="snippet-title-input"` + - `aria-invalid={!!errors.title}` + - `aria-describedby="title-error"` (when error present) +- **Language select:** + - `data-testid="snippet-language-select"` with `aria-label` + - `data-testid="snippet-language-options"` on content + - `data-testid={`language-option-${lang}`}` on items +- **Description textarea:** + - `data-testid="snippet-description-textarea"` + - `aria-label="Snippet description"` + +### SnippetDialog.tsx +✅ **Already had:** +- `data-testid="snippet-dialog"` on DialogContent +- `data-testid="snippet-dialog-cancel-btn"` +- `data-testid="snippet-dialog-save-btn"` + +### SnippetViewer.tsx +- **Added:** `data-testid="snippet-viewer-dialog"` on DialogContent + +### SnippetViewerHeader.tsx +- **Added:** `data-testid="snippet-viewer-toggle-preview-btn"` with `aria-pressed` and `aria-label` +- **Added:** `data-testid="snippet-viewer-copy-btn"` with descriptive `aria-label` +- **Added:** `data-testid="snippet-viewer-edit-btn"` with `aria-label` +- **Added:** `aria-hidden="true"` to all icons + +--- + +## UI Primitive Components + +### button.tsx +✅ **Passes through all props** - Supports data-testid and accessibility attributes + +### input.tsx +✅ **Passes through all props** - Supports data-testid and accessibility attributes + +### dialog.tsx +- **DialogOverlay:** + - **Added:** `aria-hidden="true"` - Hides scrim from accessibility tree + - **Added:** `data-testid="dialog-overlay"` - Test identifier +- **DialogContent close button:** + - **Enhanced:** `aria-label="Close dialog"` (more descriptive) + - **Added:** `data-testid="dialog-close-btn"` + +### sonner.tsx (Toast component) +- **Added:** `data-testid="toast-container"` to Toaster component +- **Added:** `position="bottom-right"` for consistent positioning +- ✅ Sonner library automatically manages `aria-live` and `role="status"` on toast notifications + +--- + +## Accessibility Patterns Implemented + +### ARIA Attributes +| Attribute | Component | Purpose | +|-----------|-----------|---------| +| `aria-label` | Multiple | Provides accessible name for buttons and regions | +| `aria-expanded` | Navigation toggle | Indicates menu open/closed state | +| `aria-pressed` | Toggle buttons | Indicates pressed state for toggles | +| `aria-hidden` | Decorative elements | Hides non-semantic elements from screen readers | +| `aria-controls` | Navigation button | Links trigger to controlled element | +| `aria-modal` | Dialog | Marks dialog as modal | +| `role="dialog"` | Dialog container | Semantic dialog role | +| `aria-describedby` | Form inputs | Links errors to input fields | +| `aria-invalid` | Form inputs | Marks invalid form fields | +| `aria-label` | Regions | Descriptive labels for landmark regions | + +### Semantic HTML +- ✅ `