From 63cfed02d9a5cf169cd8ae20a25c35c249e46565 Mon Sep 17 00:00:00 2001
From: TypoGenie
Date: Thu, 19 Feb 2026 00:12:20 +0200
Subject: [PATCH] docs: add WCAG 2.2 AAA accessibility section to README
---
README.md | 97 ++++++++++++++++++++++++++++++++++++++++++++++-----
metadata.json | 5 ---
2 files changed, 89 insertions(+), 13 deletions(-)
delete mode 100644 metadata.json
diff --git a/README.md b/README.md
index f00cff3..a940ba8 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
-
+
@@ -31,6 +31,7 @@
+
@@ -41,6 +42,7 @@
✨ Features •
+ ♿ Accessibility •
🎨 Demo •
🚀 Quick Start •
📚 Docs •
@@ -83,6 +85,7 @@ In a world where document formatting tools are increasingly locked behind paywal
- **💾 Local Processing** - Your documents never leave your machine
- **🖥️ Native Desktop App** - Built with Tauri for Windows (Portable EXE)
- **📥 One-Click Export** - Clean `.docx` files ready for Microsoft Word
+- **♿ WCAG 2.2 AAA** - Full keyboard access, screen reader support, runtime contrast validation, reduced motion support
### 🏛️ Style Categories
@@ -115,6 +118,75 @@ Every style includes meticulously configured:
---
+## ♿ Accessibility
+
+TypoGenie targets **WCAG 2.2 AAA** conformance across the entire application - both the app interface and the documents it generates. Accessibility is enforced at runtime, not bolted on after the fact.
+
+### Visual & Perception
+
+| Feature | Detail |
+|---------|--------|
+| **Color Contrast** | All text meets 7:1 contrast ratio (AAA) against zinc-950 backgrounds. Template colors are auto-corrected at render time via `ensureContrast()` - large text (18pt+/14pt+ bold) enforces 4.5:1, body text enforces 7:1 |
+| **Focus Indicators** | 2px indigo focus ring at 80% opacity, visible on all dark backgrounds. Meets 3:1 contrast requirement for non-text UI |
+| **Reduced Motion** | Global CSS `prefers-reduced-motion` disables all animations and transitions. Framer Motion animations individually gated via `useReducedMotion()` hook |
+| **Forced Colors** | Windows High Contrast Mode supported via `@media (forced-colors: active)` rules |
+| **Zoom Support** | Root font size set to `100%` (not `px`) so browser zoom and text scaling work correctly. `overflow-x: hidden` (not `overflow: hidden`) allows content access at 200%+ zoom |
+| **Text Spacing** | Line-height enforced at minimum 1.5 for body text, 1.0 for headings. Justified text overridden to left-aligned at render time (WCAG 1.4.8) |
+
+### Keyboard Navigation
+
+| Feature | Detail |
+|---------|--------|
+| **Full Keyboard Access** | Every interactive element is reachable and operable via keyboard. Logo uses ``, not `` |
+| **Skip Navigation** | "Skip to main content" link in index.html, visible on focus |
+| **Style Card Listbox** | Cards implement ARIA listbox pattern (`role="listbox"`/`role="option"`) with arrow key navigation, Enter/Space selection, and `aria-selected` state |
+| **Modal Focus Trapping** | All three modals use native `
` element - focus trap, Escape to close, and focus restoration handled natively by the browser |
+| **Shortcut Scoping** | Single-character shortcuts (`?`/`/`) are scoped to non-input contexts so they don't intercept typing in search or other fields |
+| **Target Sizes** | All interactive controls meet 44x44px minimum touch/click target (WCAG 2.5.5 AAA) |
+| **Iframe Keyboard Safety** | Preview iframes set to `tabIndex={-1}` so keyboard focus doesn't get trapped in non-interactive content |
+
+### Screen Reader Support
+
+| Feature | Detail |
+|---------|--------|
+| **Landmarks** | ``, ``, ``, ``, `` |
+| **Live Regions** | Screen readers announce state transitions (upload/configure/generate/preview), search result counts, loading states, export success/failure |
+| **Semantic Markup** | Progress stepper uses `` with `aria-current="step"`. Keyboard shortcuts list uses `// `. Decorative elements marked `aria-hidden="true"` |
+| **Modal Accessibility** | All dialogs have `aria-labelledby` pointing to their heading. Export options use `/` for radio groups |
+| **Dynamic Labels** | Favorite button announces "Add/Remove [style name] from favorites" with `aria-pressed` state. Category and paper size filters expose `aria-pressed` toggle state |
+| **Accessible Names** | Every icon-only button has an `aria-label`. All decorative icons carry `aria-hidden="true"` |
+| **Error Handling** | Errors use `role="alert"` (no conflicting `aria-live`). File upload errors linked to dropzone via `aria-describedby`. No auto-dismissing error messages |
+| **Error Boundary** | Application-level `ErrorBoundary` component catches crashes and renders an accessible `role="alert"` error screen with a reload option |
+
+### Accessible Document Output
+
+The `.docx` files TypoGenie generates are also built with accessibility in mind:
+
+| Feature | Detail |
+|---------|--------|
+| **Document Metadata** | Every exported DOCX includes `title`, `description`, and `creator` properties for assistive technology |
+| **Heading Structure** | Semantic `HeadingLevel` preserved in both rendering modes (semantic and high-fidelity table layout) |
+| **Table Headers** | Rows containing `` elements are marked with `tableHeader: true` so screen readers can announce column/row headers |
+| **Image Placeholders** | ` ` elements in Markdown are converted to italic `[Image: alt text]` placeholders rather than silently dropped |
+| **Contrast-Safe Colors** | All template text colors are validated and auto-corrected against their backgrounds before being applied to the document |
+
+### Runtime Contrast Validation
+
+Template colors are never trusted blindly. At CSS generation time, every text/background color pair passes through `ensureContrast()`:
+
+```
+Template says text color = #555555 on background #1a1a1a
+→ contrastRatio("#555555", "#1a1a1a") = 2.8:1 (fails 7:1 AAA)
+→ ensureContrast() lightens to #9a9a9a = 7.1:1 (passes)
+→ Rendered color = #9a9a9a
+```
+
+This means all 165+ styles automatically meet WCAG AAA contrast requirements regardless of their original color definitions. The original aesthetic is preserved as closely as possible while guaranteeing readability.
+
+
+
+---
+
## 🎨 Demo
@@ -343,13 +415,21 @@ npm run tauri # Access Tauri CLI directly
typogenie/
├── 📁 src/ # Frontend source code (React)
│ ├── 📁 components/ # UI components
-│ │ ├── FileUpload.tsx # Drag-and-drop upload zone
-│ │ ├── StyleSelector.tsx # Style gallery
-│ │ └── Preview.tsx # Final preview & export
-│ ├── 📁 services/ # Logic
-│ │ ├── templateLoader.ts # Loads JSON templates via Rust
-│ │ └── templateRenderer.ts # Generates CSS/DOCX from JSON
+│ │ ├── ErrorBoundary.tsx # Accessible crash recovery screen
+│ │ ├── ExportOptionsModal.tsx # DOCX export options (native dialog)
+│ │ ├── FileUpload.tsx # Drag-and-drop upload zone
+│ │ ├── Preview.tsx # Final preview & export
+│ │ ├── StylePreviewModal.tsx # Full-page style preview (native dialog)
+│ │ └── StyleSelector.tsx # Style gallery with listbox pattern
│ ├── 📁 hooks/ # React hooks
+│ │ ├── useDialog.ts # Native management with focus restore
+│ │ └── ...
+│ ├── 📁 services/ # Logic
+│ │ ├── templateLoader.ts # Loads JSON templates via Rust
+│ │ └── templateRenderer.ts # Generates CSS/DOCX with contrast validation
+│ ├── 📁 utils/ # Utilities
+│ │ ├── contrastUtils.ts # WCAG contrast ratio validation
+│ │ └── docxConverter.ts # Accessible DOCX generation
│ └── 📄 App.tsx # Main application component
├── 📁 src-tauri/ # Tauri desktop app
│ ├── 📁 src/ # Rust backend code (filesystem access)
@@ -369,7 +449,8 @@ typogenie/
| **Framework** | React 19.2.4 | UI components & state management |
| **Language** | TypeScript 5.8.2 | Type safety & developer experience |
| **Build Tool** | Vite 6.2.0 | Fast development & optimized builds |
-| **Styling** | Tailwind CSS | Utility-first CSS |
+| **Styling** | Tailwind CSS 4 | Utility-first CSS |
+| **Animation** | Framer Motion (motion/react) | Transitions with reduced-motion support |
| **Icons** | Lucide React | Beautiful, consistent iconography |
| **Markdown** | marked 12.0.0 | Local Markdown parsing |
| **Documents** | docx 8.5.0 | Client-side DOCX generation |
diff --git a/metadata.json b/metadata.json
deleted file mode 100644
index a9449fd..0000000
--- a/metadata.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "name": "TypoGenie",
- "description": "Transform markdown into beautifully formatted Microsoft Word documents with professional typography styles.",
- "requestFramePermissions": []
-}