---
title: "React 元件"
description: "在 React 應用程式中嵌入 ThunderPhone 語音小工具"
---

`ThunderPhoneWidget` 元件會呈現具有玻璃擬態風格的通話列，內建靜音、結束通話及顯示連線狀態的控制項。這是在 React 應用程式中加入語音人工智慧功能最快的方法。

## 安裝

```bash
npm install @thunderphone/widget
```

## 基本用法

```tsx
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'

function App() {
  return (
    <ThunderPhoneWidget
      publishableKey="pk_live_your_publishable_key"
    />
  )
}
```

<Warning>
  你**必須**匯入 CSS 檔案，元件才能正確呈現。否則，元件將不會套用任何樣式。
</Warning>

---

## Props

此元件可透過 `ThunderPhoneWidgetProps` 接受以下 props：

| 屬性 | 類型 | 必填 | 預設值 | 說明 |
|------|------|----------|---------|-------------|
| `publishableKey` | `string` | 是 | -- | 控制台 **網頁小工具**中的可發布 API 金鑰（`pk_live_...`）。系統會根據金鑰的小工具設定自動解析智慧體。 |
| `theme` | `'light' \| 'dark'` | 否 | `'light'` | 色彩配置。將 `tp--light` 或 `tp--dark` 類別套用至小工具根元素。 |
| `primaryColor` | `string` | 否 | `'#000000'` (light) / `'#ffffff'` (dark) | 作為強調色使用的 CSS 色彩字串（通話按鈕、波形、啟用中的指示器）。 |
| `title` | `string` | 否 | `'Voice assistant'` | 顯示於小工具列中的文字。 |
| `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | 否 | `'bottom-right'` | 小工具在檢視區中的固定位置。 |
| `apiBase` | `string` | 否 | `'https://api.thunderphone.com/v1'` | 覆寫 API 基礎 URL。 |
| `language` | `string` | 否 | -- | 每個工作階段的語言覆寫設定——語言代碼或地區設定，例如 `en`、`es` 或 `fr-FR`。未設定時，會套用智慧體已設定的語言。需要在金鑰的[瀏覽器覆寫](/zh-Hant/guides/embed-web-widget)下設定 `language`。 |
| `voice` | `string` | 否 | -- | 每個工作階段的語音覆寫設定——語音名稱，例如 `maria`。未設定時，會套用智慧體已設定的語音。需要在金鑰的[瀏覽器覆寫](/zh-Hant/guides/embed-web-widget)下設定 `voice`。 |
| `context` | `string` | 否 | -- | 傳遞給智慧體的每個工作階段事實性頁面或網站情境（例如訪客正在瀏覽頁面的詳細資訊）。伺服器端會截斷為 12,000 個字元。需要在金鑰的[瀏覽器覆寫](/zh-Hant/guides/embed-web-widget)下設定 `context`。 |
| `onConnect` | `() => void` | 否 | -- | 語音工作階段成功連線時呼叫。 |
| `onDisconnect` | `() => void` | 否 | -- | 工作階段結束時呼叫。 |
| `onError` | `(error) => void` | 否 | -- | 發生錯誤時呼叫。`error` 物件包含 `error`（代碼）和 `message` 欄位。 |
| `className` | `string` | 否 | -- | 套用至小工具容器的額外 CSS 類別名稱。 |
| `ringtone` | `boolean \| string` | 否 | `false` | 連線時播放鈴聲。`true` 使用預設鈴聲，或使用自訂音訊的 URL 字串。 |

---

## 範例

### 深色主題搭配自訂顏色

```tsx
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'

function App() {
  return (
    <ThunderPhoneWidget
      publishableKey="pk_live_your_publishable_key"
      theme="dark"
      primaryColor="#8b5cf6"
      title="Talk to our AI"
    />
  )
}
```

### 自訂位置

```tsx
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'

