主题与样式覆盖

theming.tsx
import { Chatkit, useChatRuntime } from '@volcengine/chatkit';
import { createMockAdapter } from '@volcengine/chatkit/adapters/mock';
import '@volcengine/chatkit/styles.css';
import { useState } from 'react';

const adapter = createMockAdapter();

// 主题:root.className 直接落在 .chatkit-wrapper 上,theme.appearance 选择实例明暗。
// token 默认声明特异性为 0,普通宿主规则即可覆盖。完整清单见本页下方。
const THEME_CSS = `
.chatkit-wrapper.theme-brand {
  --chatkit-color-primary: #6d28d9;
  --chatkit-color-primary-hover: #7c3aed;
  --chatkit-color-link: #7c3aed;
  --chatkit-color-primary-subtle: #f3edff;
  --chatkit-color-bg-subtle: #f5f0ff;
  --chatkit-color-bg-hover: #ede4ff;
  --chatkit-color-border-strong: #c4b5fd;
}
.chatkit-wrapper.theme-warm {
  --chatkit-color-bg: #fffaf3;
  --chatkit-color-bg-subtle: #fbeedd;
  --chatkit-color-bg-hover: #f7e3c8;
  --chatkit-color-border: #f1dcc0;
  --chatkit-color-border-strong: #e3bf8f;
  --chatkit-color-text: #3b2a1a;
  --chatkit-color-primary: #c2410c;
  --chatkit-color-primary-hover: #ea580c;
  --chatkit-color-link: #c2410c;
  --chatkit-radius-lg: 14px;
  --chatkit-radius-2xl: 24px;
  --chatkit-font-family: Georgia, 'Songti SC', serif;
}
/* 透明底:聊天区透出宿主页面自己的背景 */
.theme-transparent {
  background: linear-gradient(135deg, #e0f2fe 0%, #fce7f3 100%);
}
.chatkit-wrapper.theme-transparent {
  --chatkit-color-bg: transparent;
  --chatkit-color-bg-elevated: #ffffff;
  --chatkit-color-bg-subtle: rgb(255 255 255 / 70%);
}
`;

const THEMES = [
  { id: '', label: '默认' },
  { id: 'theme-brand', label: '品牌紫' },
  { id: 'theme-warm', label: '暖色大圆角' },
  { id: 'theme-dark', label: '完整深色' },
  { id: 'theme-transparent', label: '透明底' },
];

export default function Theming() {
  const runtime = useChatRuntime({ sessionId: 'mock-session-css', adapter });
  const [theme, setTheme] = useState('theme-brand');
  if (!runtime) return null;
  return (
    <div className="demo-column">
      <style>{THEME_CSS}</style>
      <div className="demo-bar">
        {THEMES.map(item => (
          <label key={item.label}>
            <input type="radio" checked={item.id === theme} onChange={() => setTheme(item.id)} /> {item.label}
          </label>
        ))}
      </div>
      <div className={`demo-main ${theme === 'theme-transparent' ? theme : ''}`}>
        <Chatkit
          runtime={runtime}
          theme={{ appearance: theme === 'theme-dark' ? 'dark' : 'inherit' }}
          root={{ className: theme }}
        />
      </div>
    </div>
  );
}
切换完整浅色与暗色主题,并覆盖单个 Chatkit 实例的 token新窗口打开

先导入一次 @volcengine/chatkit/styles.css。公开的 --chatkit-* CSS token 提供视觉默认值;组件样式在实际绘制位置读取它们。CSS 变量沿 DOM 继承,React context 则提供上传、输入框命令和渲染配置,两者不能互相代替。

输入建议的段落样式边界

输入建议的候选文字绘制在内置编辑器的真实空段落内。相同原文、宿主样式和可用宽度下,提示与 Tab 填入后的正文共用内容起点、字形、行高、换行与段落盒模型;仅候选文字使用 --chatkit-color-text-tertiary。段落 border-color: currentColor 仍使用段落自身的颜色。候选不进入文档、草稿或撤销历史,操作 chip 是段落外的原生按钮。长候选随正文高度增长,达到编辑器 max-height 后在同一视口滚动。

