Skip to content
Open
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
37 changes: 37 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,43 @@ yarn storybook # Primary development environment
- **Auto-cleanup**: Merged PR environments cleaned from S3 after 14 days or immediately after merging to dev branch (dev is main branch for this repo)
- **Slack integration**: `#prd-uds` and `#prdfam-uds-ci` channels for alerts

## Storybook MCP

This monorepo has Storybook MCP servers available for all component packages. When doing UI development, always use the MCP tools to find and reuse existing components before creating new ones.

### Available MCP servers

Each package runs its own Storybook dev server with an MCP endpoint. Start the relevant Storybook first, then use the corresponding MCP toolset:

| Package | Storybook command | MCP endpoint |
|---|---|---|
| `unity-react-core` | `cd packages/unity-react-core && yarn storybook` | `http://localhost:9200/mcp` |
| `unity-bootstrap-theme` | `cd packages/unity-bootstrap-theme && yarn storybook` | `http://localhost:9000/mcp` |
| `app-degree-pages` | `cd packages/app-degree-pages && yarn storybook` | `http://localhost:9010/mcp` |
| `app-rfi` | `cd packages/app-rfi && yarn storybook` | `http://localhost:9020/mcp` |
| `app-webdir-ui` | `cd packages/app-webdir-ui && yarn storybook` | `http://localhost:9030/mcp` |
| `component-events` | `cd packages/component-events && yarn storybook` | `http://localhost:9060/mcp` |
| `component-header-footer` | `cd packages/component-header-footer && yarn storybook` | `http://localhost:9080/mcp` |
| `component-news` | `cd packages/component-news && yarn storybook` | `http://localhost:9090/mcp` |

### Workflow

1. **Before building any UI**, use `list-all-documentation` on the relevant MCP server to discover available components.
2. **Before using a component**, call `get-documentation` to understand its props, variants, and usage patterns.
3. **After generating UI**, use `get-storybook-story-instructions` and write stories so the work can be previewed and tested.
4. **Run tests** using `run-story-tests` to validate interaction behavior and accessibility. Fix any failures before considering the task done.
5. **Preview work** using `preview-stories` to show live story renders inline.

### Key conventions for this codebase

- Components live in `packages/unity-react-core/src/components/` — this is the foundational library. Always check here first.
- Styles come from `unity-bootstrap-theme` (Bootstrap 5 + ASU brand tokens). Use Bootstrap utility classes before writing custom CSS.
- There are lots of components that arent yet in `packages/unity-react-core/src/components/`, also check `packages/unity-bootstrap-theme/stories/` for components that aren't in `packages/unity-react-core/src/components/`.
- The exception is `component-header-footer`, which uses styled-components and does not depend on the theme.
- All components use JSDoc TypeScript comments for prop documentation — these are surfaced in the MCP docs toolset.
- Always prefer typescript when creating any new components or updating any components in unity-react-core. Refactor only javascript files you modify in unity-react-core to typescript when you have to modify them but always ask user and let them know that this should be udpated to Typescript if they are modifying a javascript file in unity-react-core.
- Google Analytics events use `trackGAEvent` / `GaEventWrapper` — preserve these when modifying existing components.

