@mieweb/ui 0.11.0-dev.19 → 0.11.0-dev.20

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/agent/README.md CHANGED
@@ -18,13 +18,13 @@ governing spec: later tickets cite it instead of re-deciding.
18
18
 
19
19
  ## Files
20
20
 
21
- | File | Purpose |
22
- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
23
- | [mieweb-ui.instructions.md](mieweb-ui.instructions.md) | The rules template. Copied verbatim to the consumer's `.github/instructions/` (VS Code Copilot auto-applies it via the `applyTo` frontmatter) and embedded, minus frontmatter, in a marked block in the consumer's `AGENTS.md` (the cross-tool convention). |
24
- | [init-agent.mjs](init-agent.mjs) | The `mieweb-ui` bin. Idempotent — rerun after upgrading `@mieweb/ui` to refresh all targets. `--experimental-agents` additionally installs the agent team below. |
25
- | [agents/](agents/) | Agent templates: `mieweb-ui-design` (orchestrator) + `mieweb-ui-styling` + `mieweb-ui-install`. Installed to the consumer's `.github/agents/` behind `--experimental-agents`. |
26
- | [skills/](skills/) | Skill templates: `mieweb-ui-catalog`, `mieweb-ui-tokens`, `mieweb-ui-icons` (generated — `pnpm agent:skills`, never hand-edit) + `mieweb-ui-brands`, `mieweb-ui-tailwind4` (hand-written, sourced from `lessons/`). Installed to `.github/skills/` behind `--experimental-agents`. |
27
- | `evals/` _(Phase 2+)_ | Golden-question eval sets per specialist; the regression harness for agent knowledge. |
21
+ | File | Purpose |
22
+ | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
23
+ | [mieweb-ui.instructions.md](mieweb-ui.instructions.md) | The rules template. Copied verbatim to the consumer's `.github/instructions/` (VS Code Copilot auto-applies it via the `applyTo` frontmatter) and embedded, minus frontmatter, in a marked block in the consumer's `AGENTS.md` (the cross-tool convention). |
24
+ | [init-agent.mjs](init-agent.mjs) | The `mieweb-ui` bin. Idempotent — rerun after upgrading `@mieweb/ui` to refresh all targets. `--experimental-agents` additionally installs the agent team below. |
25
+ | [agents/](agents/) | Agent templates: `mieweb-ui-design` (orchestrator) + `mieweb-ui-styling` + `mieweb-ui-install` + `mieweb-ui-a11y`. Installed to the consumer's `.github/agents/` behind `--experimental-agents`. |
26
+ | [skills/](skills/) | Skill templates: `mieweb-ui-catalog`, `mieweb-ui-tokens`, `mieweb-ui-icons` (generated — `pnpm agent:skills`, never hand-edit) + `mieweb-ui-brands`, `mieweb-ui-tailwind4`, `mieweb-ui-a11y-checklist` (hand-written). Installed to `.github/skills/` behind `--experimental-agents`. |
27
+ | `evals/` _(Phase 2+)_ | Golden-question eval sets per specialist; the regression harness for agent knowledge. |
28
28
 
29
29
  Rule content is sourced from [lessons/component-policy.md](../lessons/component-policy.md);
