组件是 ChatKit 附带的容器和组件。你可以使用预构建的组件、修改模板,或者设计你自己的组件,以便在你的产品中完全自定义 ChatKit。

快速设计组件
使用 组件构建器 ,在 ChatKit Studio 中试验卡片布局、列表行和预览组件。当你找到喜欢的设计时,将生成的 JSON 复制到你的集成中,并从你的后端提供服务。
上传资产
上传资产以自定义 ChatKit 组件,使其与你的产品相匹配。ChatKit 要求上传的文件和图片必须由你的后端托管,然后才能在消息中引用它们。请按照 Python SDK 中的上传指南 for a reference implementation.
ChatKit 组件可以直接在对话中显示上下文、快捷方式和交互式卡片。当用户点击组件按钮时,你的应用程序将收到一个自定义操作负载,以便你可以从后端进行响应。
在你的服务器上处理操作
组件操作允许用户从 UI 触发逻辑。操作可以绑定到各种组件节点上的不同事件(例如,按钮点击),然后由你的服务器或客户端集成来处理。
使用 onAction 回调或等效的 React hook 捕获组件事件。将操作负载转发到你的后端以处理操作。 WidgetsOption 需要完整的服务器示例?请参阅
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 文档 在 for an end-to-end walkthrough.
操作文档 了解更多.
参考
我们建议从上面的可视化构建器和工具开始。使用本文档的其余部分来了解组件的工作原理并查看所有选项。
组件由单个容器(WidgetRoot) 构建,该容器包含许多组件(WidgetNode).
容器 (WidgetRoot)
容器具有特定的特征,例如显示状态指示文本和主要操作。
-
Card - 一个有边界的组件容器。支持
status,confirmandcancel字段,用于在组件下方显示状态指示器和操作按钮。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” }per-side:{ 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" }per-side:{ 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" }per-side:{ 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 – 中的一个物品
ListViewwith optional action.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
-
选择 – 下拉单选输入框。
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
-
间隔 – 布局中使用的弹性空白区域。
minSize: int | str | Nonekey: str | None
-
文本 – 显示纯文本(使用
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
-
标题 – 突出的标题文本。
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
-
表单 – 可以提交 action 的布局容器。
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" }per-side:{ 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
-
过渡 – 包裹可播放动画的内容。
children: WidgetNode | Nonekey: str | None