关于 x-card
x-card 是使用 `@ant-design/x-card` 的技能;该 React 渲染器可将结构化命令呈现为 AI Agent 的交互界面。内容涵盖组件配置、目录、数据绑定、动作处理和流式渲染,并推荐使用 v0.9,同时兼容 v0.8。
主要功能
- 01在 React 中渲染 A2UI 命令
- 02管理组件目录
- 03使用 JSON Pointer 绑定数据
- 04处理用户触发的动作
- 05渐进式渲染流式命令
- 06支持 A2UI v0.8 和 v0.9
适用场景
- 01构建 Agent 驱动的表单界面
- 02渲染交互式 Agent 回复
- 03渐进式显示流式卡片界面
- 04将 A2UI 命令从 v0.8 迁移
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ ant-design/ x --skill x-card安装后在 Claude Code 中输入/x-card确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
reference/ACTIONS.mdAPI.mdCATALOG.mdCOMMANDS.mdDATA_BINDING.mdINTRODUCTION.mdUSAGE.md详细介绍
🎯 技能定位
此技能涵盖 @ant-design/x-card —— A2UI 协议的 React 实现,可让 AI Agent 通过结构化 JSON 命令流动态渲染丰富的交互式 UI。
涵盖内容:
XCard.Box+XCard.Card组件用法- A2UI v0.9 命令类型:
createSurface、updateComponents、updateDataModel、deleteSurface - 自定义组件注册与目录管理
- 通过 JSON Pointer 路径(RFC 6901)进行数据绑定
- 操作处理——将用户事件发送回 Agent
- 流式渐进式渲染模式
- v0.8 与 v0.9 协议的差异
范围:推荐使用 v0.9 协议。v0.8 仅为向后兼容而提供支持——所有新工作都应优先使用 v0.9。
目录
📦 包概览
| 包 | 职责 |
|---|---|
@ant-design/x-card | A2UI 协议的 React 渲染器——XCard.Box、XCard.Card、目录 API |
@ant-design/x | 聊天 UI 组件(Bubble、Sender 等)——不在此处涵盖 |
@ant-design/x-sdk | 数据提供程序、流式处理——不在此处涵盖 |
npm install @ant-design/x-card
导出项:
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';
// Subcomponents
XCard.Box; // Container: receives commands, owns catalog maps
XCard.Card; // Renderer: renders a single surface by id
🗂️ 组件架构
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 属性
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 属性
interface CardProps {
id: string; // surfaceId to render
}
ActionPayload
interface ActionPayload {
name: string; // from action.event.name
surfaceId: 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>;
}
🚀 快速入门决策指南
| 如果你需要…… | 首先阅读 |
|---|---|
| 设置 XCard.Box + XCard.Card | USAGE.md → 基本设置 |
| 将命令从 Agent 发送到卡片 | COMMANDS.md |
| 注册自定义组件目录 | CATALOG.md → 本地目录 |
| 将组件属性绑定到实时数据 | DATA_BINDING.md |
| 处理用户交互 / 表单提交 | ACTIONS.md |
| 构建流式渐进式 UI | USAGE.md → 流式处理 |
| 从 v0.8 迁移到 v0.9 | COMMANDS.md → v0.8 与 v0.9 |
| 查阅完整属性类型 | API.md |
🛠 推荐工作流
- 定义目录——注册本地目录,或使用 A2UI Basic Catalog URL。
- 注册自定义组件——通过
XCard.Box的components属性传入。 - 创建 React 树——用
XCard.Box包装 surfaces,并为每个 surface 添加XCard.Card。 - 传入命令——将
XAgentCommand_v0_9[]推送到commands属性(通常来自流式 Agent 响应)。 - 处理操作——在
onAction中接收ActionPayload,并相应更新命令。
最小可运行示例
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 catalog
const 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 implementations
const 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. Render
export 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 response
setCmdQueue((prev) => [...prev /* new commands */]);
};
return (
<XCard.Box commands={cmdQueue} components={{ Text, Button }} onAction={handleAction}>
<XCard.Card id="welcome" />
</XCard.Box>
);
}
🚨 开发规则
- 每个命令都必须包含
"version": "v0.9"— 省略会导致协议拒绝。 - 每个界面的组件树只能有一个
id: "root"组件 — 它是树的根节点。 - 只能使用扁平邻接列表 — 绝不要将组件对象嵌套在其他组件对象中;始终通过
id字符串引用子组件。 - 结构与数据分离 — 使用
updateComponents更新布局,使用updateDataModel更新内容/状态。 - 挂载前注册目录 — 在组件树渲染前调用
registerCatalog()。 - 将
components映射传给XCard.Box,而不是XCard.Card— Box 会将其分发给所有 Card。 - 绝不要在行内重新创建
components对象 — 使用useMemo或模块级常量保持其稳定,避免重新渲染。 - 输入组件需要
value: { path: "..." }才能实现双向绑定 — 字面值不会更新数据模型。 - 对于流式传输:将新命令追加到数组,而不是替换数组 — Card 会增量处理差异。
action.event.context路径是写入目标 — 它们指向用户输入数据在数据模型中的存储位置;不要将其解析为读取来源。- 操作上下文中的路径引用会自动解析 — 触发操作时,X-Card 会将操作配置中的
{ path: "xxx" }转换为 onAction 负载中的{ value: "actual_value" }。v0.9(action.event.context = { key: { path } })和 v0.8(action.context = [{ key, value: { path } }])格式均适用。
🤝 技能协作
| 场景 | 技能组合 |
|---|---|
| 带有结构化卡片响应的 AI 聊天 | use-x-chat + x-components + x-card |
| 独立的 Agent 表单 UI | 仅使用 x-card |
| 流式 Markdown + 卡片侧面板 | x-markdown + x-card |
| 从 Agent 向卡片进行 HTTP 流式传输 | x-request → 将响应作为命令传入 |
🔗 参考资源
- USAGE.md — 设置指南、流式传输模式、多界面示例
- COMMANDS.md — 全部四种 A2UI v0.9 命令类型,v0.8 与 v0.9 的差异
- DATA_BINDING.md — JSON Pointer 路径、动态类型、双向绑定、模板迭代
- ACTIONS.md — 操作定义、ActionPayload、表单提交模式
- CATALOG.md — 本地目录注册、远程 URL 加载、自定义组件架构
- API.md — Box、Card、命令、目录、操作的完整 TypeScript 类型
官方文档
评论
支持 Markdown