diff --git a/docs/docs/features.md b/docs/docs/features.md
index 2ab0a2d76..29e8ca103 100644
--- a/docs/docs/features.md
+++ b/docs/docs/features.md
@@ -174,6 +174,7 @@ TestPlanIt is a comprehensive test management platform designed to help teams pl
- **Custom statuses** - Create statuses with custom icons and colors
- **Templates** - Create templates for consistent test case structure
- **User preferences** - Configure theme, locale, timezone, and date/time formats; preference selections are visible from the profile view as well as the editor
+- **Accessible theme** - Opt-in high-contrast theme tuned for WCAG 2.2 Level AA (stronger contrast, larger interactive targets, visible focus), selectable per user without affecting other themes
- **Configurations** - Author OS / browser / environment configurations scoped to projects, with an admin UX overhaul covering bulk assign and search
### Security & Compliance
diff --git a/docs/docs/user-guide/user-menu.md b/docs/docs/user-guide/user-menu.md
index 3fc89321c..ffd337c7f 100644
--- a/docs/docs/user-guide/user-menu.md
+++ b/docs/docs/user-guide/user-menu.md
@@ -14,7 +14,8 @@ Once opened, the menu displays:
1. **Your Name and Email**: Shown at the top for identification.
2. **View Profile**: Navigates you directly to your **[User Profile](./user-profile.md)** page.
3. **Theme**: Opens a sub-menu where you can select your preferred visual theme for the application.
- - Options include Light, Dark, System (matches your operating system setting), Green, Orange, and Purple.
+ - Options include Light, Dark, System (matches your operating system setting), Green, Orange, Purple, and **Accessible**.
+ - **Accessible** is a high-contrast theme tuned for accessibility (WCAG 2.2 AA): it strengthens text and border contrast, enlarges small interactive targets, and adds a clearly visible keyboard focus ring. Choose it if you rely on these aids — see [Accessibility](#accessibility) below.
- A checkmark indicates the currently active theme.
- Selecting a new theme saves the preference to your profile and reloads the application to apply the change.
4. **Language**: Opens a sub-menu to select the display language for the application interface.
@@ -22,3 +23,15 @@ Once opened, the menu displays:
- A checkmark indicates the currently active language.
- Selecting a new language saves the preference to your profile and reloads the application to apply the change.
5. **Sign Out**: Logs you out of your current session and redirects you to the Sign In page.
+
+## Accessibility
+
+TestPlanIt includes an opt-in **Accessible** theme designed to meet the [WCAG 2.2](https://www.w3.org/TR/WCAG22/) Level AA presentation requirements. It is one of the regular theme choices in the **Theme** sub-menu (and on your [User Profile](./user-profile.md) preferences), so you can turn it on or off at any time without affecting other users.
+
+Compared to the default themes, the Accessible theme:
+
+- **Increases contrast** for body text, secondary ("muted") text, and UI borders so content meets the minimum contrast ratio.
+- **Enlarges small interactive targets** (such as compact icon buttons and toggles) to at least the recommended minimum size.
+- **Adds a high-contrast keyboard focus ring** so the currently focused control is always clearly visible.
+
+Your selection is saved to your profile and persists across sessions and devices. The other themes are left unchanged, so teammates who prefer them are unaffected.
diff --git a/docs/docs/user-guide/user-profile.md b/docs/docs/user-guide/user-profile.md
index 710f088fe..dcfcbb320 100644
--- a/docs/docs/user-guide/user-profile.md
+++ b/docs/docs/user-guide/user-profile.md
@@ -63,7 +63,7 @@ When viewing your own profile, you can view and edit these preferences:
#### Display Preferences
-- **Theme**: Choose from Light, Dark, System, Green, Orange, or Purple themes (with color indicators)
+- **Theme**: Choose from Light, Dark, System, Green, Orange, Purple, or **Accessible** themes (with color indicators). The Accessible theme is a high-contrast option tuned for [WCAG 2.2](https://www.w3.org/TR/WCAG22/) Level AA — see [Accessibility](./user-menu.md#accessibility)
- **Locale**: Language preference (English, German, Spanish, French, Italian, Dutch, Polish, Portuguese, Turkish, Vietnamese, Russian, Chinese Simplified, Chinese Traditional, Japanese, Korean)
- **Items Per Page**: Number of items to show in paginated tables (10, 25, 50, 100)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 566809169..a09347ce1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1017,6 +1017,9 @@ importers:
specifier: ^4.4.3
version: 4.4.3
devDependencies:
+ '@axe-core/playwright':
+ specifier: ^4.11.3
+ version: 4.11.3(playwright-core@1.60.0)
'@babel/core':
specifier: ^7.29.7
version: 7.29.7
@@ -3318,6 +3321,11 @@ packages:
resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==}
engines: {node: '>=18.0.0'}
+ '@axe-core/playwright@4.11.3':
+ resolution: {integrity: sha512-h/kfksv4F0cVIDlKpT4700OehdRgpvuVskuQ2nb7/JmtWUXpe9ftHAPtwyXGvVSsa6SJ64A9ER7Zrzc/sIvC4w==}
+ peerDependencies:
+ playwright-core: '>= 1.0.0'
+
'@babel/code-frame@7.29.0':
resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
engines: {node: '>=6.9.0'}
@@ -10095,6 +10103,10 @@ packages:
resolution: {integrity: sha512-byD6KPdvo72y/wj2T/4zGEvvlis+PsZsn/yPS3pEO+sFpcrqRpX/TJCxvVaEsNeMrfQbCr7w163YqoD9IYwHXw==}
engines: {node: '>=4'}
+ axe-core@4.11.4:
+ resolution: {integrity: sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==}
+ engines: {node: '>=4'}
+
axios@1.16.1:
resolution: {integrity: sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==}
@@ -25600,6 +25612,11 @@ snapshots:
'@aws/lambda-invoke-store@0.2.4': {}
+ '@axe-core/playwright@4.11.3(playwright-core@1.60.0)':
+ dependencies:
+ axe-core: 4.11.4
+ playwright-core: 1.60.0
+
'@babel/code-frame@7.29.0':
dependencies:
'@babel/helper-validator-identifier': 7.28.5
@@ -34715,6 +34732,8 @@ snapshots:
axe-core@4.11.2: {}
+ axe-core@4.11.4: {}
+
axios@1.16.1:
dependencies:
follow-redirects: 1.16.0(debug@4.3.7)
diff --git a/testplanit/.gitignore b/testplanit/.gitignore
index e424fb52b..523eaf245 100644
--- a/testplanit/.gitignore
+++ b/testplanit/.gitignore
@@ -61,6 +61,12 @@ e2e/playwright-report/
e2e/test-results/
.env.e2e
+# Accessibility scan (e2e/a11y) — never commit results, seeded fixtures, or reports
+e2e/a11y/results/
+e2e/a11y/.a11y-fixtures.json
+e2e/a11y/playwright-report/
+e2e/a11y/test-results/
+
# DB backups
backups/
diff --git a/testplanit/app/[locale]/admin/app-config/columns.tsx b/testplanit/app/[locale]/admin/app-config/columns.tsx
index 58d2f063b..a8fac1195 100644
--- a/testplanit/app/[locale]/admin/app-config/columns.tsx
+++ b/testplanit/app/[locale]/admin/app-config/columns.tsx
@@ -84,6 +84,7 @@ export function getColumns(
variant="ghost"
className="px-2 py-1 h-auto"
data-testid="edit-config-button"
+ aria-label={t("actions.edit")}
onClick={() => onEditConfig?.(row.original)}
>