小组件是 ChatKit 自带的容器和组件。您可以使用预构建的小组件、修改模板,或设计自己的组件,以充分定制产品中的 ChatKit。

快速设计小组件
使用 ChatKit Studio 中的小组件构建器 (Widget Builder) 来试验卡片布局、列表行和预览组件。当您拥有满意的设计后,将生成的 JSON 复制到您的集成中,并由后端提供支持。
上传资源
上传资源以自定义 ChatKit 小组件,使其与您的产品风格相匹配。ChatKit 要求上传的文件和图像在被消息引用之前,必须先由您的后端托管。请参考 Python SDK 中的上传指南以获取参考实现。
ChatKit 小组件可以直接在对话中呈现上下文、快捷方式和交互式卡片。当用户点击小组件按钮时,您的应用程序会收到一个自定义操作负载 (payload),以便您可以从后端进行响应。
在服务器上处理操作
小组件操作允许用户从 UI 触发逻辑。操作可以绑定到各种小组件节点的事件(如按钮点击),然后由您的服务器或客户端集成进行处理。
使用 WidgetsOption 或相应的 React 钩子中的 onAction 回调来捕获小组件事件。将操作负载转发到您的后端以处理这些操作。
1
2
3
4
5
6
7
8
9
10
11
chatkit.setOptions({
widgets: {
async onAction(action, item) {
await fetch("/api/widget-action", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action, itemId: item.id }),
});
},
},
});需要完整的服务器示例?请查看 ChatKit Python SDK 文档获取端到端的演练。
在 操作文档中了解更多信息。
参考
我们建议从上述可视化构建器和工具开始。使用本文档的其余部分来了解小组件的工作原理并查看所有可用选项。
小组件由单个容器 (WidgetRoot) 构建,其中包含许多组件 (WidgetNode)。
容器 (WidgetRoot)
容器具有特定的特性,例如显示状态指示器文本和主要操作。
-
卡片 (Card) - 小组件的边界容器。支持
status、confirm和cancel字段,用于在小组件下方显示状态指示器和操作按钮。children: list[WidgetNode]size: “sm” | “md” | “lg” | “full” (默认: “md”)padding: float | str | dict[str, float | str] | None (键:top,right,bottom,left,x,y)background: str |{ dark: str, light: str }| Nonestatus:{ text: str, favicon?: str }|{ text: str, icon?: str }| Nonecollapsed: bool | NoneasForm: bool | Noneconfirm:{ label: str, action: ActionConfig }| Nonecancel:{ label: str, action: ActionConfig }| Nonetheme: “light” | “dark” | Nonekey: str | None
-
列表视图 (ListView) – 显示垂直的条目列表,每一项均为
ListViewItem。children: list[ListViewItem]limit: int | “auto” | Nonestatus:{ text: str, favicon?: str }|{ text: str, icon?: str }| Nonetheme: “light” | “dark” | Nonekey: str | None
组件 (WidgetNode)
支持以下小组件类型。您也可以在小组件构建器的组件部分浏览组件并使用交互式编辑器。
-
徽章 (Badge) – 用于状态或元数据的小型标签。
label: strcolor: “secondary” | “success” | “danger” | “warning” | “info” | “discovery” | Nonevariant: “solid” | “soft” | “outline” | Nonepill: bool | Nonesize: “sm” | “md” | “lg” | Nonekey: str | None
-
盒子 (Box) – 用于布局的灵活容器,支持方向、间距和样式设置。
children: list[WidgetNode] | Nonedirection: “row” | “column” | Nonealign: “start” | “center” | “end” | “baseline” | “stretch” | Nonejustify: “start” | “center” | “end” | “stretch” | “between” | “around” | “evenly” | Nonewrap: “nowrap” | “wrap” | “wrap-reverse” | Noneflex: int | str | Noneheight: float | str | Nonewidth: float | str | NoneminHeight: int | str | NoneminWidth: int | str | NonemaxHeight: int | str | NonemaxWidth: int | str | Nonesize: float | str | NoneminSize: int | str | NonemaxSize: int | str | Nonegap: int | str | Nonepadding: float | str | dict[str, float | str] | None (键:top,right,bottom,left,x,y)margin: float | str | dict[str, float | str] | None (键:top,right,bottom,left,x,y)border: int |dict[str, Any]| None (单边框:{ size: int, color?: str|{ dark: str, light: str }, style?: “solid” | “dashed” | “dotted” | “double” | “groove” | “ridge” | “inset” | “outset” },按侧边设置:{ top?: int|dict, right?: int|dict, bottom?: int|dict, left?: int|dict, x?: int|dict, y?: int|dict })radius: “2xs” | “xs” | “sm” | “md” | “lg” | “xl” | “2xl” | “3xl” | “4xl” | “full” | “100%” | “none” | Nonebackground: str |{ dark: str, light: str }| NoneaspectRatio: float | str | Nonekey: str | None
-
行 (Row) – 水平排列子组件。
children: list[WidgetNode] | Nonegap: int | str | Nonepadding: float | str | dict[str, float | str] | None (键:top,right,bottom,left,x,y)align: “start” | “center” | “end” | “baseline” | “stretch” | Nonejustify: “start” | “center” | “end” | “stretch” | “between” | “around” | “evenly” | Noneflex: int | str | Noneheight: float | str | Nonewidth: float | str | NoneminHeight: int | str | NoneminWidth: int | str | NonemaxHeight: int | str | NonemaxWidth: int | str | Nonesize: float | str | NoneminSize: int | str | NonemaxSize: int | str | Nonemargin: float | str | dict[str, float | str] | None (键:top,right,bottom,left,x,y)border: int | dict[str, Any] | None (单边框:{ size: int, color?: str | { dark: str, light: str }, style?: "solid" | "dashed" | "dotted" | "double" | "groove" | "ridge" | "inset" | "outset" },按侧边设置:{ top?: int|dict, right?: int|dict, bottom?: int|dict, left?: int|dict, x?: int|dict, y?: int|dict })radius: “2xs” | “xs” | “sm” | “md” | “lg” | “xl” | “2xl” | “3xl” | “4xl” | “full” | “100%” | “none” | Nonebackground: str |{ dark: str, light: str }| NoneaspectRatio: float | str | Nonekey: str | None
-
列 (Col) – 垂直排列子组件。
children: list[WidgetNode] | Nonegap: int | str | Nonepadding: float | str | dict[str, float | str] | None (键:top,right,bottom,left,x,y)align: “start” | “center” | “end” | “baseline” | “stretch” | Nonejustify: “start” | “center” | “end” | “stretch” | “between” | “around” | “evenly” | Nonewrap: “nowrap” | “wrap” | “wrap-reverse” | Noneflex: int | str | Noneheight: float | str | Nonewidth: float | str | NoneminHeight: int | str | NoneminWidth: int | str | NonemaxHeight: int | str | NonemaxWidth: int | str | Nonesize: float | str | NoneminSize: int | str | NonemaxSize: int | str | Nonemargin: float | str | dict[str, float | str] | None (键:top,right,bottom,left,x,y)border: int | dict[str, Any] | None (单边框:{ size: int, color?: str | { dark: str, light: str }, style?: "solid" | "dashed" | "dotted" | "double" | "groove" | "ridge" | "inset" | "outset" },按侧边设置:{ top?: int|dict, right?: int|dict, bottom?: int|dict, left?: int|dict, x?: int|dict, y?: int|dict })radius: “2xs” | “xs” | “sm” | “md” | “lg” | “xl” | “2xl” | “3xl” | “4xl” | “full” | “100%” | “none” | Nonebackground: str |{ dark: str, light: str }| NoneaspectRatio: float | str | Nonekey: str | None
-
按钮 (Button) – 灵活的动作按钮。
submit: bool | Nonestyle: “primary” | “secondary” | Nonelabel: stronClickAction: ActionConfigiconStart: str | NoneiconEnd: str | Nonecolor: “primary” | “secondary” | “info” | “discovery” | “success” | “caution” | “warning” | “danger” | Nonevariant: “solid” | “soft” | “outline” | “ghost” | Nonesize: “3xs” | “2xs” | “xs” | “sm” | “md” | “lg” | “xl” | “2xl” | “3xl” | Nonepill: bool | Noneblock: bool | Noneuniform: bool | NoneiconSize: “sm” | “md” | “lg” | “xl” | “2xl” | Nonekey: str | None
-
标题 (Caption) – 较小的辅助文本。
value: strsize: “sm” | “md” | “lg” | Noneweight: “normal” | “medium” | “semibold” | “bold” | NonetextAlign: “start” | “center” | “end” | Nonecolor: str |{ dark: str, light: str }| Nonetruncate: bool | NonemaxLines: int | Nonekey: str | None
-
日期选择器 (DatePicker) – 带有下拉日历的日期输入框。
onChangeAction: ActionConfig | Nonename: strmin: datetime | Nonemax: datetime | Noneside: “top” | “bottom” | “left” | “right” | Nonealign: “start” | “center” | “end” | Noneplaceholder: str | NonedefaultValue: datetime | Nonevariant: “solid” | “soft” | “outline” | “ghost” | Nonesize: “3xs” | “2xs” | “xs” | “sm” | “md” | “lg” | “xl” | “2xl” | “3xl” | Nonepill: bool | Noneblock: bool | Noneclearable: bool | Nonedisabled: bool | Nonekey: str | None
-
分割线 (Divider) – 水平或垂直的分隔符。
spacing: int | str | Nonecolor: str |{ dark: str, light: str }| Nonesize: int | str | Noneflush: bool | Nonekey: str | None
-
图标 (Icon) – 按名称显示图标。
name: strcolor: str |{ dark: str, light: str }| Nonesize: “xs” | “sm” | “md” | “lg” | “xl” | Nonekey: str | None
-
图像 (Image) – 显示带有可选样式、适配方式和位置的图像。
size: int | str | Noneheight: int | str | Nonewidth: int | str | NoneminHeight: int | str | NoneminWidth: int | str | NonemaxHeight: int | str | NonemaxWidth: int | str | NoneminSize: int | str | NonemaxSize: int | str | Noneradius: “2xs” | “xs” | “sm” | “md” | “lg” | “xl” | “2xl” | “3xl” | “4xl” | “full” | “100%” | “none” | Nonebackground: str |{ dark: str, light: str }| Nonemargin: int | str | dict[str, int | str] | None (键:top,right,bottom,left,x,y)aspectRatio: float | str | Noneflex: int | str | Nonesrc: stralt: str | Nonefit: “none” | “cover” | “contain” | “fill” | “scale-down” | Noneposition: “center” | “top” | “bottom” | “left” | “right” | “top left” | “top right” | “bottom left” | “bottom right” | Noneframe: bool | Noneflush: bool | Nonekey: str | None
-
列表视图 (ListView) – 显示垂直的条目列表。
children: list[ListViewItem] | Nonelimit: int | “auto” | Nonestatus: dict[str, Any] | None (形状:{ text: str, favicon?: str })theme: “light” | “dark” | Nonekey: str | None
-
列表项 (ListViewItem) –
ListView中的一个条目,支持可选操作。children: list[WidgetNode] | NoneonClickAction: ActionConfig | Nonegap: int | str | Nonealign: “start” | “center” | “end” | “baseline” | “stretch” | Nonekey: str | None
-
Markdown – 渲染 Markdown 格式的文本,支持流式更新。
value: strstreaming: bool | Nonekey: str | None
-
选择框 (Select) – 下拉单选输入框。
options: list[dict[str, str]] (每个选项:{ label: str, value: str })onChangeAction: ActionConfig | Nonename: strplaceholder: str | NonedefaultValue: str | Nonevariant: “solid” | “soft” | “outline” | “ghost” | Nonesize: “3xs” | “2xs” | “xs” | “sm” | “md” | “lg” | “xl” | “2xl” | “3xl” | Nonepill: bool | Noneblock: bool | Noneclearable: bool | Nonedisabled: bool | Nonekey: str | None
-
间隔 (Spacer) – 用于布局的灵活空白区域。
minSize: int | str | Nonekey: str | None
-
文本 (Text) – 显示纯文本(使用
Markdown进行 Markdown 渲染)。支持流式更新。value: strcolor: str |{ dark: str, light: str }| Nonewidth: float | str | Nonesize: “xs” | “sm” | “md” | “lg” | “xl” | Noneweight: “normal” | “medium” | “semibold” | “bold” | NonetextAlign: “start” | “center” | “end” | Noneitalic: bool | NonelineThrough: bool | Nonetruncate: bool | NoneminLines: int | NonemaxLines: int | Nonestreaming: bool | Noneeditable: bool | dict[str, Any] | None (当为 dict 时:{ name: str, autoComplete?: str, autoFocus?: bool, autoSelect?: bool, allowAutofillExtensions?: bool, required?: bool, placeholder?: str, pattern?: str })key: str | None
-
大标题 (Title) – 突出的标题文本。
value: strsize: “xs” | “sm” | “md” | “lg” | “xl” | “2xl” | “3xl” | “4xl” | “5xl” | Noneweight: “normal” | “medium” | “semibold” | “bold” | NonetextAlign: “start” | “center” | “end” | Nonecolor: str |{ dark: str, light: str }| Nonetruncate: bool | NonemaxLines: int | Nonekey: str | None
-
表单 (Form) – 可以提交操作的布局容器。
onSubmitAction: ActionConfigchildren: list[WidgetNode] | Nonealign: “start” | “center” | “end” | “baseline” | “stretch” | Nonejustify: “start” | “center” | “end” | “stretch” | “between” | “around” | “evenly” | Noneflex: int | str | Nonegap: int | str | Noneheight: float | str | Nonewidth: float | str | NoneminHeight: int | str | NoneminWidth: int | str | NonemaxHeight: int | str | NonemaxWidth: int | str | Nonesize: float | str | NoneminSize: int | str | NonemaxSize: int | str | Nonepadding: float | str | dict[str, float | str] | None (键:top,right,bottom,left,x,y)margin: float | str | dict[str, float | str] | None (键:top,right,bottom,left,x,y)border: int | dict[str, Any] | None (单边框:{ size: int, color?: str | { dark: str, light: str }, style?: "solid" | "dashed" | "dotted" | "double" | "groove" | "ridge" | "inset" | "outset" },按侧边设置:{ top?: int|dict, right?: int|dict, bottom?: int|dict, left?: int|dict, x?: int|dict, y?: int|dict })radius: “2xs” | “xs” | “sm” | “md” | “lg” | “xl” | “2xl” | “3xl” | “4xl” | “full” | “100%” | “none” | Nonebackground: str |{ dark: str, light: str }| Nonekey: str | None
-
过渡 (Transition) – 包裹可能具有动画效果的内容。
children: WidgetNode | Nonekey: str | None