<< All versions
Skill v2.9.0
currentLLM-judged scan95/100ant-design/x/x-card
2 files
──Details
PublishedAugust 5, 2026 at 01:41 PM
Content Hashsha256:679a751e1352045a...
Git SHAb529d8e96d5b
Bump Typepatch
──Files
Files (1 file, 10.3 KB)
SKILL.md10.3 KBactive
SKILL.md · 275 lines · 10.3 KB
name: x-card version: 2.9.0 description: Use when building AI-driven UIs with @ant-design/x-card — covers XCard.Box, XCard.Card, A2UI v0.9 commands, data binding, catalogs, actions, and streaming patterns.
🎯 Skill Positioning
This skill covers `@ant-design/x-card` — the React implementation of the A2UI protocol, enabling AI agents to dynamically render rich interactive UIs through structured JSON command streams.
It covers:
XCard.Box+XCard.Cardcomponent usage- A2UI v0.9 command types:
createSurface,updateComponents,updateDataModel,deleteSurface - Custom component registration and catalog management
- Data binding via JSON Pointer paths (RFC 6901)
- Action handling — sending user events back to the agent
- Streaming progressive rendering patterns
- v0.8 ↔ v0.9 protocol differences
Scope: v0.9 is the recommended protocol. v0.8 is supported for backward compatibility only — prefer v0.9 for all new work.
Table of Contents
- 📦 Package Overview
- 🗂️ Component Architecture
- 🚀 Quick Start Decision Guide
- 🛠 Recommended Workflow
- 🚨 Development Rules
- 🤝 Skill Collaboration
- 🔗 Reference Resources
📦 Package Overview
| Package | Responsibility | |
|---|---|---|
@ant-design/x-card | React renderer for A2UI protocol — XCard.Box, XCard.Card, catalog APIs | |
@ant-design/x | Chat UI components (Bubble, Sender, etc.) — not covered here | |
@ant-design/x-sdk | Data providers, streaming — not covered here |
bash
npm install @ant-design/x-card
Exports:
typescript
import {XCard,registerCatalog,loadCatalog,validateComponent,clearCatalogCache,} from '@ant-design/x-card';import type {XAgentCommand_v0_9,XAgentCommand_v0_8,ActionPayload,Catalog,CatalogComponent,} from '@ant-design/x-card';// SubcomponentsXCard.Box; // Container: receives commands, owns catalog mapsXCard.Card; // Renderer: renders a single surface by id
🗂️ Component Architecture
XCard.Box├── owns: catalogMap, surfaceCatalogMap├── dispatches: commands → all XCard.Card children├── aggregates: onAction events from all Cards└── XCard.Card (id="surface-a")│ ├── owns: component tree, data model, commandVersion│ └── resolves: data bindings, triggers actions└── XCard.Card (id="surface-b")└── ...
XCard.Box Props
typescript
interface BoxProps {commands?: (XAgentCommand_v0_9 | XAgentCommand_v0_8)[];/** Component names must start with an uppercase letter (React component convention) */components?: Record<string, React.ComponentType<any>>;onAction?: (payload: ActionPayload) => void;children?: React.ReactNode; // Should contain XCard.Card elements}
XCard.Card Props
typescript
interface CardProps {id: string; // surfaceId to render}
ActionPayload
typescript
interface ActionPayload {name: string; // from action.event.namesurfaceId: string; // which surface triggered it/*** Context passed by component, with path references automatically resolved.** For action.event.context fields using { path: "xxx" } format:* - X-Card automatically resolves them to { value: "actual_value" }* - Other properties (like label) are preserved** Example input config:* { username: { path: "/form/username", label: "用户名" } }** Example resolved context:* { username: { value: "张三", label: "用户名" } }*/context: Record<string, any>;}
🚀 Quick Start Decision Guide
| If you need to... | Read first | |
|---|---|---|
| Set up XCard.Box + XCard.Card | USAGE.md → Basic Setup | |
| Send commands from agent to card | COMMANDS.md | |
| Register a custom component catalog | CATALOG.md → Local Catalog | |
| Bind component props to live data | DATA_BINDING.md | |
| Handle user interactions / form submit | ACTIONS.md | |
| Build a streaming progressive UI | USAGE.md → Streaming | |
| Migrate from v0.8 to v0.9 | COMMANDS.md → v0.8 vs v0.9 | |
| Look up full prop types | API.md |
🛠 Recommended Workflow
- Define your catalog — register a local catalog or use the A2UI Basic Catalog URL.
- Register custom components — pass them via
XCard.Boxcomponentsprop. - Create the React tree — wrap surfaces with
XCard.Box, addXCard.Cardper surface. - Feed commands — push
XAgentCommand_v0_9[]intocommandsprop (typically from streaming agent response). - Handle actions — receive
ActionPayloadinonAction, update commands in response.
Minimal Working Example
tsx
import React, { useState } from 'react';import { XCard, registerCatalog } from '@ant-design/x-card';import type { XAgentCommand_v0_9, ActionPayload, Catalog } from '@ant-design/x-card';// 1. Define and register local catalogconst myCatalog: Catalog = {catalogId: 'local://my_catalog.json',components: {Text: {type: 'object',properties: { text: { type: 'string' }, variant: { type: 'string' } },required: ['text'],},Button: {type: 'object',properties: { text: { type: 'string' }, action: {} },required: ['text'],},},};registerCatalog(myCatalog);// 2. Custom component implementationsconst Text: React.FC<{ text: string; variant?: string }> = ({ text, variant }) => (<p className={`text-${variant ?? 'body'}`}>{text}</p>);const Button: React.FC<{ text: string; onAction?: (ctx: any) => void; action?: any }> = ({text,onAction,action,}) => <button onClick={() => onAction?.(action?.event?.context ?? {})}>{text}</button>;// 3. Build commands (from agent stream)const commands: XAgentCommand_v0_9[] = [{version: 'v0.9',createSurface: {surfaceId: 'welcome',catalogId: 'local://my_catalog.json',},},{version: 'v0.9',updateComponents: {surfaceId: 'welcome',components: [{ id: 'root', component: 'Column', children: ['title', 'btn'] },{ id: 'title', component: 'Text', text: { path: '/user/name' }, variant: 'h1' },{id: 'btn',component: 'Button',text: 'Start',action: { event: { name: 'start', context: {} } },},],},},{version: 'v0.9',updateDataModel: {surfaceId: 'welcome',path: '/user/name',value: 'Alice',},},];// 4. Renderexport default function App() {const [cmdQueue, setCmdQueue] = useState<XAgentCommand_v0_9[]>(commands);const handleAction = (payload: ActionPayload) => {console.log('Action:', payload.name, payload.context);// Append new commands based on agent responsesetCmdQueue((prev) => [...prev /* new commands */]);};return (<XCard.Box commands={cmdQueue} components={{ Text, Button }} onAction={handleAction}><XCard.Card id="welcome" /></XCard.Box>);}
🚨 Development Rules
- Always include `"version": "v0.9"` on every command — omitting it causes protocol rejection.
- One and only one `id: "root"` component per surface's component tree — this is the tree root.
- Flat adjacency list only — never nest component objects inside other component objects; always reference children by
idstring. - Separate structure from data —
updateComponentsfor layout,updateDataModelfor content/state. - Register catalog before mounting — call
registerCatalog()before the component tree renders. - Pass `components` map to `XCard.Box`, not to
XCard.Card— Box distributes to all Cards. - Never recreate the `components` object inline — keep it stable with
useMemoor module-level constant to avoid re-renders. - Input components require `value: { path: "..." }` for two-way binding — literal values do not update the data model.
- For streaming: append new commands to the array rather than replacing it — Card processes the diff incrementally.
- `action.event.context` paths are write targets — they point to where user-entered data lives in the data model; do not resolve them as read sources.
- Path references in action context are automatically resolved — when an action is triggered, X-Card converts
{ path: "xxx" }in the action config to{ value: "actual_value" }in the onAction payload. This works for both v0.9 (action.event.context = { key: { path } }) and v0.8 (action.context = [{ key, value: { path } }]) formats.
🤝 Skill Collaboration
| Scenario | Skill combination | |
|---|---|---|
| AI chat with structured card responses | use-x-chat + x-components + x-card | |
| Standalone agent form UI | x-card only | |
| Streaming Markdown + card side-panel | x-markdown + x-card | |
| HTTP streaming from agent into card | x-request → feed response as commands |
🔗 Reference Resources
- USAGE.md — Setup guide, streaming pattern, multi-surface examples
- COMMANDS.md — All four A2UI v0.9 command types, v0.8 vs v0.9 diff
- DATA_BINDING.md — JSON Pointer paths, dynamic types, two-way binding, template iteration
- ACTIONS.md — Action definitions, ActionPayload, form submission pattern
- CATALOG.md — Local catalog registration, remote URL loading, custom component schema
- API.md — Full TypeScript types for Box, Card, commands, catalog, actions