function App() {
  return (
    <ThunderPhoneWidget
      publishableKey="pk_live_your_publishable_key"
      position="bottom-left"
    />
  )
}
```

### 每個工作階段的語言、語音和情境

當通話開始時，`language`、`voice` 與 `context` 屬性會轉送至工作階段請求（`POST /widget/session`），並覆寫該工作階段中智慧體已設定的預設值。在控制台中該小工具的 **瀏覽器覆寫** 下啟用你要使用的每個屬性（或在金鑰的 `allowed_overrides` 中啟用）。新建立的小工具不接受任何覆寫，而帶有未啟用覆寫的工作階段請求會以 `400 override_not_allowed` 失敗；請參閱[瀏覽器覆寫](/zh-Hant/guides/embed-web-widget)。

```tsx
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'

function PricingPageWidget() {
  return (
    <ThunderPhoneWidget
      publishableKey="pk_live_your_publishable_key"
      language="es"
      voice="maria"
      context="Page: Pricing. Plans: Starter $29/mo, Pro $99/mo. Annual billing saves 20%."
    />
  )
}
```

使用 `context` 為智慧體提供訪客目前所在頁面的事實資訊——例如產品詳細資料、定價或頁面專屬常見問題。智慧體會將其視為頁面內容，而非指令。伺服器端會將其截斷為 12,000 個字元。

### 搭配事件回呼

```tsx
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'

function SupportWidget() {
  return (
    <ThunderPhoneWidget
      publishableKey="pk_live_your_publishable_key"
      onConnect={() => {
        console.log('Voice session connected')
        analytics.track('widget_call_started')
      }}
      onDisconnect={() => {
        console.log('Voice session ended')
        analytics.track('widget_call_ended')
      }}
      onError={(error) => {
        console.error(`Widget error: ${error.error} - ${error.message}`)
      }}
    />
  )
}
```

### 搭配自訂樣式

```tsx
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'

function BrandedWidget() {
  return (
    <ThunderPhoneWidget
      publishableKey="pk_live_your_publishable_key"
      primaryColor="#4a90d9"
      className="my-custom-widget"
    />
  )
}
```

```css
.my-custom-widget .tp-button--end {
  background-color: #e74c3c;
}
```

請參閱[樣式指南](/zh-Hant/widget/styling)，瞭解所有可用的 CSS 類別和自訂屬性。

### 搭配鈴聲

建立連線時播放電話響鈴聲：

```tsx
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'

function PhoneWidget() {
  return (
    <ThunderPhoneWidget
      publishableKey="pk_live_your_publishable_key"
      ringtone={true}
    />
  )
}
```

傳入音訊檔案 URL 以使用自訂鈴聲：

```tsx
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  ringtone="https://example.com/my-ringtone.mp3"
/>
```

當小工具處於 `connecting` 狀態時，鈴聲會循環播放；智慧體連線後，鈴聲會平順淡出。

### 搭配自訂 API 基底

<Tip>
  只有在使用自行託管或代理 API 端點時，才需要設定 `apiBase`。預設值指向 `https://api.thunderphone.com/v1`。
</Tip>

```tsx
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  apiBase="https://your-proxy.example.com/v1"
/>
```

---

## 錯誤處理

觸發 `onError` 回呼時，會收到包含兩個欄位的錯誤物件：

| 欄位 | 類型 | 說明 |
|-------|------|-------------|
| `error` | `string` | 機器可讀的錯誤代碼 |
| `message` | `string` | 人類可讀的錯誤說明 |

常見錯誤代碼包括不允許的網域、找不到智慧體，以及無效的 API 金鑰。

---

## 後續步驟

<CardGroup cols={2}>
  <Card title="無介面 Hook" icon="code" href="/zh-Hant/widget/headless-hook">
    需要完全掌控 UI？改用 `useThunderPhone` Hook。
  </Card>
  <Card title="樣式設定" icon="palette" href="/zh-Hant/widget/styling">
    使用 CSS 自訂屬性自訂顏色、尺寸與版面配置。
  </Card>
</CardGroup>