公开样式入口支持范围
.chatkit-composer-rich-text-area视口宽度、最小/最大高度与滚动。
.chatkit-composer-rich-text-paragraph普通块级段落的 margin、物理/逻辑 padding、border、box-sizing、宽度约束、字体、字距、缩进、对齐、大小写转换、空白/断行及水平 LTR/RTL;相对单位、响应式规则和动态主题可用。
实例 .chatkit-wrapper / root.style实例作用域类名与主题变量;正文只需定义一份样式。

不要覆盖内部 widget、CSS Module 哈希类名或 DOM 层级。若 :empty、.is-editor-empty、:has()、焦点/内容状态等让两态具有不同的几何样式,或者全局 reset 覆盖 widget,则不保证同形。flex/grid/table/float/绝对定位、多栏、竖排、CSS transform/zoom、连续几何动画、生成内容和特殊伪元素排版不在此契约内;浏览器正常缩放仍可使用。遵循下文的 CSS layer 约定。公开插槽 slots['composer.overlay'] 触发输入框下方的降级建议,物理位置不同,不适用同位置对齐保证。

输入建议的组合 Demo可切换非对称 padding/border、主题、自定义 chip 与长候选。

实例明暗与 token 作用域

Chatkit 默认浅色。通过 theme.appearance 可直接选择 light、dark 或 inherit(默认):显式模式优先于祖先;inherit 使用最近有效祖先的 data-chatkit-theme="light|dark",没有有效祖先时使用浅色。Provider 未提供显式明暗时,也可以只在外层容器上写 data-chatkit-theme,不传 theme;若 Provider 已指定明暗,实例需显式传 appearance: 'inherit' 才会重新按 DOM 祖先解析。同页并列或嵌套实例可独立选择主题,wrapper 的 color-scheme、代码高亮和内部弹层会跟随本实例。系统偏好和持久化由宿主管理。

<div data-chatkit-theme="dark">
  <Chatkit runtime={runtime} />
  <Chatkit runtime={otherRuntime} theme={{ appearance: 'light' }} />
</div>

root.className 和 root.style 直接作用到本实例的 .chatkit-wrapper。在外层容器仅声明同名 --chatkit-* 不会覆盖 wrapper 自身的默认值。可以直接在实例根节点映射宿主变量:

<Chatkit
  runtime={runtime}
  theme={{ appearance: 'dark' }}
  root={{ className: 'my-chat', style: { '--chatkit-color-link': 'var(--app-link)' } }}
/>

宿主也可用 CSS 命中 .chatkit-wrapper 覆盖公开 token;默认声明特异性为零,且处于 @layer chatkit,普通宿主规则即可覆盖:

.chatkit-wrapper.my-chat {
  --chatkit-color-bg: #101820;
  --chatkit-color-bg-elevated: #182532;
  --chatkit-color-link: #96c8ff;
  --chatkit-code-blue: #96c8ff;
}

如果聊天区背景改为 transparent,建议为 --chatkit-color-bg-elevated 提供不透明值。宿主变量不会自动影响 Chatkit;需要联动时显式将公开 token 指向宿主变量。

每个 wrapper 都声明自己的默认 token,嵌套实例也一样。因此 inherit 继承的是明暗选择,不是父实例的品牌色覆写。多个实例要共享品牌色时,将同一组宿主变量映射到各自 wrapper;只想修改一个实例时,用它自己的 root.className 或 root.style。

公开入口与 context 边界

“从包根导出”不代表组件可以在任意位置独立使用:

入口放置方式与主题边界
Chatkit创建实例 wrapper。root.className/style 作用于这个节点,theme.appearance 选择明暗。
SessionList可独立于 Chatkit 和 Provider 使用;始终需要受控 sessions 数组和 onSelect。自建 wrapper,有 Provider 时读取其主题,否则继承最近 DOM 祖先的主题。空数组仍保留 wrapper。
AttachmentButton、VoiceInput可放入 Chatkit 插槽;要在聊天区外操作输入框时,放在同一个 ChatkitProvider 下,并保留已挂载的 Chatkit 输入框。外置时自建主题 wrapper;附件还需要 Provider 配置 features.attachments.upload。
TooltipIconButton可以不依赖 Provider 独立渲染;在 Chatkit context 外自建 wrapper,按最近 DOM 祖先解析明暗,不读取 Provider 的显式 theme。其 className/style 传给按钮,不是 wrapper。
ComposerAddAttachment、StaticMarkdownText读取 Chatkit 内部 context,通过 Chatkit 插槽或消息渲染器使用。只有外层 ChatkitProvider 或手工加一个 CSS wrapper 都不够。
Flow 渲染辅助组件不自动创建独立主题 wrapper;放在 Chatkit 的消息渲染器内使用。包含 Markdown 的渲染路径还会读取内部 context,不能按任意位置的独立组件接入。

