@worldresources/wri-design-systems 2.194.5 → 2.195.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -70,6 +70,19 @@ Optional: run it against a specific path:
70
70
  ds setup-ai /path/to/your/project
71
71
  ```
72
72
 
73
+ ### Available Skills
74
+
75
+ Copy the `SKILL.md` file you want into the matching skills folder in your own project:
76
+
77
+ - Skills repo path: `agents/skills/<skill-name>/SKILL.md`
78
+ - Copy the folder into the agent-specific skills directory your project uses.
79
+
80
+ | Skill | What it does |
81
+ | --------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
82
+ | [`a11y-checker`](agents/skills/a11y-checker/SKILL.md) | Reviews components, stories, and docs for accessibility issues and suggests or applies fixes. |
83
+ | [`ds-ui-creator`](agents/skills/ds-ui-creator/SKILL.md) | Guides UI creation with the WRI Design System first, Chakra UI second, and custom code last. |
84
+ | [`pr-description`](agents/skills/pr-description/SKILL.md) | Generates a PR description from the branch diff in a consistent markdown format. |
85
+
73
86
  ### Create the Project Theme
74
87
 
75
88
  With this custom theme you can change the color scheme according to your Project Theme
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: a11y-checker
3
+ description: Reviews UI code (HTML, JSX, TSX, Vue, etc.) for accessibility (a11y) compliance across both library development (WRI Design System) and generic web applications, providing concrete guidelines and code-level fixes.
4
+ ---
5
+
6
+ When running the accessibility checker on any codebase, follow this multi-tiered guide to ensure compliance with universal WCAG standards as well as library-specific rules.
7
+
8
+ ## 1. Universal Accessibility Standards (Any Web Project)
9
+
10
+ Apply these rules to any kind of project (plain HTML, native React, Vue, Angular, or other UI libraries):
11
+
12
+ ### Accessible Names & Interactive Elements
13
+
14
+ - **Discernible Text**: Every clickable control (buttons, links, inputs) must have a discernible text label.
15
+ - **Icon-Only Actions**: If a button contains only an icon or image, it must receive an `aria-label` or `aria-labelledby` attribute (e.g., `<button aria-label="Close dialog">` or `<IconButton aria-label="Delete item" />`).
16
+ - **Images and SVGs**:
17
+ - Standalone SVGs used as controls must have `role="img"` and an `aria-label`.
18
+ - Decorative icons or illustrations must have `aria-hidden="true"` or `alt=""` so they are ignored by screen readers.
19
+
20
+ ### Forms & Input Controls
21
+
22
+ - **Explicit Associations**: Native HTML form controls must have a `<label>` explicitly linked using the `for` (or `htmlFor` in React) and `id` attributes.
23
+ - **Accessible Placeholders**: A `placeholder` is not an accessible label. A proper visible label or `aria-label` must always be provided.
24
+ - **Validation Signals**: Error states must never rely on color changes alone. Set `aria-invalid="true"` and programmatically link the input to its validation error message using `aria-describedby="error-message-id"`.
25
+
26
+ ### Layout & Landmark Structures
27
+
28
+ - **Semantic HTML**: Use correct semantic tags (`<header>`, `<nav>`, `<main>`, `<footer>`, `<aside>`, `<section>`) instead of generic `<div>` wrappers.
29
+ - **Multiple Landmarks**: If a page has multiple navigation regions, distinguish them using unique `aria-label` attributes (e.g., `<nav aria-label="Main navigation">` and `<nav aria-label="Footer navigation">`).
30
+
31
+ ### Keyboard Navigation & Focus Management
32
+
33
+ - **Focus Path**: Every interactive element must be reachable using the `Tab` key. Custom non-interactive elements that trigger actions (e.g., a clickable `div`) must have `tabindex="0"`.
34
+ - **Keyboard Triggers**: Custom interactive elements must handle `Enter` and `Space` key presses using keydown/keyup event handlers.
35
+ - **Visible Focus**: Never suppress the browser's default focus outlines (`outline: none` or `outline: 0`) unless you are explicitly defining custom, highly-visible CSS focus indicator styles (e.g. using `:focus-visible`).
36
+ - **Overlay Focus Traps**: Modals, slide-out panels, and dropdown menus must trap keyboard focus inside them while open, and must restore focus to the triggering element upon closure.
37
+
38
+ ### Data & Tabular Layouts
39
+
40
+ - **Tables**: HTML tables must use correct semantic markup (`<table>`, `<thead>`, `<tbody>`, `<tr>`, `<th>`, `<td>`). Headers should use `scope="col"` or `scope="row"`. Provide a `<caption>` or an `aria-label` to summarize the table structure.
41
+ - **Sortable Columns**: Header cells representing sortable columns must declare the current sort order via `aria-sort` (e.g. `aria-sort="ascending"` or `aria-sort="descending"`).
42
+
43
+ ---
44
+
45
+ ## 2. Project-Specific Rules
46
+
47
+ ### Context A: WRI Design System Library Contributor (`src/components/**`)
48
+
49
+ When writing or updating components inside the `@worldresources/wri-design-systems` library:
50
+
51
+ - **Expose ARIA Props**: Ensure TypeScript interfaces in `types.ts` explicitly declare standard `aria-*` props, and forward them directly to the underlying elements.
52
+ - **Defaults**: Check the component documentation guidelines in `contributor-ai/a11y.instructions.md`.
53
+ - **Test with Axe**: Write stories (`*.stories.tsx`) that demonstrate accessible configurations and include testing using `jest-axe` or Storybook's built-in a11y tools.
54
+
55
+ ### Context B: Consumer Apps using WRI Design System
56
+
57
+ When consuming WRI DS components in external applications:
58
+
59
+ - **Use Wrapper API**: Prefer built-in design system properties (e.g., `label` and `error` props on `TextInput` or `Select`) which automatically wire up proper markup, instead of manually writing custom ARIA glue.
60
+ - **No Overrides**: Never add `tabIndex={-1}` or visual overrides that hide focus rings on standard DS buttons or inputs.
61
+
62
+ ---
63
+
64
+ ## 3. Auditing Process
65
+
66
+ When checking a file, follow this flow:
67
+
68
+ 1. **Interactive Control Scan**: Locate all interactive controls (buttons, links, custom clickable elements). Verify that each has a discernible name (text, `aria-label`, or linked label).
69
+ 2. **Keyboard Path Audit**: Trace where focus moves. Ensure overlays/modals have trap-and-release focus management, and focus indicators are visible.
70
+ 3. **Form Wiring Verification**: Check that all input fields have valid labels, required states (`aria-required`), and connected error messages.
71
+ 4. **Markup Semantics Check**: Ensure landmarks exist and no inline SVG or icon lack proper `aria-hidden` or label states.
72
+
73
+ ---
74
+
75
+ ## 4. Code Examples (Common Fixes)
76
+
77
+ ### Custom Icon Buttons
78
+
79
+ ```tsx
80
+ // ❌ HTML / Generic React Error (No accessible name, icon read as raw text or ignored)
81
+ <button onClick={onClose}><CloseIcon /></button>
82
+
83
+ // ✅ HTML / Generic React Fix
84
+ <button aria-label="Close dialog" onClick={onClose}>
85
+ <CloseIcon aria-hidden="true" />
86
+ </button>
87
+
88
+ // ✅ WRI DS Fix
89
+ <IconButton aria-label="Close dialog" icon={<CloseIcon aria-hidden="true" />} onClick={onClose} />
90
+ ```
91
+
92
+ ### Form Fields with Error States
93
+
94
+ ```tsx
95
+ // ❌ Generic HTML Error (Color only, screen reader cannot read validation error connection)
96
+ <input type="email" style={{ borderColor: 'red' }} />
97
+ <span className="error">Invalid email address</span>
98
+
99
+ // ✅ Generic HTML Fix
100
+ <label htmlFor="email-input">Email Address</label>
101
+ <input
102
+ id="email-input"
103
+ type="email"
104
+ aria-invalid="true"
105
+ aria-describedby="email-error-msg"
106
+ />
107
+ <span id="email-error-msg" className="error">Invalid email address</span>
108
+
109
+ // ✅ WRI DS Fix
110
+ <TextInput
111
+ label="Email Address"
112
+ error="Invalid email address"
113
+ aria-invalid={true}
114
+ aria-describedby="email-error-msg"
115
+ id="email-input"
116
+ />
117
+ ```
@@ -0,0 +1,156 @@
1
+ ---
2
+ name: ds-ui-creator
3
+ description: Guidelines for building user interfaces and components in applications consuming the WRI Design System, incorporating Level 1 (WRI DS), Level 2 (Chakra UI v3), and Level 3 (Custom CSS/HTML).
4
+ ---
5
+
6
+ When building components and user interfaces in an application consuming the WRI Design System, developers and AI coding agents must follow these guidelines:
7
+
8
+ ## 1. Component Hierarchy (Golden Rule)
9
+
10
+ Always evaluate and build UI elements using the following hierarchy. Never skip a level:
11
+
12
+ ```
13
+ 1. @worldresources/wri-design-systems (WRI DS) ← Always check first
14
+ 2. @chakra-ui/react (Chakra UI v3) ← Fallback if no WRI DS equivalent
15
+ 3. Custom HTML + CSS / Styled Primitives ← Last resort (requires reasoning tag)
16
+ ```
17
+
18
+ ### Level 1: WRI Design System (`@worldresources/wri-design-systems`)
19
+
20
+ - **First Choice**: Check Storybook, Zeroheight style guide, or README files to verify if a component exists in the design system.
21
+ - **Do Not Rebuild**: Never use raw elements (e.g. `<button>`, `<input>`, `<select>`) or raw Chakra equivalents when a WRI DS wrapper exists (e.g. `Button`, `IconButton`, `Select`, `TextInput`).
22
+ - **No Style Overrides**: Do NOT use `sx`, `css`, `style`, or `className` to override design system component styles. Use them exactly as-is to preserve visual consistency.
23
+ - **Query MCP**: Use the Storybook MCP server to check component listings (`mcp_wri-storybook_getComponentList`) and verify exact prop signatures (`mcp_wri-storybook_getComponentsProps`).
24
+
25
+ ### Level 2: Chakra UI v3 (`@chakra-ui/react`)
26
+
27
+ - **Use as Fallback**: If there is no corresponding WRI DS component, use standard Chakra UI v3 primitives (e.g., `<Box>`, `<Flex>`, `<Grid>`).
28
+ - **Chakra v3 API Only**: Do not use legacy Chakra v2 properties (like `colorScheme`, `isDisabled`, or `leftIcon`). Verify all props using the Chakra MCP server (`mcp_chakra-ui_get_component_props`).
29
+ - **Theme Integration**: Apply styling using the themed token functions rather than passing raw non-token values.
30
+
31
+ ### Level 3: Custom Code (Last Resort)
32
+
33
+ - **Required Marker**: If custom CSS or custom HTML is absolutely necessary because neither WRI DS nor Chakra v3 has the capabilities needed, comment it clearly with:
34
+ `// [CUSTOM COMPONENT] — <detailed reason explaining why Level 1 & 2 were bypassed>`
35
+ - **No Hardcoding**: Custom components must still use design token functions for sizes, colors, margins, and borders. Never write raw hex colors, px, or rem.
36
+
37
+ ---
38
+
39
+ ## 2. Design Tokens & Theme API (Strict Token Enforcement)
40
+
41
+ All values (colors, spacing, typography, borders, radii) must resolve through the design system token functions. Never hardcode literal values like `#2C7D6E`, `1rem`, `16px`, etc.
42
+
43
+ ### Token Helper Imports
44
+
45
+ Import the themed helpers directly from the `@worldresources/wri-design-systems` package:
46
+
47
+ ```typescript
48
+ import {
49
+ getThemedColor,
50
+ getThemedSpacing,
51
+ getThemedRadius,
52
+ getThemedBorderWidth,
53
+ getThemedFontSize,
54
+ getThemedLineHeight,
55
+ } from '@worldresources/wri-design-systems'
56
+ ```
57
+
58
+ ### Reference Tables
59
+
60
+ | Category | Function | Valid Values / Steps / Tokens | Example |
61
+ | :--------------- | :------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------- |
62
+ | **Colors** | `getThemedColor(variant, step)` | **Variants**: `neutral`, `primary`, `secondary`, `success`, `warning`, `error`, `accessible`<br>**Steps**: `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900` | `getThemedColor('primary', 500)` |
63
+ | **Spacing** | `getThemedSpacing(token)` | `0`, `50`, `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900`, `1000`, `1100`, `1200`, `1400`, `1600`, `2000`, `2400`, `2800` | `getThemedSpacing(400)` (1rem) |
64
+ | **Radius** | `getThemedRadius(token)` | `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900` | `getThemedRadius(500)` (0.5rem) |
65
+ | **Border Width** | `getThemedBorderWidth(token)` | `100`, `200`, `300`, `400` | `getThemedBorderWidth(100)` (0.0625rem) |
66
+ | **Font Size** | `getThemedFontSize(token)` | `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900`, `1000`, `1100` | `getThemedFontSize(700)` (1.5rem) |
67
+ | **Line Height** | `getThemedLineHeight(token)` | `300`, `400`, `500`, `600`, `700`, `800`, `900`, `1000`, `1100`, `1200` | `getThemedLineHeight(400)` (1rem) |
68
+
69
+ ### Code Examples
70
+
71
+ ```tsx
72
+ // ❌ INCORRECT (Hardcoded visual values & bypassed tokens)
73
+ <Box
74
+ p="1rem"
75
+ bg="#2C7D6E"
76
+ borderRadius="8px"
77
+ fontSize="16px"
78
+ border="1px solid #E2E8F0"
79
+ />
80
+
81
+ // ✅ CORRECT (Tokens mapped using design system theme helper functions)
82
+ <Box
83
+ p={getThemedSpacing(400)}
84
+ bg={getThemedColor('primary', 500)}
85
+ borderRadius={getThemedRadius(500)}
86
+ fontSize={getThemedFontSize(400)}
87
+ border={`${getThemedBorderWidth(100)} solid ${getThemedColor('neutral', 200)}`}
88
+ />
89
+ ```
90
+
91
+ ---
92
+
93
+ ## 3. Accessibility (A11y) Requirements
94
+
95
+ Accessibility must be verified at every call site. Components provide internally sound accessible states, but they require proper configurations from developers:
96
+
97
+ 1. **Accessible Control Names**:
98
+ - Icon-only actions (like `IconButton`, `CloseButton`, or a text-free `Button`) must receive a localized, descriptive `aria-label`.
99
+ - Form fields must have labels. Prefer the built-in `label` prop. If no visible label is shown, provide `aria-label` or `aria-labelledby`.
100
+ 2. **Interactive States**:
101
+ - Toggle buttons must reflect state with `aria-pressed={isPressed}`.
102
+ - Elements that trigger collapsible panels or menus must use `aria-expanded={isOpen}` and `aria-controls="panel-id"`.
103
+ 3. **Form Validation & Error States**:
104
+ - When a field has validation errors, set `aria-invalid={true}` and use `aria-describedby` pointing to the error message container. Never signal an error state through color changes alone.
105
+ 4. **Layout Navigation Landmarks**:
106
+ - Multiple navigation regions must be distinguished with distinct labels (e.g. `<nav aria-label="Main navigation">` and `<nav aria-label="Footer">`).
107
+ 5. **Tabular Information**:
108
+ - Tables must have an `aria-label` or a `<caption>` child, and sortable headers must announce sorting state via `aria-sort` or its equivalent.
109
+ 6. **Focus Management**:
110
+ - Never suppress focus outlines (e.g., do not add `outline: none` or set `tabIndex={-1}` on interactive controls unless deliberately building focus-trap cycles).
111
+
112
+ ---
113
+
114
+ ## 4. Internationalization (i18n)
115
+
116
+ All WRI DS components ship with English defaults. To localize UI strings for other languages, follow one of these patterns:
117
+
118
+ - **Global/Provider Context**: Wrap the application with `DesignSystemLocaleProvider` to pass common translations (e.g., optional field suffixes, required markers, list expand/hide actions).
119
+
120
+ ```tsx
121
+ import { DesignSystemLocaleProvider, type DesignSystemLabels } from '@worldresources/wri-design-systems'
122
+
123
+ const labels: DesignSystemLabels = {
124
+ TextInput: {
125
+ optionalSuffix: t('common.optional'),
126
+ requiredSymbolLabel: t('common.required'),
127
+ },
128
+ CheckboxList: {
129
+ expandLabel: t('ds.expand'),
130
+ hideLabel: t('ds.hide'),
131
+ },
132
+ }
133
+
134
+ <DesignSystemLocaleProvider labels={labels}>
135
+ <App />
136
+ </DesignSystemLocaleProvider>
137
+ ```
138
+
139
+ - **Component-Level Override**: Pass translated values directly to the component using its `labels` prop. Never hardcode English literals in the `labels` prop; always route strings through the translation framework.
140
+ ```tsx
141
+ <Password
142
+ labels={{
143
+ showLabel: t('password.show'),
144
+ hideLabel: t('password.hide'),
145
+ }}
146
+ />
147
+ ```
148
+
149
+ ---
150
+
151
+ ## 5. Forbidden Patterns
152
+
153
+ - **Importing Raw Chakra Primitives when WRI DS Wrappers Exist**: Do not do `import { Button } from '@chakra-ui/react'` when WRI DS has `Button`.
154
+ - **Applying Style Overrides on WRI DS Components**: Bypassing design consistency with `sx={{...}}`, `style={{...}}`, or inline style blocks is forbidden.
155
+ - **Passing Raw Strings for Tokens**: Do not use `<Box bg="primary.500" />`. Use the exact helper call instead: `<Box bg={getThemedColor('primary', 500)} />`.
156
+ - **Placeholder Labels**: Do not use `placeholder` in place of a proper visible label or `aria-label` attribute.
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: pr-description
3
+ description: Guidelines for writing PR description. Covers required content, formatting, and examples. Use when the user asks to summarize changes for a PR or create a PR description.
4
+ ---
5
+
6
+ When writing a PR description:
7
+
8
+ 1. Run `git diff main...HEAD` to see all changes on this branch
9
+ 2. Write a description following this format, in markdown:
10
+
11
+ ## What
12
+
13
+ One sentence explaining what this PR does.
14
+
15
+ ## Why
16
+
17
+ Brief context on why this change is needed
18
+
19
+ ## Changes
20
+
21
+ - Bullet points of specific changes made
22
+ - Group related changes together
23
+ - Mention any files deleted or renamed
24
+ - Add some examples of before/after code where helpful