> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thunderphone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 样式

> 使用 CSS 自定义 ThunderPhone 语音小组件的外观

该小组件呈现为带有内置浅色和深色主题的毛玻璃风格栏。可通过三个层级进行自定义：用于常见选项的属性、用于主题设置的 CSS 自定义属性，以及用于完全控制的 CSS 类覆盖。

<Note>
  这些样式选项适用于由 `ThunderPhoneWidget` React 组件和 `ThunderPhone.mount()` CDN 方法渲染的预构建小组件。如果您需要完全自定义的 UI，请改用[无头 Hook](/zh/widget/headless-hook)。
</Note>

***

## 主题

`theme` 属性控制小组件的配色方案。它会将 `tp--light` 或 `tp--dark` 类应用到小组件根元素：

```tsx theme={null}
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  theme="dark"
/>
```

| 主题        | 类           | 描述              |
| --------- | ----------- | --------------- |
| `'light'` | `tp--light` | 浅色背景搭配深色文本。默认值。 |
| `'dark'`  | `tp--dark`  | 深色背景搭配浅色文本。     |

两种主题均采用带有背景模糊和细微透明效果的毛玻璃风格栏设计。

***

## CSS 自定义属性

该组件公开了可覆盖的 CSS 自定义属性（变量），让您无需修改单个类即可更改颜色。这些属性由应用于 `.tp-widget` 根元素的主题类（`.tp--light` 或 `.tp--dark`）定义：

| 属性                   | 默认值（浅色）                                 | 默认值（深色）                                  | 说明                                                         |
| -------------------- | --------------------------------------- | ---------------------------------------- | ---------------------------------------------------------- |
| `--tp-accent`        | `#000`                                  | `#fff`                                   | 强调色：开始按钮、波形条、连接圆点、已连接状态文本。通过 `primaryColor` 属性以**内联**方式设置。 |
| `--tp-bg`            | `rgba(255, 255, 255, 0.82)`             | `rgba(15, 15, 15, 0.85)`                 | 控件条背景（半透明；由 `--tp-glass` 模糊处理）。                            |
| `--tp-surface`       | `rgba(0, 0, 0, 0.04)`                   | `rgba(255, 255, 255, 0.07)`              | 静音按钮背景。                                                    |
| `--tp-surface-hover` | `rgba(0, 0, 0, 0.07)`                   | `rgba(255, 255, 255, 0.12)`              | 静音按钮悬停背景。                                                  |
| `--tp-border`        | `rgba(0, 0, 0, 0.08)`                   | `rgba(255, 255, 255, 0.1)`               | 控件条和按钮边框。                                                  |
| `--tp-border-hover`  | `rgba(0, 0, 0, 0.14)`                   | `rgba(255, 255, 255, 0.18)`              | 悬停时的边框颜色。                                                  |
| `--tp-text`          | `rgba(0, 0, 0, 0.88)`                   | `rgba(255, 255, 255, 0.95)`              | 主文本（标题、智能体名称）。                                             |
| `--tp-text-2`        | `rgba(0, 0, 0, 0.5)`                    | `rgba(255, 255, 255, 0.55)`              | 次要文本（副标题、状态行、通话计时器）。                                       |
| `--tp-glass`         | `blur(32px) saturate(180%)`             | `blur(32px) saturate(180%)`              | 在控件条上创建玻璃效果的 `backdrop-filter`。                            |
| `--tp-shadow`        | 三层阴影堆叠                                  | 三层阴影堆叠                                   | 控件条的 `box-shadow`（光环 + 近层 + 远层）。                           |
| `--tp-shadow-hover`  | 三层阴影堆叠                                  | 三层阴影堆叠                                   | 为悬停抬升效果声明；当前未被任何规则应用。                                      |
| `--tp-glow`          | `inset 0 1px 0 0 rgba(255,255,255,0.5)` | `inset 0 1px 0 0 rgba(255,255,255,0.06)` | 叠加到控件条阴影上的内部顶部高光。                                          |
| `--tp-connected`     | `#059669`                               | `#34d399`                                | 已连接状态指示器颜色（状态圆点）。                                          |
| `--tp-error`         | `#dc2626`                               | `#fb7185`                                | 错误状态文本颜色。                                                  |
| `--tp-end-bg`        | `rgba(239, 68, 68, 0.08)`               | `rgba(251, 113, 133, 0.12)`              | 结束通话按钮背景。                                                  |
| `--tp-end-color`     | `#ef4444`                               | `#fb7185`                                | 结束通话按钮图标颜色。                                                |
| `--tp-end-border`    | `rgba(239, 68, 68, 0.12)`               | `rgba(251, 113, 133, 0.15)`              | 结束通话按钮边框。                                                  |
| `--tp-end-hover`     | `rgba(239, 68, 68, 0.14)`               | `rgba(251, 113, 133, 0.2)`               | 结束通话按钮悬停背景。                                                |
| `--tp-idle-opacity`  | `0.4`                                   | `0.3`                                    | 为闲置状态变暗效果声明；当前未被任何规则应用。                                    |