ChatkitProvider 自身不创建主题 DOM 边界。它把 theme 和 root 作为内部 Chatkit 的默认配置;实例显式提供同名配置时整体替换,不深合并 root.style。Provider 的 root 不会复制给外置列表、附件或语音按钮。外置组件的品牌色覆写也要命中它们自己的 wrapper,见独立组件接入。

例如,DOM 祖先为 dark、Provider 显式为 light 时,外置列表和附件按钮使用 light;内部 Chatkit 若显式设置 theme={{ appearance: 'inherit' }},则重新跟随自己的 DOM 祖先而使用 dark。不要把 Provider 的默认配置当成强制覆盖所有后代的主题。

附件菜单与 Portal

通过 Chatkit 插槽使用 ComposerAddAttachment 时,菜单使用实例内 Portal,挂在所属 wrapper 内,读取该实例的浅暗默认值和局部 token。同页多个实例的菜单分别跟随各自主题。

请通过公开的组件和插槽接入,不要手工拼装内部 Provider 或把菜单节点移到 document.body;脱离所属 wrapper 后,局部 token 和组件样式无法自动跟随。在聊天区外选择文件应使用 AttachmentButton。接入代码和键盘操作见附件页。

常用 token 的实际用途

token影响范围
--chatkit-color-primary / --chatkit-color-primary-hover主操作及悬停色;primary 不自动生成 hover 或 link 颜色。
--chatkit-color-link链接按钮、会话列表链接和富文本 tag 等强调色;不控制 Markdown 正文外链。
--chatkit-color-link-subtle文件 chip 悬停边框。
--chatkit-color-text-tertiary弱文字、Flow 文案和 Markdown 正文外链。
--chatkit-color-bg-elevated输入框、建议面板等抬升表面。
--chatkit-color-tooltip-bg / --chatkit-color-tooltip-textTooltip 背景与前景;暗色默认前景不依赖可透明的实例背景。
--chatkit-line-height-tooltip / --chatkit-line-height-tooltip-mini普通与 mini Tooltip 的独立行高。
--chatkit-shadow-focus普通模式下,基础 Button、发送/停止及下述六个内置按钮的键盘焦点阴影;不是所有按钮共用的唯一焦点入口。

键盘焦点与强制颜色模式

以下六个内置按钮共用下述键盘焦点样式:

场景按钮
输入框附件菜单添加附件触发器(1 个)
附件图片预览关闭、上一张、下一张(3 个)
会话提示条详情展开/收起、操作按钮(2 个)

普通浅色或暗色模式下,这六个按钮在 :focus-visible 使用 --chatkit-shadow-focus 取代浏览器原生 outline。默认表达式为 0 0 0 2px var(--chatkit-color-bg), 0 0 0 5px var(--chatkit-color-primary):背景色形成 2px 间隔,主操作色形成向外延伸至 5px 的外环。浅色默认背景/主色为 #fff / #101013,暗色为 #16171b / #e8e9ee。该 token 控制键盘焦点标记,不改变按钮的尺寸或非焦点态配色。

宿主可以按实例覆写,例如:

.chatkit-wrapper.my-chat {
  --chatkit-shadow-focus: 0 0 0 2px var(--chatkit-color-bg), 0 0 0 5px #9cbcff;
}

在 forced-colors: active 下,这六个按钮改用 outline: 2px solid Highlight 和 outline-offset: 2px。Highlight 是用户系统调色板中的颜色,不能理解为固定品牌色。此模式下浏览器将 box-shadow 计算为 none,因此只覆写阴影 token 不能替换系统色轮廓;该差异是为了保留焦点标记。参见 CSS Color Adjustment 规范。

