Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 29 additions & 20 deletions .cursor/rules/coding.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,35 @@ alwaysApply: true

# Recipe for implementing tasks
Always follow the following recipe for implementing tasks:
1. Only start implementing a task after the user has explicitly told so.
2. Before starting coding, create a task planning document (.md) in the docs/task-planning folder.
3. The task planning document contains a table with three columns: tasks description, DoD (Definition of Done) and Status. Status is open, working, checking, review, complete. Initially all tasks are "open".
1. Open = the task hasn't been worked on.
2. Working = the task is currently being implemented.
3. Checking = the DoD of the tasks are being checked.
4. Review = the user is reviewing the result.
5. complete = the user has approved the result and the task is complete.
4. After creating the task planning document, let the user review the doc.
5. After the user has approved the task planning document, implement each task one after the other.
6. After implementing a task, check the criteria for DoD and report the result to the user.
7. If DoD is not met, fix the problem until DoD is met.
8. Before and after each task, update each task in the table with the right status.
9. After finishing implementing, perform all necessary tests and check if the DoD for this task is met.
10. Report on test results and DoD criteria and ask user if a PR should be submitted.
11. If the user approves submitting a PR, and before PR is submitted, the task is marked with "PR" in docs/project_plan.md.
12. After PR ist submitted, report to the user and wait for manual instructions.
13. The user will then review and merge the PR or ask for updates.
14. Pull the repo again to check if the PR has been merged.
15. After task is completed (PR merged), the task is marked with a checkmark in docs/project_plan.md. This change does not warrant a separate PR, it will be included in the next PR. Just do git add for the file. Delete the feature branch locally and remotely.
1. Task planning:
1. Only start implementing a task after the user has explicitly told so.
2. Before starting coding, create a task planning document (.md) in the docs/task-planning folder.
3. The task planning document contains a table with three columns: tasks description, DoD (Definition of Done) and Status. Status is open, working, checking, review, complete. Initially all tasks are "open".
- Open = the task hasn't been worked on.
- Working = the task is currently being implemented.
- Checking = the DoD of the tasks are being checked.
- Review = the user is reviewing the result.
- complete = the user has approved the result and the task is complete.
4. After creating the task planning document, let the user review the doc.
3. Task implementation:
1. Do this only after the user has approved the task planning document.
2. Implement each task in the task-planning document one after the other.
3. After implementing a task, check the criteria for DoD and report the result to the user.
4. If DoD is not met, fix the problem until DoD is met.
5. Before and after each task, update each task in the table with the right status.
6. After finishing implementing, perform all necessary tests and check if the DoD for this task is met.
7. Report on test results and DoD criteria and ask user if a PR should be submitted.
8. If the user approves submitting a PR, and before PR is submitted, the task is marked with "PR" in docs/project_plan.md.
4. PR submission:
1. Do this only after the user approves submitting a PR.
2. Create a temporary markdown file with the PR description.
3. Submit the PR, using the temporary markdown file.
4. After PR ist submitted, report to the user and wait for manual instructions.
5. The user will then review and merge the PR or ask for updates.
5. Post-PR cleanup:
1. Do this after the user confirms that the PR has been successfully merged.
2. Checkout develop and do `git pull` to update the branch with the merged PR.
3. After task is completed (PR merged), the task is marked with a checkmark in docs/project_plan.md. This change does not warrant a separate PR, it will be included in the next PR. Just do git add for the file. Delete the feature branch locally and remotely.

# Instructions to handle error situations:
- CI Pipeline fails:
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/a11y-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Accessibility Tests

on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]

jobs:
a11y-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'

- name: Install dependencies
run: pnpm install

- name: Install Playwright browsers
run: cd packages/ui-kit && npx playwright install --with-deps

- name: Run accessibility tests with Storybook
run: cd packages/ui-kit && pnpm test-storybook:ci
env:
CI: true
4 changes: 2 additions & 2 deletions docs/project_plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ A pragmatic breakdown into **four one‑week sprints** plus a preparatory **Spri
| 2.1 | Add NumberInput, Select, Checkbox, RadioGroup components. | Unit & a11y tests pass; form story displays all. | ✓ |
| 2.2 | Integrate **React Hook Form + Zod**; create `FormGrid` + `FormGroup`. | Story "Form Example" submits & reports validation errors in Storybook interaction test. | ✓ |
| 2.3 | Implement Zustand session store skeleton with dark‑mode flag. | Vitest verifies default state + setter actions. | ✓ |
| 2.4 | ESLint rule enforcing named `useEffect` & cleanup. | Failing example in test repo triggers lint error; real code passes. | PR |
| 2.5 | Extend CI to run axe‑core on all stories. | Pipeline fails if any new a11y violations introduced. | |
| 2.4 | ESLint rule enforcing named `useEffect` & cleanup. | Failing example in test repo triggers lint error; real code passes. | |
| 2.5 | Extend CI to run axe‑core on all stories. | Pipeline fails if any new a11y violations introduced. | PR |