## Key Files for Understanding Context
- `/packages/unity-react-core/src/components/` - Core React component patterns
- `/packages/unity-bootstrap-theme/src/` - Theme structure (CSS/SCSS + JS)
Expand Down
4 changes: 4 additions & 0 deletions .storybook-config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ const favicon = `

import { fileURLToPath } from "url";

export function addons() {
return ["@storybook/addon-mcp"];
}

export function previewAnnotations(entry = []) {
return [...entry, fileURLToPath(import.meta.resolve('./preset/preview.js'))];
}
Expand Down
36 changes: 36 additions & 0 deletions .vscode/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"servers": {
"asu-unity-react-core": {
"type": "http",
"url": "http://localhost:9200/mcp"
},
"asu-unity-bootstrap-theme": {
"type": "http",
"url": "http://localhost:9000/mcp"
},
"asu-app-degree-pages": {
"type": "http",
"url": "http://localhost:9010/mcp"
},
"asu-app-rfi": {
"type": "http",
"url": "http://localhost:9020/mcp"
},
"asu-app-webdir-ui": {
"type": "http",
"url": "http://localhost:9030/mcp"
},
"asu-component-events": {
"type": "http",
"url": "http://localhost:9060/mcp"
},
"asu-component-header-footer": {
"type": "http",
"url": "http://localhost:9080/mcp"
},
"asu-component-news": {
"type": "http",
"url": "http://localhost:9090/mcp"
}
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@siteimprove/alfa-playwright": "^0.78.1",
"@siteimprove/alfa-test-utils": "^0.78.1",
"@storybook/addon-docs": "^10.0.0",
"@storybook/addon-mcp": "^0.6.0",
"@storybook/react": "^10.0.0",
"@types/node": "^20.0.0",
"@types/react-dom": "^18.3.0",
Expand Down
155 changes: 154 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7562,7 +7562,7 @@ __metadata:
languageName: node
linkType: hard

"@standard-schema/spec@npm:^1.1.0":
"@standard-schema/spec@npm:^1.0.0, @standard-schema/spec@npm:^1.1.0":
version: 1.1.0
resolution: "@standard-schema/spec@npm:1.1.0"
checksum: 10c0/d90f55acde4b2deb983529c87e8025fa693de1a5e8b49ecc6eb84d1fd96328add0e03d7d551442156c7432fd78165b2c26ff561b970a9a881f046abb78d6a526
Expand Down Expand Up @@ -7598,6 +7598,26 @@ __metadata:
languageName: node
linkType: hard

"@storybook/addon-mcp@npm:^0.6.0":
version: 0.6.0
resolution: "@storybook/addon-mcp@npm:0.6.0"
dependencies:
"@storybook/mcp": "npm:0.7.0"
"@tmcp/adapter-valibot": "npm:^0.1.5"
"@tmcp/transport-http": "npm:^0.8.5"
picoquery: "npm:^2.5.0"
tmcp: "npm:^1.19.3"
valibot: "npm:1.2.0"
peerDependencies:
"@storybook/addon-vitest": ^0.0.0-0 || ^9.1.16 || ^10.0.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 || ^10.4.0-0
storybook: ^0.0.0-0 || ^9.1.16 || ^10.0.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 || ^10.4.0-0
peerDependenciesMeta:
"@storybook/addon-vitest":
optional: true
checksum: 10c0/f1edf6edd3ee242a54f3fb6cfb967a71504cca3ae160b43012d9d25d5485ad521b10d382010732428714ba58ad691c6638ec0a1393f7d16b0e736221f8ded8c0
languageName: node
linkType: hard

"@storybook/builder-vite@npm:10.3.3":
version: 10.3.3
resolution: "@storybook/builder-vite@npm:10.3.3"
Expand Down Expand Up @@ -7652,6 +7672,18 @@ __metadata:
languageName: node
linkType: hard

"@storybook/mcp@npm:0.7.0":
version: 0.7.0
resolution: "@storybook/mcp@npm:0.7.0"
dependencies:
"@tmcp/adapter-valibot": "npm:^0.1.5"
"@tmcp/transport-http": "npm:^0.8.5"
tmcp: "npm:^1.19.3"
valibot: "npm:1.2.0"
checksum: 10c0/56c90e597684e55e40451da47fc41e581d21365f405990c3cfbaaf8a19b71da17ede83399ed1524c6a1726050b0e0ba55474de5344cdeefe0cf9045faccb92b8
languageName: node
linkType: hard

"@storybook/react-dom-shim@npm:10.3.3":
version: 10.3.3
resolution: "@storybook/react-dom-shim@npm:10.3.3"
Expand Down Expand Up @@ -8003,6 +8035,45 @@ __metadata:
languageName: node
linkType: hard

"@tmcp/adapter-valibot@npm:^0.1.5":
version: 0.1.5
resolution: "@tmcp/adapter-valibot@npm:0.1.5"
dependencies:
"@standard-schema/spec": "npm:^1.0.0"
"@valibot/to-json-schema": "npm:^1.3.0"
valibot: "npm:^1.1.0"
peerDependencies:
tmcp: ^1.17.0
valibot: ^1.1.0
checksum: 10c0/176be80a74285f986ba8900116bf1ec2b97d249177b48127940b06bd08c70965a2e50d0aaa3785d4bdadd70f8e3f341fd881ce24c317a9d890cdb24ebf059399
languageName: node
linkType: hard

"@tmcp/session-manager@npm:^0.2.1":
version: 0.2.1
resolution: "@tmcp/session-manager@npm:0.2.1"
peerDependencies:
tmcp: ^1.16.3
checksum: 10c0/dadcfe6cf0e2be2536f0969aab3782355f2ff705d0a782ee9017e644b31c7eb57a593954676c252373a7d042ec6cd026e27db27460085b1c1036f7dcb1b37af5
languageName: node
linkType: hard

"@tmcp/transport-http@npm:^0.8.5":
version: 0.8.5
resolution: "@tmcp/transport-http@npm:0.8.5"
dependencies:
"@tmcp/session-manager": "npm:^0.2.1"
esm-env: "npm:^1.2.2"
peerDependencies:
"@tmcp/auth": ^0.3.3 || ^0.4.0
tmcp: ^1.18.0
peerDependenciesMeta:
"@tmcp/auth":
optional: true
checksum: 10c0/208ba54571188e69ec57a33cc316ece812f3013c2e5c2355be62cb17e90665b258e069bd7eadce7898612018a7bd0ce958db95357a409930ca7a119a00d3c28e
languageName: node
linkType: hard

"@tootallnate/once@npm:1":
version: 1.1.2
resolution: "@tootallnate/once@npm:1.1.2"
Expand Down Expand Up @@ -9204,6 +9275,15 @@ __metadata:
languageName: node
linkType: hard

"@valibot/to-json-schema@npm:^1.3.0":
version: 1.6.0
resolution: "@valibot/to-json-schema@npm:1.6.0"
peerDependencies:
valibot: ^1.3.0
checksum: 10c0/3dabbb9ed0f135c436a9f4a22ff1ad3df500e0bdff1b771eb9a03f4ba7a412bb1873a9cc1ff32c09ff47d10be8d1834a540705229380b9fc46fb65a9b41dbae2
languageName: node
linkType: hard

"@vitejs/plugin-react@npm:^4.3.1":
version: 4.4.1
resolution: "@vitejs/plugin-react@npm:4.4.1"
Expand Down Expand Up @@ -10373,6 +10453,7 @@ __metadata:
"@siteimprove/alfa-playwright": "npm:^0.78.1"
"@siteimprove/alfa-test-utils": "npm:^0.78.1"
"@storybook/addon-docs": "npm:^10.0.0"
"@storybook/addon-mcp": "npm:^0.6.0"
"@storybook/react": "npm:^10.0.0"
"@types/node": "npm:^20.0.0"
"@types/react-dom": "npm:^18.3.0"
Expand Down Expand Up @@ -15168,6 +15249,13 @@ __metadata:
languageName: node
linkType: hard

"esm-env@npm:^1.2.2":
version: 1.2.2
resolution: "esm-env@npm:1.2.2"
checksum: 10c0/3d25c973f2fd69c25ffff29c964399cea573fe10795ecc1d26f6f957ce0483d3254e1cceddb34bf3296a0d7b0f1d53a28992f064ba509dfe6366751e752c4166
languageName: node
linkType: hard

"espree@npm:^10.0.1, espree@npm:^10.4.0":
version: 10.4.0
resolution: "espree@npm:10.4.0"
Expand Down Expand Up @@ -20652,6 +20740,13 @@ __metadata:
languageName: node
linkType: hard

"json-rpc-2.0@npm:^1.7.1":
version: 1.7.1
resolution: "json-rpc-2.0@npm:1.7.1"
checksum: 10c0/260f573fd2f38c04bce63076b9293ed0c222c10bff12dd14fed8b926555af6d390c4bcc888b01dd42f28a8759056b8e4420b9f65f09e64d12d042a541fd88695
languageName: node
linkType: hard

"json-schema-traverse@npm:^0.4.1":
version: 0.4.1
resolution: "json-schema-traverse@npm:0.4.1"
Expand Down Expand Up @@ -24940,6 +25035,13 @@ __metadata:
languageName: node
linkType: hard

"picoquery@npm:^2.5.0":
version: 2.5.0
resolution: "picoquery@npm:2.5.0"
checksum: 10c0/ac22a7622ecf6f6c0d2657b04d2ca346f814ff4d343827e6ca53d2d5cecfebee18d80b1290b916d11db6f62866bec26e92bb0a0d7939bd15971e60320db8d265
languageName: node
linkType: hard

"pidtree@npm:^0.3.0":
version: 0.3.1
resolution: "pidtree@npm:0.3.1"
Expand Down Expand Up @@ -28668,6 +28770,13 @@ __metadata:
languageName: node
linkType: hard

"sqids@npm:^0.3.0":
version: 0.3.0
resolution: "sqids@npm:0.3.0"
checksum: 10c0/2ce528b83f2780166b2e8025ece1e8262ee217ed51ab5656959cb6e1a885eee5b6ea86627ce6b0321d7b0eeb34a2ed455476c01c44e6e55e18cee52b3e1b9eb3
languageName: node
linkType: hard

"ssim.js@npm:^3.1.1":
version: 3.5.0
resolution: "ssim.js@npm:3.5.0"
Expand Down Expand Up @@ -29948,6 +30057,19 @@ __metadata:
languageName: node
linkType: hard

"tmcp@npm:^1.19.3":
version: 1.19.3
resolution: "tmcp@npm:1.19.3"
dependencies:
"@standard-schema/spec": "npm:^1.0.0"
json-rpc-2.0: "npm:^1.7.1"
sqids: "npm:^0.3.0"
uri-template-matcher: "npm:^1.1.1"
valibot: "npm:^1.1.0"
checksum: 10c0/c310c21b32aa6716037eebd126eb39a62e86ef99a9d95b8dc53b7e5d212b7109beefa56506a489193018e3caed471809da8d1b07de00e747b259d0396b9b49c3
languageName: node
linkType: hard

"tmp@npm:^0.0.33":
version: 0.0.33
resolution: "tmp@npm:0.0.33"
Expand Down Expand Up @@ -31013,6 +31135,13 @@ __metadata:
languageName: node
linkType: hard

"uri-template-matcher@npm:^1.1.1":
version: 1.1.2
resolution: "uri-template-matcher@npm:1.1.2"
checksum: 10c0/27bf1880a9110b85aff4d09157869b3b37c4355f1c8212e17f698394116fc79da1896c2f03f795eb5bee0007434b448c4f3002ade257e604a1176c14b8157d12
languageName: node
linkType: hard

"urix@npm:^0.1.0":
version: 0.1.0
resolution: "urix@npm:0.1.0"
Expand Down Expand Up @@ -31139,6 +31268,30 @@ __metadata:
languageName: node
linkType: hard

"valibot@npm:1.2.0":
version: 1.2.0
resolution: "valibot@npm:1.2.0"
peerDependencies:
typescript: ">=5"
peerDependenciesMeta:
typescript:
optional: true
checksum: 10c0/e6897ed2008fc900380a6ce39b62bc5fca45fd5e070f70571c6380ede3ba026d0b7016230215d87f7f3d672a28dbde5a0522d39830b493fdc3dccd1a59ef4ee6
languageName: node
linkType: hard

"valibot@npm:^1.1.0":
version: 1.3.1
resolution: "valibot@npm:1.3.1"
peerDependencies:
typescript: ">=5"
peerDependenciesMeta:
typescript:
optional: true
checksum: 10c0/e20a4097fa726f57530da1e64558af47ddd2303129c77978fe93c522c66cf4c79540ea3af864523589283ea25e347c3d65b8044fa4913376208dde576b9f6382
languageName: node
linkType: hard

"validate-npm-package-license@npm:3.0.4, validate-npm-package-license@npm:^3.0.1, validate-npm-package-license@npm:^3.0.4":
version: 3.0.4
resolution: "validate-npm-package-license@npm:3.0.4"
Expand Down