---
title: "스타일링"
description: "CSS로 ThunderPhone 음성 위젯의 모양을 맞춤 설정합니다"
---

위젯은 기본 제공 라이트 및 다크 테마가 적용된 글래스모피즘 바 형태로 렌더링됩니다. 사용자 지정은 세 가지 수준에서 가능합니다. 일반 옵션에는 props를 사용하고, 테마에는 CSS 사용자 지정 속성을 사용하며, 완전한 제어에는 CSS 클래스 재정의를 사용합니다.

<Note>
  이러한 스타일링 옵션은 `ThunderPhoneWidget` React 컴포넌트와 `ThunderPhone.mount()` CDN 메서드로 렌더링되는 사전 구축 위젯에 적용됩니다. 완전히 사용자 지정된 UI가 필요하면 대신 [헤드리스 훅](/ko/widget/headless-hook)을 사용합니다.
</Note>

---

## 테마

`theme` prop은 위젯의 색상 구성을 제어합니다. 위젯 루트에 `tp--light` 또는 `tp--dark` 클래스를 적용합니다.

```tsx
<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` prop에서 **인라인**으로 설정됩니다. |
| `--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` | 3계층 그림자 스택 | 3계층 그림자 스택 | 바의 `box-shadow`(링 + 근거리 + 원거리 계층)입니다. |
| `--tp-shadow-hover` | 3계층 그림자 스택 | 3계층 그림자 스택 | 호버 시 높이감을 위해 선언되었으며, 현재 어떤 규칙에도 적용되지 않습니다. |
| `--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` prop을 통해 강조 색상을 설정합니다.

```tsx
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  primaryColor="#e11d48"
/>
```

<Warning>
  `--tp-accent`는 `primaryColor` prop에서 **인라인 스타일**로 설정되므로, `--tp-accent`의 스타일시트 재정의는 적용되지 않습니다. prop으로 강조 색상을 변경하십시오. 다른 모든 사용자 지정 속성은 CSS에서 재정의할 수 있습니다.
</Warning>

CSS로 다른 사용자 지정 속성을 재정의합니다. 스타일시트 순서와 관계없이 기본값을 정의하는 테마 클래스보다 규칙의 우선순위를 높이려면 두 클래스 선택자(`.tp-widget.tp--light` / `.tp-widget.tp--dark`)를 사용하십시오.

```css
.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` prop으로 설정한 모서리, `z-index: 9999`). 테마 클래스와 기본 글꼴 설정을 포함하며, 자체적인 시각적 장식은 없습니다. |
| `.tp--light` / `.tp--dark` | 테마 수정자 | 테마와 함께 `.tp-widget`에 적용되며, 모든 `--tp-*` 사용자 정의 속성을 정의합니다. |
| `.tp-bar` | 바 | 글래스모피즘 필 자체입니다. 배경, 배경 흐림, 테두리, `99px` 반경 및 그림자를 포함합니다. 너비는 `300px`입니다. |
| `.tp-meta` | 텍스트 블록 | 모든 텍스트를 담는 컨테이너입니다 -- 대기 중에는 제목과 부제목, 통화 중에는 에이전트 이름과 상태를 표시합니다. |
| `.tp-name` | 기본 레이블 | 대기 중에는 `title` prop을 표시하고, 통화 중에는 연결된 에이전트의 이름을 표시합니다(`title`로 대체 가능). |
| `.tp-sub` | 부제목 | 대기 중에 표시되는 "현재 이용 가능" 문구입니다. |
| `.tp-start` | 대기 중 통화 버튼 | 원형 강조 시작 버튼(42px)입니다. 배경으로 `--tp-accent`를 사용합니다. |
| `.tp-dot` | 연결 점 | 연결 중에 바 왼쪽에 표시되는 맥동 강조 점입니다. |
| `.tp-wave` / `.tp-wave--idle` | 파형 | 5개 막대로 구성된 파형입니다. `--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
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  theme="light"
  primaryColor="#059669"
  title="Talk to support"
/>
```

### CSS를 통한 사용자 지정 색상

전체 색상을 제어하려면 사용자 지정 속성을 재정의합니다. 강조 색상은 CSS가 아니라 `primaryColor` prop에서 가져온다는 점을 기억하세요.

```tsx
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  primaryColor="#059669"
/>
```

```css
/* 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
/* 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
.tp-meta {
  display: none;
}
```

또는 개별 요소를 숨길 수 있습니다.

```css
/* 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-status`가 아니라 `.tp-name`/`.tp-sub`에 있습니다. `.tp-status`만 숨겨도 위젯이 유휴 상태일 때 제목은 계속 표시됩니다.
</Note>

### 테마별 재정의

테마 클래스를 사용하여 특정 테마를 대상으로 지정합니다.

```css
/* 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
<ThunderPhoneWidget
  publishableKey="pk_live_your_publishable_key"
  theme="dark"
  className="support-widget"
/>
```

그런 다음 CSS에서 해당 클래스를 대상으로 지정합니다.

```css
.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 재정의만으로 충분하지 않다면 [헤드리스 훅](/ko/widget/headless-hook)을 사용하여 완전히 제어할 수 있습니다. 모든 HTML과 스타일링은 직접 제공하고, `useThunderPhone`이 음성 세션을 처리합니다. 이 훅은 파형과 같은 오디오 반응형 시각화를 구축할 수 있도록 `audioLevelRef`도 제공합니다.

```tsx
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>
  오디오 반응형 애니메이션, 사용자 지정 레이아웃 또는 기존 컴포넌트 라이브러리와의 통합이 필요한 경우 헤드리스 훅이 적합합니다. 빠른 테마 조정에는 CSS 재정의와 사용자 지정 속성이 더 적합합니다.
</Tip>