30
30
  keep the two in sync when policy changes.
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: MIE UI A11y Agent
3
+ description: Accessibility auditor for apps built with @mieweb/ui — ARIA naming, keyboard navigation, focus management, color contrast, and live-region announcements. Invoke to audit a component or page for accessibility, triage axe violations, or plan screen-reader announcements and focus behavior using the library's a11y toolkit.
4
+ tools: ['search', 'codebase', 'fetch']
5
+ handoffs:
6
+ - label: Apply Fixes
7
+ agent: agent
8
+ prompt: Apply the accessibility fixes identified in the audit above to the codebase.
9
+ send: false
10
+ ---
11
+
12
+ # MIE UI A11y Agent
13
+
14
+ You are the accessibility auditor for apps built with the **@mieweb/ui** design
15
+ system. You are **read-only**: you audit, explain, and prescribe — the
16
+ **Apply Fixes** handoff performs the edits.
17
+
18
+ ## Your sources of truth (never inline-duplicate them)
19
+
20
+ - **`mieweb-ui-a11y-checklist` skill** — the five-category audit procedure
21
+ (names/ARIA, keyboard, focus, live regions, contrast), the library toolkit
22
+ (`useFocusTrap`, `useLiveAnnouncement`, `VisuallyHidden`, `useDragReorder`,
23
+ `Modal`, `Toast`/`Alert`) with caveats, the verified AA contrast traps, and
24
+ the testing guidance. Follow it for every audit.
25
+ - **`mieweb-ui-tokens` skill** — the color scales behind any contrast
26
+ recommendation.
27
+ - **`mieweb-ui-catalog` skill** — component props when prescribing a
28
+ library-backed fix (e.g. `Button size="icon"` requires `aria-label`).
29
+ - The installed `mieweb-ui.instructions.md` — Rule 9 is the policy you
30
+ enforce; Rules 2 and 5 back the "use the component, not a styled div"
31
+ fixes.
32
+
33
+ ## Audit workflow
34
+
35
+ 1. **Scope the audit.** A component, a page, or a diff — confirm which files;
36
+ read them fully before reporting.
37
+ 2. **Run the checklist in order** (names/ARIA → keyboard → focus → live
38
+ regions → contrast). Grep targets: `onClick` on non-interactive elements,
39
+ `aria-label`-less icon buttons, `tabIndex={-1}`, `outline-none` without a
40
+ replacement focus style, the known contrast-trap class combinations.
41
+ 3. **Prefer library fixes.** A hand-rolled dialog becomes `Modal`; a bespoke
42
+ alert div becomes `Alert`/`Toast`; silent or pointer-only reorders get
43
+ `useDragReorder` with `keyboard: true` + `rowProps` (or move buttons) and
44
+ its built-in `announcement` rendered in a live region; icon-only controls
45
+ get `aria-label` or `VisuallyHidden`. Never invent props — verify in the
46
+ catalog skill.
47
+ 4. **Report, then hand off.** Findings first, in the format below; offer
48
+ **Apply Fixes** for the edits.
49
+
50
+ ## Audit output format
51
+
52
+ ### ♿ A11y audit for `<scope>`
53
+
54
+ | # | Category | File | Line | Issue | Fix |
55
+ | --- | -------- | ---- | ---- | ----- | --- |
56
+
57
+ Order findings by category (names/ARIA, keyboard, focus, live regions,
58
+ contrast). After the table: what passes, counts by category, and any
59
+ judgment calls (e.g. announcements deliberately scoped to reorders). Close by
60
+ offering the **Apply Fixes** handoff.
61
+
62
+ ## Redirects
63
+
64
+ - "Which component should I use?" → **MIE UI Design Agent**.
65
+ - Token/brand/dark-mode audits beyond contrast → **MIE UI Styling Agent**
66
+ (contrast findings are yours; palette policy is theirs).
67
+ - Install/setup problems (unstyled components, dark mode not applying) →
68
+ **MIE UI Install Agent**.
69
+
70
+ ## Rules
71
+
72
+ 1. Evidence over checklists: cite file and line for every finding; read the
73
+ code before flagging it.
74
+ 2. Axe sees only the current render — call out interaction states (open
75
+ menus, error states) that automated runs will miss.
76
+ 3. Both themes and any active brand count for contrast; a combination that
77
+ passes in light mode can fail in dark.
78
+ 4. Flag over-announcing too — live regions that fire on every keystroke are a
79
+ finding, not a virtue.
@@ -11,6 +11,10 @@ handoffs:
11
11
  agent: MIE UI Install Agent
12
12
  prompt: Diagnose the installation/setup problem above (peer deps, Tailwind wiring, CSS entry, dark-mode plumbing) and report the minimal fix.
13
13
  send: false
14
+ - label: Accessibility audit
15
+ agent: MIE UI A11y Agent
16
+ prompt: Audit the code discussed above for accessibility (ARIA naming, keyboard navigation, focus management, live regions, contrast) and report findings.
17
+ send: false
14
18
  ---
15
19
 
16
20
  # MIE UI Design Agent (orchestrator)
@@ -44,8 +48,9 @@ comparison tables) and `mieweb-ui-icons` (icon aliases and conventions):
44
48
  | --------------------------------------------------- | -------------------- |
45
49
  | install / peer deps / preset / safelist / `@source` | MIE UI Install Agent |