### 覆盖自定义属性

通过 `primaryColor` 属性设置强调色：

```tsx theme={null}
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  primaryColor="#e11d48"
/>
```

<Warning>
  `--tp-accent` 会通过 `primaryColor` 属性设置为**内联样式**，因此在样式表中覆盖 `--tp-accent` 不会生效。请通过该属性更改强调色。其他所有自定义属性均可在 CSS 中覆盖。
</Warning>

使用 CSS 覆盖其他自定义属性。请使用双类选择器（`.tp-widget.tp--light` / `.tp-widget.tp--dark`），这样无论样式表顺序如何，您的规则都会优先于定义默认值的主题类：

```css theme={null}
.tp-widget.tp--light {
  --tp-bg: rgba(0, 0, 0, 0.9);
  --tp-text: rgba(255, 255, 255, 0.95);
  --tp-text-2: rgba(255, 255, 255, 0.55);
  --tp-border: rgba(255, 255, 255, 0.15);
}
```

***

## CSS 类

所有小部件类均以 `tp-` 为前缀，以避免与您现有的样式冲突。

| 类                             | 元素      | 说明                                                                                       |
| ----------------------------- | ------- | ---------------------------------------------------------------------------------------- |
| `.tp-widget`                  | 根包装器    | 固定定位容器（`position: fixed`，角落由 `position` 属性设置，`z-index: 9999`）。承载主题类和基础字体设置；自身不含视觉外观。     |
| `.tp--light` / `.tp--dark`    | 主题修饰符   | 与主题一起应用于 `.tp-widget`；定义所有 `--tp-*` 自定义属性。                                               |
| `.tp-bar`                     | 栏       | 玻璃拟态胶囊主体：背景、背景模糊、边框、`99px` 圆角半径和阴影。宽度为 `300px`。                                          |
| `.tp-meta`                    | 文本块     | 所有文本的容器——空闲时为标题和副标题，通话期间为智能体名称和状态。                                                       |
| `.tp-name`                    | 主标签     | 空闲时显示 `title` 属性；通话期间显示已连接智能体的名称（若无则回退使用 `title`）。                                       |
| `.tp-sub`                     | 副标题     | 空闲时显示的“当前可用”文本行。                                                                         |
| `.tp-start`                   | 空闲通话按钮  | 圆形强调色启动按钮（42px）。使用 `--tp-accent` 作为背景。                                                   |
| `.tp-dot`                     | 连接圆点    | 连接时显示在栏左侧的脉冲强调色圆点。                                                                       |
| `.tp-wave` / `.tp-wave--idle` | 波形      | 五条柱状波形。`--idle` 会添加缓慢的呼吸动画；通话期间柱状条会随音频响应。                                                |
| `.tp-button`                  | 通话中按钮   | 通话中控制按钮的基础样式（42px，12px 圆角）。                                                              |
| `.tp-button-group`            | 按钮行     | 通话期间包装静音和结束按钮。                                                                           |
| `.tp-button--start`           | 连接按钮变体  | 通话开始时显示的强调色变体。                                                                           |
| `.tp-button--mute`            | 静音切换    | 在通话期间将麦克风静音或取消静音。使用 `--tp-surface`。                                                      |
| `.tp-button--end`             | 结束通话按钮  | 挂断通话。使用 `--tp-end-*` 调色板。                                                                |
| `.tp-button--loading`         | 加载修饰符   | 连接时降低按钮亮度。                                                                               |
| `.tp-icon` / `.tp-spin`       | 图标      | 按钮图标尺寸；`tp-spin` 会为连接中的旋转指示器添加动画。                                                        |
| `.tp-status`                  | 通话中状态块  | 在连接中、已连接或错误状态下包装状态行。                                                                     |
| `.tp-status__text`            | 状态行     | 连接状态文本（例如“正在连接...”）或通话计时器。根据状态应用 `.tp-status--connected`（强调色）或 `.tp-status--error`（错误色）。 |
| `.tp-status__name`            | 智能体名称槽位 | 状态块的一部分，但不会在当前栏布局中渲染——智能体名称会显示在 `.tp-name` 中。                                            |
| `.tp-status__dot`             | 状态圆点    | 已连接状态的脉冲圆点样式（使用 `--tp-connected`）。                                                       |

