VPAT 2.4 — WCAG 2.1 AA
Voluntary Product Accessibility Template — self-assessment. Independent third-party audit scheduled for 2026-Q3.
Product name: R2 Digital Library
Version / Date: Current production build, assessed April 29, 2026
Standards: WCAG 2.1 Levels A and AA · Section 508 (36 CFR Part 1194) · EN 301 549 V3.2.1
Evaluation methods: Automated (axe-core, Lighthouse, Pa11y), manual keyboard-only testing, NVDA + VoiceOver screen-reader testing, 200% zoom verification, reduced-motion / high-contrast mode verification.
Contact: accessibility@r2library.com
WCAG 2.1 Success Criteria
| Ref | Success Criterion | Level | Conformance | Remarks & Explanations |
|---|---|---|---|---|
| 1.1.1 | Non-text Content | A | Supports | All non-decorative images provide alt text. Decorative icons use aria-hidden="true". PDF covers include metadata-derived alt text. |
| 1.2.1 | Audio-only and Video-only (Prerecorded) | A | Not Applicable | Platform does not host audio-only or video-only content. Publisher-provided multimedia carries responsibility with the publisher. |
| 1.2.2 | Captions (Prerecorded) | A | Not Applicable | See 1.2.1. |
| 1.2.3 | Audio Description or Media Alternative | A | Not Applicable | See 1.2.1. |
| 1.3.1 | Info and Relationships | A | Supports | Semantic HTML throughout: headings, lists, labels, landmark regions. Data tables use proper thead/tbody/th scope. |
| 1.3.2 | Meaningful Sequence | A | Supports | DOM order matches visual order for all primary workflows. Tested with screen-reader virtual cursor. |
| 1.3.3 | Sensory Characteristics | A | Supports | Instructions do not rely solely on color, shape, or spatial position. "Click the red button" type copy is banned in code review. |
| 1.3.4 | Orientation | AA | Supports | Responsive design works in both portrait and landscape; no orientation lock. |
| 1.3.5 | Identify Input Purpose | AA | Supports | All common inputs carry appropriate autocomplete attributes (name, email, tel, organization, etc.). |
| 1.4.1 | Use of Color | A | Supports | Color is never the sole means of conveying information. Status badges pair color with icon + text label; form errors include text + icon + aria-invalid. |
| 1.4.2 | Audio Control | A | Not Applicable | No auto-playing audio or video. |
| 1.4.3 | Contrast (Minimum) | AA | Supports | All text meets 4.5:1 on default palette. Verified via automated contrast tooling on every page render; CI blocks regressions. |
| 1.4.4 | Resize Text | AA | Supports | Text resizes to 200% without loss of content or functionality. No fixed-height containers that clip resized text. |
| 1.4.5 | Images of Text | AA | Supports | Text is never rendered as images except in publisher-supplied book pages (content provenance); reader interface text is always live text. |
| 1.4.10 | Reflow | AA | Supports | Content reflows at 320 CSS pixel widths without horizontal scrolling. Reader chapter view reflows cleanly; fixed-layout PDFs maintain pan-and-zoom. |
| 1.4.11 | Non-text Contrast | AA | Supports | UI components and graphical objects meet 3:1 against adjacent colors. Focus indicators verified at 3:1. |
| 1.4.12 | Text Spacing | AA | Supports | Text spacing overrides (line-height 1.5, paragraph-spacing 2×, letter-spacing 0.12×, word-spacing 0.16×) do not break layout. |
| 1.4.13 | Content on Hover or Focus | AA | Supports | Tooltips and popovers are dismissible, hoverable, and persistent (don't disappear on focus move). |
| 2.1.1 | Keyboard | A | Supports | All functionality operable via keyboard. Reader pagination (arrow keys), TOC navigation, search, bookmarks, annotations all keyboard-reachable. |
| 2.1.2 | No Keyboard Trap | A | Partially Supports | Primary workflows have no keyboard traps. A small number of admin-only confirmation dialogs use native browser confirm() which behaves correctly but is not a proper focus-trapped modal; replacement in progress. |
| 2.1.4 | Character Key Shortcuts | A | Supports | Single-key shortcuts in the reader (/, +, -) are only active when the reader surface has focus; no platform-wide single-key shortcuts. |
| 2.2.1 | Timing Adjustable | A | Supports | No timed interactions except session timeouts, which display a warning and can be extended. |
| 2.2.2 | Pause, Stop, Hide | A | Supports | No auto-updating content that is not user-initiated. Toast notifications auto-dismiss on 6s but respect prefers-reduced-motion and can be manually dismissed. |
| 2.3.1 | Three Flashes or Below Threshold | A | Supports | No content flashes more than three times per second. |
| 2.4.1 | Bypass Blocks | A | Supports | Every page starts with a "Skip to main content" link (see apps/web/src/app/[locale]/(library)/layout.tsx). |
| 2.4.2 | Page Titled | A | Supports | Every page has a unique, descriptive title via Next.js Metadata API. |
| 2.4.3 | Focus Order | A | Supports | Focus order matches DOM order. No use of positive tabindex. |
| 2.4.4 | Link Purpose (In Context) | A | Supports | Link text + surrounding context convey purpose. No "click here" or "read more" without context. |
| 2.4.5 | Multiple Ways | AA | Supports | Content reachable via browse, search, A–Z index, publisher directory, journals index, disciplines, MeSH, and sitemap. |
| 2.4.6 | Headings and Labels | AA | Supports | Headings and form labels are descriptive and unique within their context. |
| 2.4.7 | Focus Visible | AA | Supports | All interactive elements have a visible focus indicator (2px ring at Level AA contrast). outline:none not used without a focus:ring replacement. |
| 2.5.1 | Pointer Gestures | A | Supports | No multi-point or path-based gestures required. Reader pagination is single-pointer or keyboard. |
| 2.5.2 | Pointer Cancellation | A | Supports | Destructive actions fire on mouseup, not mousedown; no functionality triggered solely on down-event. |
| 2.5.3 | Label in Name | A | Supports | Accessible name contains visible label text for all interactive controls. |
| 2.5.4 | Motion Actuation | A | Not Applicable | No functionality depends on device motion or user motion. |
| 3.1.1 | Language of Page | A | Supports | html lang attribute set per locale (en, es, fr, etc.) via next-intl middleware. |
| 3.1.2 | Language of Parts | AA | Supports | Inline language changes use lang attribute. Medical terminology (Latin, Greek roots in Tabers Dictionary) carries lang tags. |
| 3.2.1 | On Focus | A | Supports | No context change on focus alone. |
| 3.2.2 | On Input | A | Supports | No unexpected context change on input. Form submissions are explicit (button click or Enter on submit field). |
| 3.2.3 | Consistent Navigation | AA | Supports | Library, admin, publisher, and platform shells each have a consistent navigation order across their pages. |
| 3.2.4 | Consistent Identification | AA | Supports | Components with the same function are consistently identified across pages (e.g. "Save" is always labeled "Save"). |
| 3.3.1 | Error Identification | A | Supports | Form validation errors are identified in text, associated with the offending field via aria-describedby, and announced via role="alert". |
| 3.3.2 | Labels or Instructions | A | Supports | All form inputs have visible labels. Optional fields explicitly marked. Required fields indicated in label + via required attribute + aria-required. |
| 3.3.3 | Error Suggestion | AA | Supports | Validation errors include suggestions ("Password must be at least 8 characters", "Please enter a valid work email address"). |
| 3.3.4 | Error Prevention (Legal, Financial, Data) | AA | Supports | Destructive actions (access-policy changes, team removal, subscription cancellation) require typed-slug confirmation or a two-step flow. |
| 4.1.1 | Parsing | A | Supports | Valid HTML output enforced via React JSX; duplicate IDs prevented in component design. (Note: WCAG 2.2 removed this criterion; included for back-compat with evaluators.) |
| 4.1.2 | Name, Role, Value | A | Supports | All custom components (tabs, dialogs, disclosures) expose name, role, and value through ARIA or native elements. |
| 4.1.3 | Status Messages | AA | Supports | Status messages use role="status" (for non-urgent, e.g. toast confirmations) or role="alert" (for form validation errors + destructive-action warnings). |
Conformance summary
Of 48 WCAG 2.1 A + AA criteria evaluated on the primary patron workflows and administrative dashboards:
- 42 — Supports
- 1 — Partially Supports
- 5 — Not Applicable
"Partially Supports" remediation tickets are tracked in our internal accessibility backlog with target completion dates. We publish a revised VPAT after every release that clears or adds a remediation item.