mcpField
X
x-card

x-card

github.com/ant-design设计与 UI4.8k68 次安装2 天前更新
代码仓库

关于 x-card

x-card 是使用 `@ant-design/x-card` 的技能;该 React 渲染器可将结构化命令呈现为 AI Agent 的交互界面。内容涵盖组件配置、目录、数据绑定、动作处理和流式渲染,并推荐使用 v0.9,同时兼容 v0.8。

主要功能

  1. 01在 React 中渲染 A2UI 命令
  2. 02管理组件目录
  3. 03使用 JSON Pointer 绑定数据
  4. 04处理用户触发的动作
  5. 05渐进式渲染流式命令
  6. 06支持 A2UI v0.8 和 v0.9

适用场景

  1. 01构建 Agent 驱动的表单界面
  2. 02渲染交互式 Agent 回复
  3. 03渐进式显示流式卡片界面
  4. 04将 A2UI 命令从 v0.8 迁移

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ant-design/x --skill x-card

安装后在 Claude Code 中输入/x-card确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

reference/
ACTIONS.md
API.md
CATALOG.md
COMMANDS.md
DATA_BINDING.md
INTRODUCTION.md
USAGE.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-cardA2UI 协议的 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.CardUSAGE.md → 基本设置
将命令从 Agent 发送到卡片COMMANDS.md
注册自定义组件目录CATALOG.md → 本地目录
将组件属性绑定到实时数据DATA_BINDING.md
处理用户交互 / 表单提交ACTIONS.md
构建流式渐进式 UIUSAGE.md → 流式处理
从 v0.8 迁移到 v0.9COMMANDS.md → v0.8 与 v0.9
查阅完整属性类型API.md

🛠 推荐工作流

  1. 定义目录——注册本地目录,或使用 A2UI Basic Catalog URL。
  2. 注册自定义组件——通过 XCard.Box 的 components 属性传入。
  3. 创建 React 树——用 XCard.Box 包装 surfaces,并为每个 surface 添加 XCard.Card。
  4. 传入命令——将 XAgentCommand_v0_9[] 推送到 commands 属性(通常来自流式 Agent 响应)。
  5. 处理操作——在 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