上述系统色 outline 仅用于列出的六个按钮。基础 Button 及依赖它的控件(如语音按钮)没有同样的强制颜色兜底;仅靠 --chatkit-shadow-focus 的控件在该模式下可能失去焦点标记,需要宿主按使用场景补充可见的 outline。外置 AttachmentButton 则使用 2px solid var(--chatkit-color-link)、1px 间隔的 outline,它是独立的文件选择按钮,并非这里的附件菜单触发器。对强制颜色模式有要求时,请在目标环境检查用到的控件。

公开 token 默认值

表格由源码生成。暗色列未单独覆写的字体、尺寸及动效沿用浅色值;焦点环使用相同表达式,颜色随当前实例的背景与主操作色变化。阴影、图片遮罩、成功/警告/错误提示、diff、代码高亮、滚动条、流光及内置文件图标均可覆盖。

下表列出可覆写的公开值,具体消费范围以上文为准。使用相同 token 的控件会共同变化;独立定义的颜色不会自动互相推导。

类别token浅色默认值暗色默认值
文字、表面与操作--chatkit-color-text#101013#e8e9ee
文字、表面与操作--chatkit-color-text-strong#1d2129#fff
文字、表面与操作--chatkit-color-text-secondary#383740#c3c5cc
文字、表面与操作--chatkit-color-text-tertiary#7a7880#a5a8b2
文字、表面与操作--chatkit-color-text-inverse#fff#16171b
文字、表面与操作--chatkit-color-text-disabled#b8b7c3#8a8e99
文字、表面与操作--chatkit-color-text-placeholder#9a9fa7#989ca8
文字、表面与操作--chatkit-color-bg#fff#16171b
文字、表面与操作--chatkit-color-bg-subtle#f6f6fc#22242a
文字、表面与操作--chatkit-color-bg-hover#f1f2f9#2b2e36
文字、表面与操作--chatkit-color-bg-disabled#ebebf5#2b2e36
文字、表面与操作--chatkit-color-border#e5e6eb#3b404a
文字、表面与操作--chatkit-color-border-strong#d2d1e0#555b68
文字、表面与操作--chatkit-color-bg-elevatedvar(--chatkit-color-bg)#22242a
文字、表面与操作--chatkit-color-tooltip-bg#1d2129var(--chatkit-color-text)
文字、表面与操作--chatkit-color-tooltip-text#fff#16171b
文字、表面与操作--chatkit-color-send-disabled-tip-bgvar(--chatkit-color-primary)var(--chatkit-color-bg-disabled)
文字、表面与操作--chatkit-color-send-disabled-tip-icon#fffvar(--chatkit-color-text-disabled)
文字、表面与操作--chatkit-color-primary#101013#e8e9ee
文字、表面与操作--chatkit-color-primary-hover#24262a#fff
文字、表面与操作--chatkit-color-link#2f79ff#8dbbff
文字、表面与操作--chatkit-color-link-subtlergb(93 155 255)#b3d2ff
文字、表面与操作--chatkit-color-primary-subtlergb(245 247 255)#1e2a44
状态--chatkit-color-dangeroklch(63.7% 0.237 25.331)#ff8d86
状态--chatkit-color-danger-strongoklch(57.7% 0.245 27.325)#ffb1a9
状态--chatkit-color-errorrgb(217 45 84)#ff8fa2
状态--chatkit-color-error-subtlergb(255 245 247)#3b202b
状态--chatkit-color-error-borderrgb(255 168 185)#844251
图标--chatkit-color-icon#42464e#c3c5cc
图标--chatkit-color-icon-muted#737a87#a5a8b2
图标--chatkit-color-icon-strong#272e3b#e8e9ee
图标--chatkit-color-icon-remove-bg#3f3f51#555b68
图标--chatkit-color-icon-on-strong#fff#16171b
文件图标--chatkit-color-file-outline#d0d5dd#748092
文件图标--chatkit-color-file-doc#155eef#79aaff
文件图标--chatkit-color-file-slide#e62e05#ff816b
文件图标--chatkit-color-file-sheet#079455#68d9a1
文件图标--chatkit-color-file-pdf#d92d20#ff8f85
文件图标--chatkit-color-file-other#7f56d9#b9a0ff
文件图标--chatkit-color-file-text#475467#aebaca
文件图标--chatkit-color-file-label#fff#16171b
文字、表面与操作--chatkit-color-shimmer-highlight#eeedf3#505562
文字、表面与操作--chatkit-color-scrollbar-thumb#d7daea#555b68
状态--chatkit-color-success#16a34a#7de2a0
状态--chatkit-color-success-subtlergb(240 250 244)#193526
状态--chatkit-color-success-borderrgb(186 230 204)#3f7554
状态--chatkit-color-warning#8a5a00#ffd16a
状态--chatkit-color-warning-subtlergb(255 249 237)#3b2f1c
状态--chatkit-color-warning-borderrgb(250 220 160)#8f6b2e
状态--chatkit-color-notice-error-subtlergb(255 243 242)#3b2327
状态--chatkit-color-notice-error-borderrgb(250 200 196)#87444a
Diff--chatkit-color-diff-add#2a814b#7de2a0
Diff--chatkit-color-diff-add-bg#edf8f0#193526
Diff--chatkit-color-diff-delete#a42a22#ff9b91
Diff--chatkit-color-diff-delete-bg#fff0ef#3b2327
预览--chatkit-color-preview-overlayrgb(29 33 41 / 60%)rgb(0 0 0 / 80%)
预览--chatkit-color-preview-controlrgb(28 31 35 / 56%)rgb(15 17 22 / 85%)
预览--chatkit-color-preview-text#fff#fff
预览--chatkit-color-preview-text-mutedrgb(255 255 255 / 72%)rgb(255 255 255 / 78%)
代码高亮--chatkit-code-text#24292e#e1e4e8
代码高亮--chatkit-code-text-muted#586069#d1d5da
代码高亮--chatkit-code-text-faint#6a737d#9da3ad
代码高亮--chatkit-code-blue#005cc5#79b8ff
代码高亮--chatkit-code-blue-strong#032f62#9ecbff
代码高亮--chatkit-code-green#22863a#85e89d
代码高亮--chatkit-code-purple#6f42c1#b392f0
代码高亮--chatkit-code-red#b31d28#f97583
代码高亮--chatkit-code-red-strong#d73a49#fdaeb7
代码高亮--chatkit-code-orange#e36209#ffab70
代码高亮--chatkit-code-bg#fff#24292e
代码高亮--chatkit-code-bg-subtle#f6f8fa#2f363d
代码高亮--chatkit-code-bg-muted#fafbfc#2f363d
代码高亮--chatkit-code-diff-add-bg#f0fff4#144620
代码高亮--chatkit-code-diff-delete-bg#ffeef0#86181d
代码高亮--chatkit-code-diff-change-bg#ffebda#c24e00
代码高亮--chatkit-code-inverse-text#fafbfc#dbedff
阴影--chatkit-shadow-button0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 1px 2px 0 rgb(0 0 0 / 5%)0 1px 2px rgb(0 0 0 / 28%)
阴影--chatkit-shadow-focus0 0 0 2px var(--chatkit-color-bg), 0 0 0 5px var(--chatkit-color-primary)0 0 0 2px var(--chatkit-color-bg), 0 0 0 5px var(--chatkit-color-primary)
阴影--chatkit-shadow-list-button0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0) var(--chatkit-gray-200), 0 1px 3px 0 rgb(0 0 0 / 10%), 0 1px 2px -1px rgb(0 0 0 / 10%)0 0 0 1px var(--chatkit-gray-200), 0 1px 3px rgb(0 0 0 / 35%), 0 1px 2px rgb(0 0 0 / 25%)
阴影--chatkit-shadow-card0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 1px 3px 0 rgb(0 0 0 / 10%), 0 1px 2px -1px rgb(0 0 0 / 10%)0 1px 3px rgb(0 0 0 / 35%), 0 1px 2px rgb(0 0 0 / 25%)
阴影--chatkit-shadow-card-hover0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 4px 6px -1px rgb(0 0 0 / 10%), 0 2px 4px -2px rgb(0 0 0 / 10%)0 4px 6px rgb(0 0 0 / 35%), 0 2px 4px rgb(0 0 0 / 25%)
阴影--chatkit-shadow-composer0 1px 3px rgb(0 0 0 / 4%)0 1px 3px rgb(0 0 0 / 25%)
阴影--chatkit-shadow-menu0 0 32px rgb(205 213 222 / 42%)0 0 32px rgb(0 0 0 / 45%)
阴影--chatkit-shadow-tooltip0 4px 10px rgb(0 0 0 / 10%)0 2px 8px rgb(0 0 0 / 40%)
阴影--chatkit-shadow-popover0 12px 32px -4px rgb(0 0 0 / 10%), 0 4px 12px rgb(0 0 0 / 6%)0 12px 32px -4px rgb(0 0 0 / 40%), 0 4px 12px rgb(0 0 0 / 30%)
阴影--chatkit-shadow-mention0 15px 35px -2px rgb(0 0 0 / 5%), 0 5px 15px rgb(0 0 0 / 5%)0 15px 35px -2px rgb(0 0 0 / 35%), 0 5px 15px rgb(0 0 0 / 30%)
阴影--chatkit-shadow-navigation0 8px 30px rgb(29 33 41 / 14%)0 8px 30px rgb(0 0 0 / 40%)
阴影--chatkit-shadow-chip0 4px 12px rgb(31 35 41 / 8%), 0 1px 2px rgb(31 35 41 / 6%)0 4px 12px rgb(0 0 0 / 35%), 0 1px 2px rgb(0 0 0 / 25%)
阴影--chatkit-shadow-chip-imagedrop-shadow(0 2px 4px rgb(31 35 41 / 14%))drop-shadow(0 2px 4px rgb(0 0 0 / 45%))
阴影--chatkit-shadow-chip-image-hoverdrop-shadow(0 3px 6px rgb(31 35 41 / 20%))drop-shadow(0 3px 6px rgb(0 0 0 / 50%))
阴影--chatkit-shadow-panel-8px 0 24px rgb(0 0 0 / 8%)-8px 0 24px rgb(0 0 0 / 35%)
阴影--chatkit-shadow-small-popover0 4px 12px rgb(0 0 0 / 8%)0 4px 12px rgb(0 0 0 / 35%)
阴影--chatkit-shadow-popover-compact0 6px 20px rgb(0 0 0 / 10%)0 6px 20px rgb(0 0 0 / 40%)
灰阶--chatkit-gray-50oklch(98.5% 0.002 247.839)#1c1d22
灰阶--chatkit-gray-100oklch(96.7% 0.003 264.542)#24262b
灰阶--chatkit-gray-200oklch(92.8% 0.006 264.531)#343740
灰阶--chatkit-gray-300oklch(87.2% 0.01 258.338)#484c57
灰阶--chatkit-gray-400oklch(70.7% 0.022 261.325)#868c98
灰阶--chatkit-gray-500oklch(55.1% 0.027 264.364)#9297a2
灰阶--chatkit-gray-600oklch(44.6% 0.03 256.802)#b8bcc6
灰阶--chatkit-gray-800oklch(27.8% 0.033 256.848)#dce0e8
灰阶--chatkit-gray-900oklch(21% 0.034 264.665)#f2f4f8
字体--chatkit-font-familyui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'
字体--chatkit-font-family-monoui-monospace, 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New', monospaceui-monospace, 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New', monospace
字体--chatkit-font-size-xs0.75rem0.75rem
字体--chatkit-font-size-sm0.875rem0.875rem
字体--chatkit-font-size-base1rem1rem
字体--chatkit-font-size-body14px14px
字体--chatkit-line-height-xscalc(1 / 0.75)calc(1 / 0.75)
字体--chatkit-line-height-smcalc(1.25 / 0.875)calc(1.25 / 0.875)
字体--chatkit-line-height-tooltip22px22px
字体--chatkit-line-height-tooltip-mini22px22px
字体--chatkit-line-height-basecalc(1.5 / 1)calc(1.5 / 1)
字体--chatkit-line-height-relaxed1.6251.625
字体--chatkit-letter-spacing-tight-0.025em-0.025em
字体--chatkit-font-weight-normal400400
字体--chatkit-font-weight-medium500500
字体--chatkit-font-weight-semibold600600
字体--chatkit-font-weight-bold700700
字体--chatkit-font-weight-extrabold800800
尺寸--chatkit-spacing0.25rem0.25rem
尺寸--chatkit-radius-md0.375rem0.375rem
尺寸--chatkit-radius-lg0.5rem0.5rem
尺寸--chatkit-radius-2xl1rem1rem
动效--chatkit-composer-glow-from#9fb3f3#9fb3f3
动效--chatkit-composer-glow-to#ff9598#ff9598
动效--chatkit-composer-glow-rest#e2e5f1#e2e5f1
动效--chatkit-composer-glow-duration10s10s
尺寸--chatkit-radius-tooltip2pxvar(--chatkit-radius-md)
尺寸--chatkit-radius-send-disabled-tip9999px9999px
尺寸--chatkit-spacing-tooltip8px 12px4px 8px
尺寸--chatkit-spacing-tooltip-mini4px 12px4px 8px
尺寸--chatkit-welcome-max-width42rem42rem
动效--chatkit-duration-fast150ms150ms
动效--chatkit-ease-standardcubic-bezier(0.4, 0, 0.2, 1)cubic-bezier(0.4, 0, 0.2, 1)
动效--chatkit-ease-outcubic-bezier(0, 0, 0.2, 1)cubic-bezier(0, 0, 0.2, 1)