---

Expand Down
44 changes: 44 additions & 0 deletions docs/task-planning/task-2.5-axe-core-ci.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Task 2.5 - Extend CI to run axe-core on all stories

## Overview

Task 2.5 involves extending the CI pipeline to run axe-core accessibility tests on all Storybook stories. The goal is to ensure that the pipeline fails if any new accessibility violations are introduced.

## Tasks

| Task Description | DoD (Definition of Done) | Status |
| ------------------------------------------------------------ | ----------------------------------------------------------- | -------- |
| Research how to run axe-core tests in CI | Documentation on chosen approach | Complete |
| Configure axe-core to test all stories in Storybook | axe-core tests run locally on all stories | Complete |
| Integrate axe-core tests into GitHub Actions workflow | CI workflow file updated with axe-core testing step | Complete |
| Ensure CI fails when accessibility violations are introduced | Test fails when a component with a11y violations is present | Complete |
| Document how to interpret and fix a11y issues | Documentation added for developers | Complete |

## Implementation Plan

1. Research methods for running axe-core tests in CI (Storybook addon vs standalone) ✅
2. Configure axe-core tests to run against all Storybook stories ✅
3. Update GitHub Actions workflow to include axe-core testing ✅
4. Create test cases to verify pipeline fails on a11y violations ✅
5. Add documentation about the a11y testing in CI ✅

## Implementation Notes

- We've implemented the axe-core accessibility testing in CI using the Storybook test runner
- A test component with intentional accessibility violations was created (`A11yTestButton`)
- We created a standalone test script (`scripts/test-a11y-violation.js`) to verify axe-core detection
- Manual verification confirms axe-core successfully detects accessibility violations:
```
┌─────────┬─────────────┬────────────┬──────────────────────────────────────────────────────────────────────────────┬───────┐
│ (index) │ id │ impact │ description │ nodes │
├─────────┼─────────────┼────────────┼──────────────────────────────────────────────────────────────────────────────┼───────┤
│ 0 │ 'image-alt' │ 'critical' │ 'Ensure <img> elements have alternative text or a role of none or presentation' │ 1 │
│ 1 │ 'region' │ 'moderate' │ 'Ensure all page content is contained by landmarks' │ 2 │
└─────────┴─────────────┴────────────┴──────────────────────────────────────────────────────────────────────────────┴───────┘
```
- The CI pipeline will fail when new accessibility violations are introduced, meeting the Definition of Done
- Documentation explaining how to interpret and fix a11y issues has been added to the `packages/ui-kit/docs/accessibility-testing.md` file

## Expected Outcome

After implementation, the CI pipeline will automatically test all Storybook stories for accessibility issues using axe-core. If any new accessibility violations are introduced, the pipeline will fail, alerting developers to fix the issues before merging.
2 changes: 1 addition & 1 deletion packages/ui-kit/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const preview: Preview = {
},
a11y: {
// axe-core configuration options
element: '#root',
element: '#storybook-root',
config: {},
disable: false,
},
Expand Down
44 changes: 44 additions & 0 deletions packages/ui-kit/.storybook/test-runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { TestRunnerConfig } from '@storybook/test-runner'
import { injectAxe, checkA11y } from 'axe-playwright'
import { getStoryContext } from '@storybook/test-runner'

const config: TestRunnerConfig = {
async preVisit(page, context) {
console.log(`Testing story: ${context.id}`);
await injectAxe(page)
},
async postVisit(page, context) {
// Get the story context so we can access parameters
const storyContext = await getStoryContext(page, context)

// Skip a11y tests if explicitly disabled for a story
if (storyContext.parameters?.a11y?.disable) {
return
}

// Configure axe with any story-level rules
const axeConfig = storyContext.parameters?.a11y?.config
if (axeConfig) {
await page.evaluate((config) => {
// Window object with axe property is provided by axe-playwright injection
window.axe.configure(config)
}, axeConfig)
}

// Use the element specified in parameters or default to #storybook-root
// The selector #storybook-root is more reliable than #root
const element = storyContext.parameters?.a11y?.element || '#storybook-root'

// Run the accessibility tests
await checkA11y(page, element, {
detailedReport: true,
detailedReportOptions: {
html: true,
},
// If any violations are found, the test will fail
includedImpacts: ['critical', 'serious', 'moderate', 'minor'],
})
},
}

export default config
132 changes: 132 additions & 0 deletions packages/ui-kit/docs/accessibility-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Accessibility Testing with axe-core

