# Customising widgets

> Change the colours, placement, language, consent and triggers of any widget, and style it from your page.

Source: https://voxio.in/docs/customising · voxioagent 2.0.0 · Index: https://voxio.in/docs/llms.txt

These options work on the voice button and the avatar panel. Pass them to `mountVoiceButton`, `mountAvatar` or the React components.

## Set the theme and colours

Pass a theme and your brand colours:

```js
mountVoiceButton({
  flowKey: "YOUR_FLOW_KEY",
  theme: "auto",          // "light", "dark" or "auto"
  colors: { primary: "#0f766e", onPrimary: "#fff", surface: "#111", text: "#eee", danger: "#e5484d" },
  radius: "14px",
  fontFamily: '"Figtree", -apple-system, "Segoe UI", sans-serif',
});
```

You can also set colours from your own CSS with `--voxio-primary`, `--voxio-surface`, `--voxio-text` and `--voxio-radius`.

## Place the widget

- `placement` (Placement): `bottom-right` (default), `bottom-left`, `top-right`, `top-left`, `bottom-center`, or `inline` to sit inside a container.
- `offset` ({ x?, y? }): The distance from the edges. Numbers are pixels.
- `zIndex` (number): The stacking order.
- `mobile` ({ placement?, offset? }): Overrides for screens narrower than 640px.
- `draggable` (boolean | { snap?, remember? }): Lets visitors move it. It snaps to an edge and remembers the spot.

## Control when it appears

- `consent` (boolean | string): Asks before opening the microphone. `true` uses the default notice; a string is your own.
- `showWhen` (ShowWhen): Starts hidden and appears on a trigger, such as `{ afterSeconds: 10 }`, `{ scrollDepth: 0.5 }` or `{ urlMatch: "/pricing" }`.
- `hidden` (boolean): Starts hidden. Call `open()` to show it.
- `session` (VoxioSession): Shares one session between widgets, such as a button and an avatar on the same call.

## Change the language and text

Pick a built-in language, or override any text the widget shows:

```js
mountVoiceButton({ flowKey: "YOUR_FLOW_KEY", locale: "hi" });   // built in: "en", "hi"
mountVoiceButton({ flowKey: "YOUR_FLOW_KEY", strings: { start: "Speak to sales" } });
```

## Style it from your page

Widgets render in a shadow root, so your page's CSS doesn't reach inside. Style their named parts with `::part()`:

```css
voxio-voice-button::part(button) { box-shadow: 0 8px 30px rgb(0 0 0 / 0.4); }
voxio-voice-button::part(label)  { font-weight: 600; }
voxio-avatar::part(panel)        { border: 1px solid #333; }
```

For anything else, pass CSS as `customStyles`. It's added inside the shadow root.

## Listen for DOM events

Every widget fires these events on its element:

| Event | detail |
| --- | --- |
| `voxio-state` | `{ state, muted }` |
| `voxio-error` | The `VoxioError` |
| `voxio-ended` | `{ reason, seconds, sessionId }` |
| `voxio-web-action` | The web action the agent asked for |

For example, to count finished calls in your analytics:

```js
document.querySelector("voxio-voice-button")
  .addEventListener("voxio-ended", (e) => analytics.track("voice_call", e.detail));
```

## Next steps

- [Web actions](https://voxio.in/docs/web-actions.md): let the agent act on your page.
- [Errors](https://voxio.in/docs/errors.md): handle each error code.