样式覆盖的边界

使用公开 token 覆写实际消费它的组件样式。宿主若有更高的文字对比度要求,应结合实际背景调整前景色;例如 Markdown 正文外链使用 --chatkit-color-text-tertiary,链接按钮使用 --chatkit-color-link,两者需要分别设置。

--chatkit-session-max-width、--chatkit-flow-diff-code-width、--chatkit-flow-diff-line-bg、--chatkit-runtime-shimmer-position 等运行时变量不属于公开主题契约;自定义插槽与宿主图片由宿主自行配色。

--chatkit-color-link-subtle 用于文件 chip 悬停边框。Flow 与会话导航中的部分局部字体族使用固定列表,覆写通用 --chatkit-font-family / --chatkit-font-family-mono 不会改掉这些声明。宿主自定义图片、图标、插槽、Shiki 主题和第三方 KaTeX 样式也不会自动主题化;公开 token 表不等于全部 CSS 属性都可配置。

浏览器与宿主兼容性

图片预览、建议面板、附件菜单与 Tooltip 都挂在各自 wrapper 内并继承 token。使用 fixed 定位的浮层会受祖先样式影响:transform、filter 或会建立定位包含块的 contain 值可能改变其定位基准。自定义布局时,注意菜单和预览是否被祖先裁切或偏移。