46
50
  | tokens, CSS vars, Tailwind classes, brands, dark | MIE UI Styling Agent |
51
+ | ARIA, keyboard nav, screen readers, contrast | MIE UI A11y Agent |
47
52
 
48
- More specialists (A11y, i18n, Migration, Grids, DataVis, Views,
53
+ More specialists (i18n, Migration, Grids, DataVis, Views,
49
54
  SuperChat, Rich Text) land in later phases; until one ships, answer its domain
50
55
  from the skills and the component docs, or defer (below).
51
56
 
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: mieweb-ui-a11y-checklist
3
+ description: Accessibility audit procedure for apps built with @mieweb/ui — ARIA naming, keyboard navigation, focus management, color contrast, and live-region announcements, plus the library's a11y toolkit (useFocusTrap, useLiveAnnouncement, VisuallyHidden, useDragReorder) and known contrast traps. USE WHEN auditing a component or page for accessibility, fixing axe violations, wiring screen-reader announcements, trapping focus in dialogs, or choosing AA-safe token combinations.
4
+ ---
5
+
6
+ # Accessibility auditing with @mieweb/ui
7
+
8
+ Policy baseline is Rule 9 of the installed `mieweb-ui.instructions.md` (every interactive element named; dynamic updates announced; tab order and focus indicators preserved). Token/contrast references live in the `mieweb-ui-tokens` skill; component props in the `mieweb-ui-catalog` skill.
9
+
10
+ ## Audit procedure
11
+
12
+ Work through the five categories in order; for each finding record file, line, issue, and the library-backed fix.
13
+
14
+ 1. **Accessible names & ARIA.** Every `<Button size="icon">`, icon-only control, and unlabeled input needs `aria-label`/`aria-labelledby` or a `<VisuallyHidden>` text child. Decorative icons get `aria-hidden="true"`. Check roles match behavior (`role="toolbar"`, `menu`/`menuitem`, `combobox`+`listbox`), and state attributes track reality (`aria-pressed`, `aria-expanded` + `aria-controls`, `aria-busy`, `aria-selected`).
15
+ 2. **Keyboard navigation.** Everything pointer-reachable must be keyboard-reachable: clickable `div`/`Card` without `role="button"` + `tabIndex={0}` + Enter/Space handler is a finding. Hidden `<input type="file">` behind a styled drop zone must still be openable by keyboard. Drag-and-drop needs a keyboard path — the library's `useDragReorder` provides one **only when opted in**: `keyboard: true` + `rowProps(id)` spread on each row (Alt+↑/↓), and/or visible `moveButtonProps` buttons. Menus need Escape-to-close (library `useEscapeKey`) and arrow-key navigation.
16
+ 3. **Focus management.** Modals/sheets: focus trap + Escape + `role="dialog" aria-modal` (library `Modal` ships all three). Verify focus *returns* to the trigger on close — `useFocusTrap` does **not** restore focus itself. Never remove focus outlines; disabled-while-busy buttons drop focus silently (prefer `aria-busy`).
17
+ 4. **Live regions & announcements.** State changes invisible to screen readers are findings: progress, errors, counts, reorders. Prefer `Toast`/`Alert` (announce for free). For custom announcements use `useLiveAnnouncement` + an `sr-only` region (pattern below). `role="alert"` for errors that appear; `role="status" aria-live="polite"` for passive counts. Announce *meaningful* changes only — announcing every keystroke-updated count is too chatty (debounce or scope to commits like reorders).
18
+ 5. **Contrast.** AA is 4.5:1 small text, 3:1 large/UI. Check both themes and any non-default brand. Known failing combinations are listed below — flag them on sight.
19
+
20
+ ## Library a11y toolkit
21
+
22
+ | Export (root entry) | Use for | Caveats |
23
+ | --- | --- | --- |
24
+ | `VisuallyHidden` | Screen-reader-only text (icon buttons, headings) | — |
25
+ | `useFocusTrap(enabled)` | Trap Tab/Shift+Tab in dialogs; focuses first focusable on enable | Queries focusables **once** when enabled — re-enable after content changes; no focus-return on close (do it yourself) |
26
+ | `useLiveAnnouncement()` | `[message, announce]` for an `aria-live` region; re-announces identical consecutive messages | You render the region yourself (pattern below) |
27
+ | `useEscapeKey`, `useClickOutside` | Dismissal plumbing for menus/popovers | — |
28
+ | `useDragReorder` | Pointer reordering, plus keyboard and announcements | Keyboard is **opt-in**: pass `keyboard: true` and spread `rowProps(id)` on rows (Alt+↑/↓), and/or render `moveButtonProps` buttons; announcements are built in — render the returned `announcement` in an `sr-only` live region |
29
+ | `usePrefersReducedMotion` | Gate bespoke animation | `MotionProvider` already respects it |
30
+ | `Modal` | Dialog with focus trap, Escape, `aria-modal` built in | — |
31
+ | `Toast` / `Alert` | Announced outcomes — never a bespoke alert div | — |
32
+
33
+ **Live-region pattern** (used across the library's list components):
34
+
35
+ ```tsx
36
+ const [announcement, announce] = useLiveAnnouncement();
37
+ // on meaningful change: announce('Item moved down');
38
+ <div aria-live="polite" className="sr-only">{announcement}</div>
39
+ ```
40
+
41
+ **Scrollable region pattern:** a keyboard-scrollable overflow container is `tabIndex={0}` + `role="region"` + `aria-label`, and must be the *single* scroll container (no nested scrolling child).
42
+
43
+ ## Known AA contrast traps (verified failures)
44
+
45
+ Ratios below are for the **default (BlueHive) palette**. Brands may override entire scales — CCME's `neutral-400` on `neutral-800` is 4.31:1, not the default 6.0:1 — so before prescribing any replacement, check the resolved values of every active brand (brand files in `src/brands/`, or computed styles at runtime) rather than trusting these numbers.
46
+
47
+ | Combination | Ratio | Use instead |
48
+ | --- | --- | --- |
49
+ | `text-destructive` on `bg-destructive/10` | 4.14:1 ✗ | `text-destructive-700 dark:text-destructive-300` |
50
+ | `text-neutral-500` on `bg-neutral-100` (small text) | 4.34:1 ✗ | `text-neutral-600`; in dark mode pair `dark:text-neutral-400` with a dark surface (e.g. `dark:bg-neutral-800` — 6.0:1 default palette; verify per brand) — on a still-light background it fails worse (2.31:1) |
51
+ | White on `bg-primary-500` (BlueHive) | 2.65:1 ✗ (even `primary-700` fails) | `<Button variant="primary">` — it uses an AA-safe shade |
52
+ | Gray-400 `#9ca3af` on white | 2.53:1 ✗ | gray-500 `#6b7280` (4.83:1) |
53
+
54
+ Raw styled buttons imitating the primary variant are both a styling finding (Rule 5) and a contrast finding — `<Button>` resolves both.
55
+
56
+ ## Testing
57
+
58
+ - Automated: run axe on rendered states (`@axe-core/playwright`, axe DevTools, or Storybook's a11y addon). Axe sees **only the current render** — open the menu/dialog/error state first, or violations in interaction states go unreported.
59
+ - Manual keyboard pass: Tab through the whole surface; verify visible focus at every stop, no traps outside dialogs, Escape closes layers, focus returns to triggers.
60
+ - Screen-reader spot check: are state changes announced exactly once, with meaningful text?
61
+
62
+ ## Verification checklist
63
+
64
+ - [ ] Every interactive element has an accessible name; decorative icons `aria-hidden`
65
+ - [ ] Full keyboard path for every pointer interaction (drag → `useDragReorder` with `keyboard: true` + `rowProps`, or move buttons)
66
+ - [ ] Dialogs trap focus, close on Escape, and return focus to the trigger
67
+ - [ ] Meaningful dynamic changes announced (`Toast`/`Alert` or `useLiveAnnouncement` + `sr-only` region)
68
+ - [ ] No known contrast traps; both themes (and active brands) checked
69
+ - [ ] Axe clean on default **and** interaction states; manual Tab pass done
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mieweb/ui",
3
- "version": "0.11.0-dev.19",
3
+ "version": "0.11.0-dev.20",
4
4
  "description": "A themeable, accessible React component library built with Tailwind CSS",
5
5
  "author": "Medical Informatics Engineering, Inc.",
6
6
  "license": "SEE LICENSE IN LICENSE",