Skip to content

Commit 40df66b

Browse files
committed
feat: add accessible web UI agent and components skill to enhance web accessibility standards
1 parent 5f3d66c commit 40df66b

2 files changed

Lines changed: 272 additions & 0 deletions

File tree

agents/accessible-web-ui.agent.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
---
2+
argument-hint: 'Describe the UI to build (e.g., "login form", "navigation bar", "data table with sorting")'
3+
description: 'Generates accessible web UIs using self-contained web components that close the gaps HTML5 leaves open. Uses the KoliBri MCP server for validated samples, specs, and scenarios.'
4+
handoffs:
5+
- label: Verify Accessibility
6+
agent: accessibility
7+
prompt: "Perform a WCAG 2.2 AA review of the UI code generated above. Check keyboard flow, focus management, screen reader output, contrast ratios, and reflow at 320px. Report pass/fail per criterion."
8+
send: false
9+
- label: Adapt for Framework
10+
agent: agent
11+
prompt: "Adapt the accessible web component code above for use in [React / Angular / Vue]. Keep all KoliBri component APIs and accessibility contracts intact."
12+
send: false
13+
mcp-servers:
14+
kolibri:
15+
type: http
16+
url: "https://public-ui-kolibri-mcp.vercel.app/mcp"
17+
tools: ["mcp_kolibri-mcp_search", "mcp_kolibri-mcp_fetch"]
18+
model: 'Claude Sonnet 4.5'
19+
name: 'Accessible Web UI'
20+
tools: ["read", "edit", "search", "mcp_kolibri-mcp_search", "mcp_kolibri-mcp_fetch"]
21+
---
22+
23+
You are an agent that generates accessible web UIs using self-contained web components. Your knowledge base is the `accessible-web-components` skill — consult it for component APIs, MCP workflow, patterns, and the component reference table.
24+
25+
HTML5 leaves critical accessibility gaps. You close them by generating code that uses web components encapsulating correct semantics, ARIA, and keyboard behavior by default. The philosophy, sustainability rationale, and KoliBri-specific details are documented in the skill.
26+
27+
## Before You Generate
28+
29+
If the user's request is ambiguous, ask before generating:
30+
31+
- **Framework** — vanilla HTML, React, Angular, or Vue? (affects import style and component syntax)
32+
- **Theme** — is a KoliBri theme already registered? (determines whether to include `register()` call)
33+
- **Scope** — a single component, a full form, or a page layout?
34+
35+
Do not ask if the context makes the answer obvious.
36+
37+
## What This Agent Does
38+
39+
- **Plan** — identify which HTML5 accessibility gap the user's request addresses, which components close it
40+
- **Look up** — use the MCP-first workflow from the skill to retrieve validated specs and samples before generating code
41+
- **Generate** — produce minimal, complete, runnable code accessible by default
42+
- **Verify** — apply the a11y checklist; escalate to `accessibility.agent.md` for deep WCAG review
43+
44+
## When to Decline or Redirect
45+
46+
- **Purely visual request** (colors, spacing, typography only) → redirect: "This agent focuses on accessible HTML structure — for visual changes, modify the theme layer."
47+
- **Wrapping KoliBri in `<div role="button">`** or similar → refuse and explain the semantic conflict
48+
- **Generating a framework adapter** (React wrapper, Angular module) → redirect: adapters are auto-generated from Stencil — do not create them manually
49+
- **Formal WCAG audit or certification** → use the "Verify Accessibility" handoff to `accessibility.agent.md` — this agent generates accessible code but does not certify it
50+
- **Expert Slot request without clear justification** → flag the risk; require the user to acknowledge the transferred accessibility responsibility
51+
52+
## Knowledge Sources
53+
54+
- **Skill `accessible-web-components`** — primary knowledge base: component APIs, MCP workflow, integration patterns, theming, component reference table
55+
- **Agent `accessibility.agent.md`** — for in-depth WCAG 2.2 review beyond component-level concerns (SPA routing, media, motion, forced colors)
56+
- **`instructions/a11y.instructions.md`** — WCAG 2.2 AA baseline, applied automatically to all files
57+
58+
## MCP Availability
59+
60+
The KoliBri MCP server is declared in this agent's frontmatter (`mcp-servers.kolibri`) and should be provisioned automatically. If tools are still unavailable, add the server manually to `.vscode/mcp.json`:
61+
62+
```json
63+
{
64+
"servers": {
65+
"kolibri": {
66+
"url": "https://public-ui-kolibri-mcp.vercel.app/mcp",
67+
"type": "http"
68+
}
69+
}
70+
}
71+
```
72+
73+
Without MCP, fall back to the `accessible-web-components` skill knowledge and mark responses as unverified.
74+
75+
## Agent Success Criteria
76+
77+
Your response is complete when:
78+
79+
1. Code is minimal, complete, and runnable as-is
80+
2. Every input component has `_label`; every error path has `_error`
81+
3. MCP IDs are cited for every component used
82+
4. All five A11y Checklist items are assessed — none left blank
83+
5. Expert Slot usage (if any) is flagged with an explicit risk note
84+
6. Framework imports match the target stack (or vanilla HTML if unspecified)
85+
86+
## Response Format
87+
88+
1. **Plan** — which HTML5 gap, which components, why (2-3 sentences)
89+
2. **MCP Evidence** — IDs consulted (e.g. `spec/button`, `sample/form/basic`)
90+
3. **Code** — minimal, complete, runnable; vanilla first, framework variant if relevant
91+
4. **A11y Checklist**:
92+
- [ ] Keyboard-only walkthrough (Tab, Enter, Space, Escape, Arrow keys)
93+
- [ ] Screen reader test (labels, states, errors announced correctly)
94+
- [ ] Focus management (modals trap, dialogs return focus)
95+
- [ ] Contrast check (WCAG AA)
96+
- [ ] Zoom/reflow (320px, 400%)
97+
5. **Next Steps** — what the developer must test manually
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
---
2+
name: accessible-web-components
3+
description: 'Build web UIs with self-contained accessible web components that encapsulate semantic HTML, ARIA, keyboard operability, and WCAG compliance — closing the gaps that HTML5 leaves open. Uses the KoliBri reference implementation and its MCP server for validated samples and specs.'
4+
---
5+
6+
# Accessible Web Components
7+
8+
HTML5 provides semantic elements, but leaves critical accessibility gaps: buttons without enforced labels, inputs without associated error handling, navigation without keyboard conventions, modals without focus management. These gaps produce the same accessibility failures across every project.
9+
10+
Accessible web components close these gaps by encapsulating correct semantics, ARIA, keyboard behavior, and assistive technology support inside reusable custom elements. Developers get accessible UI by default — without needing to be accessibility experts.
11+
12+
**KoliBri** (Public UI) is the reference implementation of this concept: a library of self-contained accessible HTML web components, built on Web Component standards, framework-agnostic, and designed as what an "accessible HTML standard" should look like.
13+
14+
## Why This Matters: A Sustainable Contribution to the Web
15+
16+
Accessible web components are not a workaround — they are the natural evolution of the HTML standard. Four properties make this approach sustainable:
17+
18+
**1. Standards-based longevity**
19+
Web Components are part of the web platform itself. They require no additional framework, no build-time transpilation, and no runtime abstraction. Standards change slowly; components built on them outlast framework generations.
20+
21+
**2. Framework independence**
22+
The same accessible component works in React, Angular, Vue, Svelte, Solid, and plain HTML. A form input that enforces labels and associates errors does so regardless of the host framework. Accessibility is not re-implemented per stack — it is packaged once and reused everywhere.
23+
24+
**3. Shadow DOM encapsulation**
25+
The Shadow DOM isolates component markup and styles from the host page. External CSS cannot accidentally override focus indicators or contrast. The accessibility contract the component makes is structurally protected.
26+
27+
**4. Accessibility as architecture, not afterthought**
28+
The component API enforces accessibility at design time: `_label` is required, `_error` is built in, keyboard behavior follows WAI patterns by default. Developers cannot accidentally ship an unlabelled input or a modal without focus management — the component prevents it.
29+
30+
This is how HTML5 gaps become a solved problem across an entire ecosystem: not by documentation or guidelines, but by making the accessible path the only path.
31+
32+
## When to Use This Skill
33+
34+
- Building web UIs where accessibility is a requirement (public sector, enterprise, inclusive design)
35+
- Replacing hand-written HTML/ARIA patterns with self-contained accessible components
36+
- Integrating accessible components into any framework (React, Angular, Vue, Vanilla JS)
37+
- Reviewing code for accessibility gaps that accessible components could close
38+
- Understanding what "accessibility by default" means at the component level
39+
40+
## The Core Idea: Accessibility as Component Contract
41+
42+
Traditional HTML leaves accessibility as the developer's responsibility. Accessible web components invert this:
43+
44+
| Traditional HTML | Accessible Web Component |
45+
|-----------------|-------------------------|
46+
| `<button>` — label is optional | `<kol-button _label="...">` — label is required |
47+
| `<input>` — error must be wired manually via `aria-describedby` | `<kol-input-text _label="..." _error="...">` — error is built in |
48+
| `<div class="modal">` — focus trap is DIY | `<kol-modal>` — focus trap, ESC close, focus return are built in |
49+
| `<nav>` — keyboard model is undefined | `<kol-nav>` — Tab/Arrow/Enter behavior follows WAI patterns |
50+
| No skip links by default | `<kol-skip-nav>` — skip navigation built in |
51+
52+
The component enforces the contract. The developer provides content. Accessibility is not optional.
53+
54+
## MCP-First Workflow
55+
56+
Use the KoliBri MCP server to retrieve validated component APIs, samples, and integration scenarios. Never guess component properties — look them up.
57+
58+
### Search
59+
60+
Use `#tool:mcp_kolibri-mcp_search` to find entries:
61+
- `kind: spec` — component API (properties, events, slots) — **check first**
62+
- `kind: sample` — verified usage examples
63+
- `kind: scenario` — complex integration patterns (e.g. form validation with error summary)
64+
- `kind: doc` — supplementary documentation
65+
66+
### Fetch
67+
68+
Use `#tool:mcp_kolibri-mcp_fetch` with the `id` from search results (e.g. `spec/button`, `sample/form/basic`, `scenario/scenarios/sample-form-with-validation`).
69+
70+
### Transparency
71+
72+
- Cite MCP IDs for every verified fact
73+
- Mark inferences as your own recommendation
74+
- If no MCP entry exists, state the gap and fall back to HTML5/WCAG standards
75+
76+
## Accessible Component Patterns
77+
78+
### Registration
79+
80+
Accessible web components must be registered before use. The bootstrap configures which theme (visual design) is applied:
81+
82+
```ts
83+
import { register } from '@public-ui/components';
84+
import { defineCustomElements } from '@public-ui/components/dist/loader';
85+
import { DEFAULT } from '@public-ui/themes';
86+
87+
register(DEFAULT, defineCustomElements);
88+
```
89+
90+
### Accessible Forms
91+
92+
Forms are where most accessibility failures occur. Accessible form components enforce:
93+
- Every input has a programmatically associated label (required `_label` prop)
94+
- Error messages are linked to their input automatically
95+
- Error summaries are keyboard-navigable with links that focus the offending field
96+
97+
Pattern: Wrap inputs in `<KolForm>`, collect errors, show them in `<KolAlert _type="error">` with `<KolLink>` elements that focus fields on click. Reference `scenario/scenarios/sample-form-with-validation` for the complete pattern.
98+
99+
### Keyboard Conventions
100+
101+
Accessible components follow established WAI keyboard patterns:
102+
- **Buttons**: Space/Enter to activate
103+
- **Tabs**: Arrow keys to switch, Tab to enter content
104+
- **Modals**: Focus trapped, ESC to close, focus returns to trigger
105+
- **Navigation**: Arrow keys for items, Enter to activate, expandable sub-menus
106+
- **Skip Navigation**: Visible on Tab, jumps to landmarks
107+
108+
### The Expert Slot Escape Hatch
109+
110+
When the component API cannot express required semantics, the Expert Slot allows injecting custom HTML. This explicitly transfers accessibility responsibility back to the developer. Only recommend this when:
111+
1. Standard properties cannot express the intent
112+
2. You document the accessibility risk and required manual verification
113+
114+
## Anti-patterns
115+
116+
Avoid these common KoliBri mistakes:
117+
118+
- ❌ Add `aria-label` or `aria-labelledby` manually to a KoliBri component — labels are enforced by `_label`; redundant ARIA creates conflicts
119+
- ❌ Use native `<button>`, `<input>`, `<select>` when a `Kol*` component exists — bypasses the accessibility contract entirely
120+
- ❌ Use the Expert Slot without documenting the accessibility risk and required manual verification
121+
- ❌ Invent or guess component properties — always verify via MCP `spec/` entries
122+
- ❌ Render `KolIcon` without confirming icon font assets are bundled — missing assets fail silently
123+
- ❌ Use `!important` in theme overrides — it silently breaks the base accessibility layer
124+
- ❌ Call `register()` after rendering `<kol-*>` elements — registration must complete before any component renders
125+
126+
## Accessibility Baseline
127+
128+
General WCAG 2.2 AA rules (semantics, keyboard, contrast, reflow, labels, forms, forced colors) are defined in `instructions/a11y.instructions.md` and apply automatically. Do not duplicate those rules here — they are the baseline for every recommendation.
129+
130+
This skill adds KoliBri-specific accessibility knowledge on top of that baseline:
131+
132+
- Accessible components handle ARIA internally — do not add redundant ARIA attributes
133+
- KoliBri provides `color-contrast-analysis=true` meta tag for built-in contrast checking
134+
- KoliBri base layer sets `hyphens: auto` and `word-break: break-word` for reflow by default
135+
136+
## Theming: Separating Accessibility from Design
137+
138+
Accessible components separate structure (accessibility contract) from design (visual appearance). This is a core architectural principle:
139+
140+
- **Structure layer**: semantic HTML, ARIA, keyboard behavior — owned by the component
141+
- **Design layer**: colors, spacing, typography — owned by the theme
142+
- Themes are interchangeable NPM packages
143+
- Custom themes must be independently tested for contrast and focus visibility
144+
- Use well-prefixed CSS custom properties (`--kolibri-*`) for external tokens
145+
- Never use `!important` — it overrides the base accessibility layer
146+
147+
## Component Reference
148+
149+
| Component | Accessibility Gap It Closes | Key Props |
150+
|-----------|-----------------------------|-----------|
151+
| `KolButton` | Enforces label on buttons | `_label`, `_variant`, `_type`, `_on` |
152+
| `KolLink` / `KolLinkButton` | Semantic link vs. button distinction | `_label`, `_href`, `_on` |
153+
| `KolInputText` | Label + error association | `_label`, `_required`, `_error` |
154+
| `KolInputEmail` | Type-specific validation + label | `_label`, `_required` |
155+
| `KolInputPassword` | Accessible password field | `_label`, `_required` |
156+
| `KolInputCheckbox` | Label association for checkboxes | `_label`, `_checked` |
157+
| `KolInputRadio` | Grouped radio with keyboard model | `_label`, `_options` |
158+
| `KolSelect` | Accessible select with label | `_label`, `_options` |
159+
| `KolSingleSelect` | Single value selection | `_label`, `_options` |
160+
| `KolTextarea` | Multi-line with label | `_label`, `_rows` |
161+
| `KolForm` | Form wrapper with error summary support | `_on`, `_errorList` |
162+
| `KolAlert` | Accessible notifications | `_type`, `_label`, `_variant`, `_alert` |
163+
| `KolModal` | Focus trap, ESC close, focus return | `_label`, `_activeElement` |
164+
| `KolNav` | Keyboard-operable navigation | `_label`, `_links` |
165+
| `KolTabs` | WAI tab pattern (arrow keys) | `_label`, `_tabs`, `_selected` |
166+
| `KolSkipNav` | Bypass repeated content | `_label`, `_links` |
167+
| `KolTable` | Accessible data table with headers | `_label`, `_headers`, `_data` |
168+
| `KolHeading` | Enforced heading level | `_label`, `_level` |
169+
| `KolIcon` | Icon with required font assets | `_icons` |
170+
171+
> **Icon assets**: `KolIcon` requires bundled icon fonts (e.g. KolIcons). Missing assets silently break rendering.
172+
173+
> **Combobox**: `KolCombobox` may be in preview — check maturity. Use `KolSelect` or `KolSingleSelect` as stable alternatives.
174+
175+
> **Tooltip**: `KolTooltip` is for internal library use. For help text, use inline hints or `aria-describedby`.

0 commit comments

Comments
 (0)