系统强制颜色模式可以覆盖品牌配色,显示效果由系统调色板决定。需要高对比度支持时,请在目标系统中检查实际使用的控件,尤其是依赖阴影显示焦点的按钮;仅覆写颜色或阴影 token 不能替代系统色 outline。

在 Safari 或移动浏览器接入时,应结合目标设备确认主题切换、浮层位置和键盘或触摸操作。文件选择、麦克风权限以及上传、鉴权和语音服务有各自的平台与业务条件,主题配置只负责界面样式。附件交互见附件,文件存储见接入文件服务和 TOS,语音服务见语音输入。

级联层 @layer chatkit

Chatkit 的样式都在 @layer chatkit 里。同源的普通样式表声明中,未进层的全局样式(Tailwind v3 preflight、normalize、全局组件库 CSS 等)优先级高于层内声明,可能覆盖组件外观;!important 声明的层序相反。把全局 reset 实际放进排在 chatkit 前面的 reset 层即可。层的先后按首次出现的顺序确定。层序声明应放在导入 @volcengine/chatkit/styles.css 之前;在同一 CSS 文件中使用 @import 时,先写层序声明,再写 import,最后写其他样式规则:

@layer reset, chatkit;
@import url('@volcengine/chatkit/styles.css');
@layer reset {
  /* 全局 reset / normalize */
}