import { A2uiSurface } from "@elabs-ai/components-ai";npm install @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-aiPrompt for your coding agent
Paste it into Claude Code, Cursor, Codex or any other coding agent. Text in [brackets] is yours to fill in.
Add the brand-ui A2uiSurface component (from @elabs-ai/components-ai) to this project. 1. Read https://elabs-ai.com/llms.txt first: it maps every package and the rules. If you can use MCP servers, connect https://elabs-ai.com/mcp and use its search, docs and tokens tools. If not, run the same lookups in the terminal: `npx -y @elabs-ai/components-cli search "<what you need>"` and `npx -y @elabs-ai/components-cli docs <Component>`. 2. Look A2uiSurface up before writing code: `npx -y @elabs-ai/components-cli docs A2uiSurface` prints its real props, variants, what it pairs with and what to avoid. 3. If @elabs-ai/components-ai is not installed yet: `pnpm add @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-ai` (or `npm install @elabs-ai/components-tokens @elabs-ai/components-ui @elabs-ai/components-ai`). If this is the first brand-ui package in the project, wire it once: import `@elabs-ai/components-tokens/styles.css` plus the `themes/light.css` and `themes/dark.css` stylesheets in the CSS entry, add one Tailwind `@source` line per installed @elabs-ai package (Tailwind does not scan node_modules, so without it everything renders unstyled), and wrap the app root in `ThemeProvider` from `@elabs-ai/components-tokens`. 4. Use it here: [the screen or file, and what it should show] 5. Rules: use only @elabs-ai/components-* components and the semantic tokens — no raw colours, no raw font sizes, no arbitrary Tailwind values. Look up each component's real props with the docs tool before you use it; never guess a prop. 6. Done means: the typecheck passes, `npx -y @elabs-ai/components-cli audit src --strict` reports nothing, and you have opened the app and looked at every screen you touched in the light and the dark theme.
Avoid
- Letting the agent emit className, style or code — a surface is data; the validator rejects anything outside `brand-ui a2ui catalog`.
- Resolving actions inside the surface — `on.<event>` names a host verb; the app's onAction decides what it means (D5).
- Reaching for A2UI for a chat that only shows messages — that is a conversation (UIMessage); A2UI is for screens the agent designs.
- Extending the catalog with a component that owns its own colours — every catalog type renders on semantic tokens so a surface inherits the app's theme.
Works with
Used inside
Pairs with
Avoid next to
Examples
Why It Was Held
"Why did you hold this?" — the decision record with approve/dismiss reaching the host, and the score explained.
API
A2uiSurface
| Prop | Type | Description |
|---|---|---|
surfacerequired | A2uiSurfaceSpec | string | null | undefined | The agent's surface: a parsed spec, or its JSON text (may be a streaming prefix). |
catalog | A2uiCatalog | Which types render, and how. Defaults to the shipped `uiCatalog`. |
onAction | A2uiActionHandler | Receives every `on.<event>` binding the user triggers. |
isStreaming | boolean | Content is arriving incrementally — build up, suppress transient errors. |
loading | boolean | No surface yet (fetch-then-show) — forces the skeleton. |
onError | (errors: A2uiError[]) => void | Fires once per settled, invalid surface with the validation errors. |
skeleton | ReactNode | Replace the default skeleton (shown before the first paint while pending). |
Theming
The tokens each state resolves to. Change the token and every theme follows.
| State | Token |
|---|---|
| loading | layout-shaped Skeleton + role=status live region until the first node paints |
| streaming | isStreaming → the JSON prefix is completed, valid nodes draw, invalid-yet nodes are pruned; no error until the input settles |
| error | settled + invalid → role=alert listing every problem with its path; onError once |