***

## 示例

### 通过 Props 自定义强调色

为小组件添加品牌风格的最简单方式：

```tsx theme={null}
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  theme="light"
  primaryColor="#059669"
  title="Talk to support"
/>
```

### 通过 CSS 自定义颜色

覆盖自定义属性以完全控制颜色。请注意，强调色来自 `primaryColor` prop，而不是 CSS：

```tsx theme={null}
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  primaryColor="#059669"
/>
```

```css theme={null}
/* Emerald theme for everything else */
.tp-widget.tp--light {
  --tp-bg: rgba(236, 253, 245, 0.85);
  --tp-text: rgba(6, 78, 59, 0.95);
  --tp-text-2: rgba(4, 120, 87, 0.8);
  --tp-border: rgba(5, 150, 105, 0.2);
}
```

### 自定义尺寸

通过调整栏、按钮和文本尺寸，使小组件变大或变小：

```css theme={null}
/* Wider bar */
.tp-bar {
  width: 340px;
}

/* Larger buttons (42px by default) */
.tp-start,
.tp-button {
  width: 56px;
  height: 56px;
}

/* Larger text */
.tp-name {
  font-size: 16px;
}

.tp-sub,
.tp-status__text {
  font-size: 14px;
}
```

### 隐藏文本标签

小组件的所有文本均位于 `.tp-meta` 中。完全隐藏它，仅保留波形和按钮：

```css theme={null}
.tp-meta {
  display: none;
}
```

或者隐藏单独的部分：

```css theme={null}
/* Hide only the idle "Available now" subtitle */
.tp-sub {
  display: none;
}

/* Hide only the in-call status line (connection state / timer) */
.tp-status {
  display: none;
}
```

<Note>
  空闲标签位于 `.tp-name`/`.tp-sub` 中，而非 `.tp-status`——仅隐藏 `.tp-status` 时，小组件空闲时仍会显示标题。
</Note>

### 特定主题覆盖

使用主题类定位特定主题：

```css theme={null}
/* Only affect dark theme */
.tp--dark .tp-start {
  box-shadow: 0 0 20px rgba(255, 255, 255, 0.25);
}

/* Only affect light theme */
.tp-widget.tp--light {
  --tp-bg: rgba(255, 255, 255, 0.95);
}
```

***

## 使用 className 设定作用域

使用 React 组件时，传入 `className` prop，将覆盖规则限定到特定的小组件实例：

```tsx theme={null}
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  theme="dark"
  className="support-widget"
/>
```

然后在 CSS 中定位该类：

```css theme={null}
.support-widget.tp--dark {
  --tp-bg: rgba(30, 30, 46, 0.9);
}

.support-widget .tp-name {
  font-weight: 700;
}
```

这样您可以在同一页面上使用多个具有不同样式的小组件实例。通过各自的 `primaryColor` prop 为每个实例设置独立的强调色（CSS 无法覆盖 `--tp-accent`——它以内联方式设置）。

***

## 完全自定义 UI

如果 CSS 覆盖不足以满足需求，[无头 Hook](/zh/widget/headless-hook) 可让您完全掌控。您提供所有 HTML 和样式，而 `useThunderPhone` 负责处理语音会话。该 Hook 还提供 `audioLevelRef`，用于构建波形等音频响应式可视化效果。

```tsx theme={null}
import { useThunderPhone } from '@thunderphone/widget'

function MyWidget() {
  const phone = useThunderPhone({
    publishableKey: 'pk_live_your_publishable_key',
  })

  return (
    <div className="my-totally-custom-widget">
      {/* Your own buttons, animations, layouts -- anything */}
      <button onClick={phone.state === 'connected' ? phone.disconnect : phone.connect}>
        {phone.state === 'connected' ? 'Hang up' : 'Call us'}
      </button>
      {phone.audio}
    </div>
  )
}
```

<Tip>
  当您需要音频响应式动画、自定义布局，或与现有组件库集成时，无头 Hook 是合适的选择。CSS 覆盖和自定义属性更适合快速调整主题。
</Tip>
