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

# Theming

> Style the Callers call widget with a WidgetThemeConfig: colors, fonts, sizes, radii and launcher position, at load time or at runtime.

The widget's look is controlled by one JSON object, a `WidgetThemeConfig`. You pick a `light` or `dark` base and override only what you need; everything you leave out comes from the base. The same object works in the dashboard, in the script tag and in code.

```javascript theme={"dark"}
new CallersWebSdk.WebCall({
  token,
  theme: {
    base: 'light',
    fab: { backgroundColor: '#0f766e', text: 'Ask us anything' },
    answers: { button: { background: '#0f766e', radius: 'full' } },
  },
});
```

> [!TIP]
>
> Prefer building themes visually? The dashboard has a theme builder, and the theme you save on the agent applies to every installation automatically. See [Styling the widget](https://docs.callers.ai/documentation/widget-agents/styling-the-widget.md).

## Which theme wins

1. A theme passed in code: `theme` in the config, `data-theme` on the script tag, or a later `setTheme()` call.
2. The theme saved on the agent in the dashboard, fetched when the widget loads.
3. **Default Light**.

So you can set the theme once on the agent, and override it in code only on sites that need something different. Once you pass a theme in code (or call `setTheme()`), the dashboard theme no longer applies to that instance.

The launcher label follows its own order: `fabText` in the config, then the theme's `fab.text`, then an icon-only button.

## Set a theme

```html Script tag (shorthand) theme={"dark"}
<script src="https://cdn.callers.ai/sdk.js" data-agent="YOUR_AGENT_ID" data-theme="dark"></script>
```

```html Script tag (full theme) theme={"dark"}
<script
  src="https://cdn.callers.ai/sdk.js"
  data-agent="YOUR_AGENT_ID"
  data-theme='{"base":"dark","fab":{"backgroundColor":"#1930a3"}}'
></script>
```

```javascript Code theme={"dark"}
const { WebCall, DEFAULT_DARK_THEME } = window.CallersWebSdk;

new WebCall({
  token,
  theme: { ...DEFAULT_DARK_THEME, fab: { backgroundColor: '#1930a3' } },
});
```

`DEFAULT_LIGHT_THEME` and `DEFAULT_DARK_THEME` are the exported starting points (`{ base: 'light', name: 'Default Light' }` and `{ base: 'dark', name: 'Default Dark' }`).

![The widget's pre-call card rendered with the Default Light and Default Dark themes](https://mintcdn.com/voxiaai/wqnSuR-gwKpmU86L/images/documentation/sdk/widget-themes-light-dark.png?fit=max\&auto=format\&n=wqnSuR-gwKpmU86L\&q=85\&s=b6a506a478ec841c888b5ccb56754462)

The two base palettes on the pre-call card. Every override in your theme sits on top of one of them.

## Change the theme at runtime

`setTheme()` replaces the whole theme immediately, even mid-call. Values you leave out go back to the base palette, so pass the complete theme each time.

```javascript theme={"dark"}
const brand = { fab: { backgroundColor: '#0f766e' } };

matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
  webCall.setTheme({ base: event.matches ? 'dark' : 'light', ...brand });
});
```

## Launcher position

Position is set outside the theme, so it also works on top of the dashboard theme:

```javascript theme={"dark"}
new WebCall({ token, launcherPosition: 'bottom-left', launcherOffset: 32 });
```

```html theme={"dark"}
<script src="https://cdn.callers.ai/sdk.js" data-agent="YOUR_AGENT_ID"
  data-launcher-position="top-right" data-launcher-offset="16"></script>
```

| Option | Values | Default |
| - | - | - |
| `launcherPosition` / `data-launcher-position` | `bottom-right`, `bottom-left`, `top-right`, `top-left` | `bottom-right` |
| `launcherOffset` / `data-launcher-offset` | 0–200 px from both edges | `24` |

![Two page mockups with the Talk to us launcher in the bottom-right and top-left corners](https://mintcdn.com/voxiaai/UGuY0UNIphM-6pUX/images/documentation/sdk/widget-launcher-positions.png?fit=max\&auto=format\&n=UGuY0UNIphM-6pUX\&q=85\&s=ec35fc1a61aac4b79fc7117e24f3539f)

The launcher in the default corner and in the top-left corner. The call window opens from the same corner.

The call window opens from the same corner. To place the call UI inside your layout instead, use `containerId` (see [Configuration](https://docs.callers.ai/sdk/configuration.md#widget-ui)).

## `WidgetThemeConfig` reference

Every field except `base` is optional. Colors accept any CSS color: hex, `rgb()`, `rgba()` or a named color.

### Top level

**base** `'light' | 'dark'` *required*

The palette everything else layers onto.

**name** `string`

A label for your own reference.

**font.family** `string` (default: Inter)

`Inter`, `system` (the device's UI font), or any font family your page already loads.

### Launcher: `fab`

| Field | Type | Description |
| - | - | - |
| `fab.backgroundColor` | color | Round button background (the icon badge on a labeled launcher) |
| `fab.iconColor` | color | Phone icon color |
| `fab.text` | string | Launcher label. Empty for an icon-only button. |
| `fab.collapsedBackground` | color | Background of the labeled pill |
| `fab.textColor` | color | Label color |

### Call window: `sections`

| Field | Description |
| - | - |
| `sections.header.background`, `.text`, `.icon`, `.border` | The header bar |
| `sections.chat.background` | The conversation area |
| `sections.bottom.background`, `.border` | The composer bar |
| `sections.precall.ctaButtonBackground`, `.ctaButtonText` | The **Voice Call** button on the pre-call card |
| `sections.precall.frostBackground` | The frosted close button |
| `sections.precall.connectingBackground` | The connecting indicator |
| `sections.precall.finishedBackground` | The divider shown after a call ends |

The hang-up button always stays red.

### Agent side: `questions`

| Field | Type | Default |
| - | - | - |
| `questions.titles.fontSize` | `sm` \| `md` \| `lg` | `md` |
| `questions.titles.align` | `left` \| `center` | `left` |
| `questions.titles.color`, `.secondaryColor` | color | from base |
| `questions.agentBubble.background`, `.text`, `.border` | color | from base |
| `questions.agentBubble.fontSize` | `sm` \| `md` \| `lg` | `md` |
| `questions.agentBubble.align` | `left` \| `center` | `left` |

### Visitor side: `answers`

| Field | Type | Default |
| - | - | - |
| `answers.input.variant` | `filled` \| `outline` | `filled` |
| `answers.input.radius` | `sm` \| `md` \| `lg` \| `full` | `md` |
| `answers.button.background`, `.text` | color | from base |
| `answers.button.radius` | `sm` \| `md` \| `lg` \| `full` | `full` |
| `answers.selectors.selected`, `.unselected`, `.indicator` | color | from base |
| `answers.selectors.size` | `sm` \| `md` \| `lg` | `md` |
| `answers.selectors.align` | `left` \| `center` | `left` |
| `answers.userBubble.background`, `.text`, `.border` | color | from base |
| `answers.userBubble.fontSize`, `.align` | as above | `md`, `left` |
| `answers.widgetCard.background`, `.text`, `.border` | color | Outer card of forms shown inline in the transcript |
| `answers.widgetCard.radius` | `sm` \| `md` \| `lg` \| `full` | `lg` |
| `answers.widgetCard.elevation` | `none` \| `sm` \| `md` \| `lg` | `md` |
| `answers.card.background`, `.border`, `.radius`, `.elevation` | Cards inside designed (A2UI) forms | radius `md`, elevation `none` |
| `answers.row.gap` | `sm` \| `md` \| `lg`: spacing between items in designed forms | `md` |

`answers.widgetCard` applies only to forms shown as an inline card. Forms shown inside an agent message use `questions.agentBubble` colors.

### Scale values

| Keyword | Titles | Body text | Radius | Row gap |
| - | - | - | - | - |
| `sm` | 16px | 14px | 8px | 8px |
| `md` | 18px | 16px | 16px | 12px |
| `lg` | 20px | 20px | 24px | 16px |
| `full` | | | fully rounded | |

### Base palettes

| Token | Light | Dark |
| - | - | - |
| Background | `#ffffff` | `#1a1a2e` |
| Text | `#181b19` | `#eeeeee` |
| Muted text | `#707b73` | `#9aa0a6` |
| Primary (buttons, launcher) | `#3655e8` | `#3655e8` |

## Complete example

```json theme={"dark"}
{
  "base": "dark",
  "name": "Brand Dark",
  "font": { "family": "Inter" },
  "fab": {
    "backgroundColor": "#1930a3",
    "iconColor": "#ffffff",
    "text": "Talk to us",
    "collapsedBackground": "#1a1a2e",
    "textColor": "#eeeeee"
  },
  "sections": {
    "header": { "background": "#16213e", "text": "#eeeeee" },
    "chat": { "background": "#1a1a2e" },
    "bottom": { "background": "#16213e", "border": "#2a2a3e" },
    "precall": { "ctaButtonBackground": "#1930a3", "ctaButtonText": "#ffffff" }
  },
  "questions": {
    "titles": { "color": "#ffffff", "fontSize": "md" },
    "agentBubble": { "background": "#22223a", "text": "#eeeeee" }
  },
  "answers": {
    "input": { "variant": "filled", "radius": "md" },
    "button": { "background": "#1930a3", "text": "#ffffff", "radius": "full" },
    "userBubble": { "background": "#1930a3", "text": "#ffffff" }
  }
}
```

## Try in the playground

Turn on **Custom widget theme** in the **Look** step to edit colors live, then open **Get code** > **setTheme()** to copy the result.

> **[Dark widget](https://sdk-playground.callers.dev/?theme=%7B%22enabled%22%3Atrue%2C%22base%22%3A%22dark%22%2C%22values%22%3A%7B%7D%7D)**
>
> Start from the dark base.

> **[Teal brand, bottom left](https://sdk-playground.callers.dev/?fab=Talk%20to%20us\&corner=bottom-left\&theme=%7B%22enabled%22%3Atrue%2C%22base%22%3A%22light%22%2C%22values%22%3A%7B%22fabBg%22%3A%22%230f766e%22%2C%22ctaBg%22%3A%22%230f766e%22%7D%7D)**
>
> A labeled launcher with custom brand colors.

## Related

> **[Styling the widget](https://docs.callers.ai/documentation/widget-agents/styling-the-widget.md)**
>
> Build a theme visually in the dashboard.

> **[Configuration](https://docs.callers.ai/sdk/configuration.md)**
>
> Every option, in code and as script tag attributes.

> **[Playground](https://docs.callers.ai/sdk/playground.md)**
>
> Try themes live and copy the generated code.

> **[Talking avatars](https://docs.callers.ai/sdk/avatars.md)**
>
> Add an animated avatar to the widget.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.