Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
50 changes: 50 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ concurrency:
jobs:
checks:
runs-on: ubuntu-latest
# The a11y steps write a PR comment and push violation screenshots to the
# a11y-screenshots branch.
permissions:
contents: write
pull-requests: write
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
steps:
- uses: actions/checkout@v4

Expand Down Expand Up @@ -42,3 +49,46 @@ jobs:
- run: pnpm lint

- run: pnpm build

# The audit runs @storybook/test-runner, which drives Playwright Chromium
# headless (no display needed on CI). Install it once, scoped to
# @surfnet/curve-storybook-config which pins playwright, so both framework
# runs share one browser.
- name: Install Playwright Chromium

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hoe is de performance? Ik zou verwachten dat we in een CI-stap een headless browser gebruiken.

run: pnpm --filter @surfnet/curve-storybook-config exec playwright install --with-deps chromium

# Headless axe sweep of every story across all themes/modes. Fast: the
# test phase is a few seconds per framework once Storybook is built (the
# build-storybook step dominates). Report-only for now; flip to blocking by
# removing `continue-on-error`.
- name: Accessibility audit (WCAG 2.1 AA)
continue-on-error: true
run: pnpm test:a11y

- name: Upload a11y reports
if: always()
uses: actions/upload-artifact@v4
with:
name: a11y-reports
path: packages/*/.a11y-report/**
if-no-files-found: ignore

# Pushes violating-element screenshots to the `a11y-screenshots` branch
# so the PR comment below can embed them by raw.githubusercontent.com
# URL. PR-only: there's no PR to attach screenshots to on a push build.
- name: Publish a11y screenshots
if: always() && github.event_name == 'pull_request'
run: ./scripts/publish-a11y-screenshots.sh

# Summarise the JSON reports into .a11y-report/comment.md.
- name: Summarise a11y findings
if: always()
run: pnpm exec jiti scripts/a11y-comment.ts

# One sticky comment, updated in place.
- name: Comment a11y findings on PR
if: always() && github.event_name == 'pull_request'
uses: marocchino/sticky-pull-request-comment@v2
with:
header: a11y-audit
path: .a11y-report/comment.md
65 changes: 34 additions & 31 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
# dependencies
node_modules
.pnpm-store

# secrets
.env
.env.local

# build output
dist
storybook-static

# turbo
.turbo

# angular
.angular

# logs
*.log
npm-debug.log*
pnpm-debug.log*

# editor / os
.DS_Store
.vs
!.vscode
.vscode/*
!.vscode/extensions.json
!.vscode/mcp.json
.idea
# dependencies
node_modules
.pnpm-store

# secrets
.env
.env.local

# build output
dist
storybook-static

# accessibility audit reports
.a11y-report

# turbo
.turbo

# angular
.angular

# logs
*.log
npm-debug.log*
pnpm-debug.log*

# editor / os
.DS_Store
.vs
\!.vscode
.vscode/*
\!.vscode/extensions.json
\!.vscode/mcp.json
.idea
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"storybook": "turbo run storybook",
"build-storybook": "turbo run build-storybook",
"lint": "turbo run lint",
"test:a11y": "turbo run test:a11y:ci",
"format": "prettier --write \"**/*.{ts,tsx,js,mjs,cjs,json,md,css,html}\"",
"format:check": "prettier --check \"**/*.{ts,tsx,js,mjs,cjs,json,md,css,html}\"",
"changeset": "changeset",
Expand Down
2 changes: 2 additions & 0 deletions packages/angular/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
a11yParameters,
frameworkGlobalTypes,
frameworkSwitcher,
sharedParameters,
Expand All @@ -16,6 +17,7 @@ export default {
decorators: [frameworkSwitcher('angular'), themeSwitcher()],
parameters: {
...sharedParameters,
...a11yParameters,
// Must be a literal (Storybook reads it via static analysis, not
// execution). Keep in sync with packages/react/.storybook/preview.ts.
options: {
Expand Down
12 changes: 12 additions & 0 deletions packages/angular/.storybook/test-runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { TestRunnerConfig } from '@storybook/test-runner';

import { runStoryA11yAudit } from '@surfnet/curve-storybook-config/test-runner';

// Delegate to the shared audit so React and Angular stay in lockstep.
const config: TestRunnerConfig = {
async postVisit(page, context) {
await runStoryA11yAudit(page, context);
},
};

export default config;
9 changes: 8 additions & 1 deletion packages/angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
"lint": "ngc --noEmit -p tsconfig.json",
"storybook": "ng run angular:storybook",
"build-storybook": "ng run angular:build-storybook",
"fix-helm-imports": "jiti scripts/rewrite-helm-imports.ts"
"fix-helm-imports": "jiti scripts/rewrite-helm-imports.ts",
"storybook:serve": "http-server storybook-static -p 6007 --silent",
"test:a11y": "test-storybook --url http://127.0.0.1:6007 --testTimeout 180000",
"test:a11y:ci": "start-server-and-test storybook:serve http://127.0.0.1:6007 test:a11y"
},
"peerDependencies": {
"@angular/common": "^22.0.0",
Expand Down Expand Up @@ -55,15 +58,19 @@
"@storybook/addon-a11y": "10.4.5",
"@storybook/addon-docs": "10.4.5",
"@storybook/angular": "10.4.5",
"@storybook/test-runner": "0.24.4",
"@surfnet/curve-contracts": "workspace:*",
"@surfnet/curve-storybook-config": "workspace:*",
"@surfnet/curve-tokens": "workspace:*",
"@surfnet/curve-typescript-config": "workspace:*",
"@tailwindcss/cli": "4.3.1",
"@tailwindcss/postcss": "4.3.1",
"axe-playwright": "2.2.2",
"http-server": "14.1.1",
"jiti": "2.7.0",
"ng-packagr": "22.0.0",
"rxjs": "7.8.2",
"start-server-and-test": "3.0.11",
"storybook": "10.4.5",
"tailwindcss": "4.3.1",
"tw-animate-css": "1.4.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/react/.storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
a11yParameters,
frameworkGlobalTypes,
frameworkSwitcher,
sharedParameters,
Expand All @@ -19,6 +20,7 @@ export default {
decorators: [frameworkSwitcher('react'), themeSwitcher()],
parameters: {
...sharedParameters,
...a11yParameters,
// Force the React jsxDecorator to always serialize the rendered JSX for the
// "Show code" panel. Without this, a story with `render: () => (...)` (no
// `args` param) is treated as a non-args story, so Storybook prints the whole
Expand Down
12 changes: 12 additions & 0 deletions packages/react/.storybook/test-runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { TestRunnerConfig } from '@storybook/test-runner';

import { runStoryA11yAudit } from '@surfnet/curve-storybook-config/test-runner';

// Delegate to the shared audit so React and Angular stay in lockstep.
const config: TestRunnerConfig = {
async postVisit(page, context) {
await runStoryA11yAudit(page, context);
},
};

export default config;
9 changes: 8 additions & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
"dev": "vite build --watch",
"lint": "tsc --noEmit",
"storybook": "storybook dev -p 6006 --no-open",
"build-storybook": "storybook build"
"build-storybook": "storybook build",
"storybook:serve": "http-server storybook-static -p 6006 --silent",
"test:a11y": "test-storybook --testTimeout 180000",
"test:a11y:ci": "start-server-and-test storybook:serve http://127.0.0.1:6006 test:a11y"
},
"peerDependencies": {
"@phosphor-icons/react": "^2.0.0",
Expand All @@ -43,6 +46,7 @@
"@storybook/addon-a11y": "10.4.5",
"@storybook/addon-docs": "10.4.5",
"@storybook/react-vite": "10.4.5",
"@storybook/test-runner": "0.24.4",
"@surfnet/curve-contracts": "workspace:*",
"@surfnet/curve-storybook-config": "workspace:*",
"@surfnet/curve-tokens": "workspace:*",
Expand All @@ -52,10 +56,13 @@
"@types/react": "19.2.17",
"@types/react-dom": "19.2.3",
"@vitejs/plugin-react": "6.0.2",
"axe-playwright": "2.2.2",
"http-server": "14.1.1",
"react": "19.2.7",
"react-dom": "19.2.7",
"rollup-plugin-preserve-directives": "^0.4.0",
"shadcn": "4.11.0",
"start-server-and-test": "3.0.11",
"storybook": "10.4.5",
"tailwindcss": "4.3.1",
"tw-animate-css": "1.4.0",
Expand Down
11 changes: 10 additions & 1 deletion packages/storybook-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
"./manager": {
"types": "./dist/manager.d.ts",
"default": "./dist/manager.js"
},
"./test-runner": {
"types": "./dist/a11y-audit.d.ts",
"default": "./dist/a11y-audit.js"
}
},
"files": [
Expand All @@ -28,11 +32,16 @@
},
"dependencies": {
"@storybook/icons": "2.0.2",
"@surfnet/curve-tokens": "workspace:*"
"@surfnet/curve-tokens": "workspace:*",
"axe-playwright": "2.2.2"
},
"devDependencies": {
"@storybook/test-runner": "0.24.4",
"@surfnet/curve-typescript-config": "workspace:*",
"@types/react": "19.2.17",
"axe-core": "4.12.1",
"playwright": "1.61.1",
"playwright-core": "1.61.1",
"react": "19.2.7",
"storybook": "10.4.5",
"typescript": "6.0.3"
Expand Down
Loading
Loading