# Accessibility Guide DocuElevate targets **WCAG 2.1 Level AA** compliance across all user-facing pages. This guide documents the accessibility standards, patterns, and practices used in the project. ## Table of Contents - [Standards Overview](#standards-overview) - [ARIA Patterns Used](#aria-patterns-used) - [Keyboard Navigation](#keyboard-navigation) - [Color and Contrast](#color-and-contrast) - [Forms and Inputs](#forms-and-inputs) - [Tables](#tables) - [Modals and Dialogs](#modals-and-dialogs) - [Dynamic Content](#dynamic-content) - [Images and Icons](#images-and-icons) - [Testing and Validation](#testing-and-validation) - [Developer Checklist](#developer-checklist) ## Standards Overview DocuElevate follows [WCAG 2.1 Level AA](https://www.w3.org/WAI/WCAG21/quickref/?currentsidebar=%23col_overview&levels=aaa) guidelines. The key principles are: | Principle | Description | |-----------|-------------| | **Perceivable** | Information and UI components must be presentable in ways all users can perceive | | **Operable** | UI components and navigation must be operable via keyboard and assistive technologies | | **Understandable** | Information and UI operation must be understandable | | **Robust** | Content must be robust enough for a wide variety of user agents and assistive technologies | ## ARIA Patterns Used ### Landmarks `base.html` provides the following landmark structure on every page: ```html
{% block content %}{% endblock %}
``` ### Navigation - Active page links use `aria-current="page"` - The admin dropdown uses `aria-haspopup="true"`, `aria-expanded`, `role="menu"`, and `role="menuitem"` - The mobile menu toggle has `aria-label="Toggle navigation menu"` and `aria-expanded` ### Decorative Icons Font Awesome icons that appear next to descriptive text must have `aria-hidden="true"`: ```html Settings ``` ## Keyboard Navigation ### Skip Link Every page inherits a skip-to-content link from `base.html` that becomes visible on keyboard focus: ```css .skip-link:focus { position: fixed; top: 0; left: 0; /* ... visible styles ... */ } ``` ### Focus Indicators Global `focus-visible` styles are defined in `frontend/static/styles.css`: ```css a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; } ``` > **Warning:** Never remove or suppress focus indicators with `outline: none` unless you provide an equally visible alternative. ### Interactive Custom Elements When using `
` or `` as interactive elements (avoid when possible), ensure: ```html
``` ## Color and Contrast ### Minimum Ratios (WCAG 1.4.3) | Text Type | Minimum Contrast Ratio | |-----------|----------------------| | Normal text (< 18pt) | 4.5:1 | | Large text (≥ 18pt or ≥ 14pt bold) | 3:1 | | UI components and graphical objects | 3:1 | ### Dark Mode Dark mode overrides in `styles.css` are verified for WCAG AA contrast ratios. When adding new color values: 1. Verify light mode contrast at [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) 2. Verify dark mode contrast for the corresponding dark override 3. Never rely on color alone — always pair with text, icons, or patterns ### Status Badges Status indicators use both color **and** text: ```html Completed Failed ``` ## Forms and Inputs ### Labels (WCAG 1.3.1, 3.3.2) Every form input **must** have an associated label: ```html ``` ### Error Messages (WCAG 3.3.1) Error messages must be announced to screen readers: ```html ``` ### Search Forms Use `role="search"` and proper labelling: ```html ``` ## Tables ### Required Structure (WCAG 1.3.1) ```html
Filename Size Status
document.pdf 1.2 MB Completed
``` ### Sortable Columns Add `aria-sort` to indicate the current sort state: ```html Filename ``` ## Modals and Dialogs ### Required Attributes (WCAG 4.1.2) ```html ``` ### Focus Management When opening a modal: 1. Move focus into the dialog (first focusable element or the dialog itself) 2. Trap focus within the dialog while open 3. Return focus to the trigger element when closed ## Dynamic Content ### Live Regions (WCAG 4.1.3) Content that updates dynamically must be announced to screen readers: ```html
``` | Attribute | Use When | |-----------|----------| | `aria-live="polite"` | Updates that don't require immediate attention (search results, progress) | | `aria-live="assertive"` | Critical updates that require immediate attention (errors) | | `role="status"` | Status information (equivalent to `aria-live="polite"`) | | `role="alert"` | Important messages that require immediate attention | ## Images and Icons ### Content Images ```html DocuElevate Logo ``` ### Decorative Images ```html ``` ### Icon-Only Buttons ```html ``` ### Icons with Adjacent Text ```html Upload ``` ## Testing and Validation ### Automated Checks (CI Pipeline) The CI pipeline runs `djlint` on every pull request: ```bash # Run locally before committing djlint frontend/templates/ --lint ``` Configuration is in `pyproject.toml` under `[tool.djlint]`. The linter enforces: | Rule | Description | |------|-------------| | H005 | `` tag must have `lang` attribute | | H013 | `` tag must have `alt` attribute | | H016 | Document must have `` tag | | H025 | Tag should not be an orphan | | H026 | Empty `id` and `class` attributes should be removed | ### Manual Testing For each new feature or UI change, verify: 1. **Keyboard navigation**: Tab through all interactive elements; confirm logical focus order 2. **Screen reader**: Test with a screen reader (VoiceOver on macOS, NVDA on Windows, Orca on Linux) 3. **Color contrast**: Check new color combinations with [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) 4. **Zoom**: Test at 200% zoom; ensure content remains usable 5. **Responsive**: Test at mobile viewport widths (320px, 375px) ### Browser Testing Tools - **Chrome DevTools Accessibility panel** — audit ARIA attributes and contrast - **axe DevTools** browser extension — automated WCAG scanning - **Lighthouse** — includes accessibility audit in Performance tab ## Developer Checklist Use this checklist when creating or modifying UI templates: - [ ] All images have appropriate `alt` attributes - [ ] All decorative icons have `aria-hidden="true"` - [ ] All icon-only buttons have `aria-label` - [ ] All form inputs have associated labels (via `for`/`id` or `aria-label`) - [ ] All tables have `aria-label` or `<caption>` and `scope` on headers - [ ] All modals have `role="dialog"`, `aria-modal="true"`, and `aria-labelledby` - [ ] Dynamic content areas have `aria-live="polite"` or appropriate role - [ ] Color contrast meets 4.5:1 for normal text, 3:1 for large text - [ ] All interactive elements are keyboard-accessible - [ ] Focus indicators are visible on all interactive elements - [ ] `djlint frontend/templates/ --lint` passes with zero errors - [ ] Page heading hierarchy is correct (h1 → h2 → h3, no skipped levels)