This document provides guidance on interpreting and fixing accessibility issues found by axe-core in our UI components.

## Accessibility Testing in CI

Our CI pipeline automatically runs accessibility tests on all Storybook stories using axe-core. If any accessibility violations are found, the CI build will fail. This helps us catch accessibility issues early in the development process.

## How To Run Accessibility Tests Locally

To run accessibility tests locally:

```bash
# Navigate to the ui-kit package
cd packages/ui-kit

# Build Storybook
pnpm build-storybook

# Run accessibility tests on all stories
pnpm test-storybook
```

## Understanding Accessibility Violations

When axe-core finds an accessibility violation, it will provide the following information:

- **Impact**: The severity of the violation (critical, serious, moderate, minor)
- **Rule ID**: A unique identifier for the rule that was violated
- **Description**: A description of the violation
- **Help URL**: A link to more information about the rule
- **Elements**: The HTML elements that violated the rule

## Common Issues and How to Fix Them

### Missing Alternative Text (image-alt)

**Issue**: Images must have alternative text for screen readers.

**Fix**: Add an `alt` attribute to all `<img>` elements:

```jsx
// Bad
<img src="image.jpg" />

// Good
<img src="image.jpg" alt="Description of the image" />

// For decorative images
<img src="decorative.jpg" alt="" />
```

### Insufficient Color Contrast (color-contrast)

**Issue**: Text must have sufficient contrast against its background.

**Fix**:

- Adjust text or background colors to meet WCAG 2.1 AA contrast requirements
- Use the DaisyUI/Tailwind color system which has been designed with contrast in mind
- For text elements, ensure a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text

### Missing Form Labels (label)

**Issue**: Form inputs must have associated labels.

**Fix**:

```jsx
// Bad
<input type="text" />

// Good
<label htmlFor="name">Name</label>
<input id="name" type="text" />

// Or using our FormField components which handle this automatically
<FormField name="name" label="Name">
<TextInput />
</FormField>
```

### Heading Hierarchy (heading-order)

**Issue**: Heading levels should increase by only one level at a time.

**Fix**: Follow proper heading hierarchy:

```jsx
<h1>Page Title</h1>
<h2>Section Title</h2>
<h3>Subsection Title</h3>
<!-- Not: <h5>Skipping levels</h5> -->
```

### ARIA Attributes (aria-\*)

**Issue**: Improper use of ARIA attributes.

**Fix**: Only use ARIA attributes when necessary and ensure they are used correctly. Our component library handles many ARIA attributes for you.

## Resources

- [axe-core Rules](https://github.com/dequelabs/axe-core/blob/master/doc/rule-descriptions.md)
- [WCAG 2.1 Guidelines](https://www.w3.org/TR/WCAG21/)
- [Web Accessibility Initiative (WAI)](https://www.w3.org/WAI/)

## Handling False Positives

In rare cases, you may encounter false positives. If you believe a violation is a false positive, you can:

1. Document why the violation is a false positive
2. Disable specific rules for a component in the story parameters:

```jsx
export const MyStory = {
parameters: {
a11y: {
config: {
rules: [
{
id: "rule-id-to-disable",
enabled: false,
},
],
},
},
},
};
```

Always provide a comment explaining why the rule is disabled.
8 changes: 7 additions & 1 deletion packages/ui-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
"test:coverage": "vitest run --coverage",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build",
"test-storybook": "test-storybook",
"test-storybook:ci": "node scripts/run-storybook-test.js",
"cy:open": "cypress open",
"cy:run": "cypress run",
"theme-screenshots": "cypress run --spec \"cypress/e2e/theme.cy.ts\"",
Expand Down Expand Up @@ -68,6 +70,7 @@
"@storybook/react": "^8.6.14",
"@storybook/react-vite": "^8.6.14",
"@storybook/test": "^8.6.14",
"@storybook/test-runner": "^0.22.0",
"@storybook/theming": "^8.6.14",
"@storybook/types": "^8.6.14",
"@testing-library/dom": "^10.0.0",
Expand All @@ -79,6 +82,8 @@
"@types/testing-library__react": "^10.2.0",
"@vitejs/plugin-react": "^4.4.1",
"autoprefixer": "^10.4.21",
"axe-playwright": "^2.1.0",
"concurrently": "^9.1.2",
"cypress": "^14.3.3",
"cypress-visual-regression": "^5.3.0",
"daisyui": "^5.0.35",
Expand All @@ -93,6 +98,7 @@
"tailwindcss": "^3.4.17",
"typescript-eslint": "^8.32.1",
"vite": "^5.4.19",
"vitest": "^1.6.1"
"vitest": "^1.6.1",
"wait-on": "^8.0.3"
}
}
Loading
Loading