---
title: "Dialer SDK UI: Embed a Power Dialer Interface | Trellus"
description: "Mount the optional Trellus dialer interface in any framework: mountDialer options, CSS theme variables, the session viewer and the local playground."
source: "https://www.trellus.ai/developers/dialer-sdk/ui"
note: "Text-only copy of the page for AI assistants and agents. Link to the source address, not this file."
site_summary: "https://www.trellus.ai/llms.txt"
---

# Optional dialer interface

A small, framework-independent interface built on the SDK. Mount it for manual, power or parallel dialing, theme it with CSS variables, and add a read-only session viewer.

@trellusrelease/dialer-ui

## Install the interface package

The interface is optional. It is built on the headless SDK and has no transport or credentials of its own. You can use it as it is, or build your own interface on the same SDK.

Install the SDK and the browser audio dependency

```bash
npm install @trellusrelease/dialer-sdk @twilio/voice-sdk
```

Install the optional interface

```bash
npm install @trellusrelease/dialer-ui
```

## mountDialer

Create one dialer, load tasks, then mount the interface into an element that already exists.

Mount the dialer interface

```javascript
import { createDialer } from '@trellusrelease/dialer-sdk';
import { mountDialer } from '@trellusrelease/dialer-ui';

const dialer = createDialer({
  transport, // Configure the real transport with the SDK quickstart.
  maxLines: 3, // Load this limit from the rep's effective policy.
  async onDisposition({ call, disposition }) {
    await saveToYourApplication(call, disposition);
  },
});
dialer.setTasks([
  { id: 'person-123', name: 'Casey Chen', phoneNumber: '+14155550100' },
]);

const ui = mountDialer(document.querySelector('#dialer'), {
  dialer,
  title: 'Outbound',
});

// When removing the view:
ui.destroy();
// When ending the SDK's lifetime:
await dialer.destroy();
```

`transport` is the mock transport from the [quickstart](https://www.trellus.ai/developers/dialer-sdk/quickstart) or the live transport from [Live calling](https://www.trellus.ai/developers/dialer-sdk/live-calling). `saveToYourApplication` is yours to implement.

- Mounting only subscribes to state. It never connects audio or places a call.
- The rep clicks **Connect audio** to start audio, then **Start dialing** or **Call number** to place calls.
- Pause stops new calls from being placed. **End call** ends an existing call.
- One mount is allowed per element.

**Your application chooses who is called.** Pass only eligible tasks to `setTasks`. Apply do-not-call, calling-hours, assignment and other eligibility rules before the tasks reach the SDK. A line limit in the interface grants no entitlement.

## Options and lifecycle

mountDialer options

| Option | Purpose |
| --- | --- |
| `dialer` Required | An SDK instance. Share one instance across your application. |
| `title` Default: Dialer | The visible heading and accessible panel name. |
| `maxParallelLines` Default: SDK cap | An optional UI ceiling from 1 to 10. It can only lower the SDK’s effective line limit. |
| `disposeDialer` Default: false | Also destroy the SDK when this view unmounts. Use it only when the view owns the SDK’s lifetime. |

- `mountDialer()` returns an object with a `destroy()` method. It removes the view and its subscriptions.
- By default your application still owns the running SDK and its calls after the view is removed.
- With `disposeDialer: true`, `destroy()` also calls the SDK’s asynchronous `destroy()`. Await the returned promise if you need to wait for cleanup.
- Set `maxLines` once on the SDK. Use `maxParallelLines` only when the interface should offer a lower limit.
- The interface reads `snapshot.maxLines` and updates its line picker when the transport lowers the cap. Parallel mode is unavailable below two lines.

## What the interface covers

- Dialing mode and line count.
- Manual number entry.
- Pause and resume.
- Mute and hangup for a specific call.
- Keypad tones.
- A live transcript.
- Audio device selection.
- Wrap-up.

**Complete wrap-up** calls `dialer.completeWrapUp()`. With an `onDisposition` handler, the SDK waits for it first. Without one, the local queue continues. The view does not claim a saved call log and does not complete tasks in a CRM. Map the optional disposition text and notes into your own schema in the handler.

- The header follows active calls: **Calling…**, **On a call** and **Ending call…**.
- Detection labels such as **Human detected**, **Screening…** or **Voicemail** describe how the call is classified. They do not mean the rep has joined.
- Mute and keypad controls need the call to be connected.
- A transcript opens when its first text arrives and stays collapsed if the user collapses it later.
- Audio devices load after the rep clicks **Audio devices**. The view does not remember the choice.
- Streaming updates keep input values and focus, so typing survives transcript updates.

## Theming

The interface renders inside an open Shadow DOM, so your styles and its styles do not collide. Set these custom properties on the mount element:

Theme variables

```css
#dialer {
  --trellus-accent: #176c46;
  --trellus-radius: 14px;
  --trellus-width: 460px;
}
```

The variables are `--trellus-accent`, `--trellus-radius` and `--trellus-width`.

- The view uses native buttons and forms, visible labels and focus outlines.
- Connection status is announced in a polite live region. Errors appear in an alert.
- Each call is labeled by its contact heading, so repeated call controls have distinct context.
- Contact names and transcripts are inserted as text. No caller input is interpreted as HTML.

## Framework use

The interface is framework-independent. In React, Vue or another framework:

- Mount into an element after it exists.
- Call `ui.destroy()` in the component’s cleanup hook.
- Keep the SDK instance outside render functions, so a rerender does not create duplicate devices or calls.
- If the page runs in an iframe with a live transport, the iframe must permit microphone use.

## mountSessionViewer

The `@trellusrelease/dialer-ui/sessions` entry point adds a read-only session browser to place beside the calling controls.

Mount the session viewer

```javascript
import { mountSessionViewer } from '@trellusrelease/dialer-ui/sessions';

const sessionsUI = mountSessionViewer(document.querySelector('#sessions'), { dialer });
const stopTranscript = dialer.on('transcript.updated', ({ sessionId, segments }) => {
  renderTranscript(sessionId, segments); // Full corrected text, not an append-only delta.
});
const sessions = dialer.getSessions();
const session = sessions.length ? dialer.getSession(sessions[0].sessionId) : null;

// On teardown:
stopTranscript();
sessionsUI.destroy();
```

`renderTranscript` is yours to implement.

mountSessionViewer options

| Option | Purpose |
| --- | --- |
| `dialer` Required | The same SDK instance the calling controls use. |
| `title` Default: Sessions & events | The visible and accessible title. |

- It shows up to 50 sessions, the selected session’s live transcript and the latest 100 events.
- It follows a connected session until the user selects another.
- It reads public IDs, status, names and text. It does not render transport objects, credentials, phone numbers or arbitrary error messages.
- It uses its own Shadow DOM.
- `destroy()` removes the view and its subscriptions. The SDK and its calls stay alive.

## Local playground

The interface package ships a runnable playground. After you install the SDK and the interface into an application, start it with the installed command. It runs as a simulation and needs no account:

Start the installed playground

```bash
npx --no-install trellus-dialer-demo
```

- Open the address the command prints, load the dialer, then connect and dial. Nothing is called.
- Adding the `--live` flag enables real telephony. That needs `@twilio/voice-sdk` installed in the application and [live access](https://www.trellus.ai/developers/dialer-sdk/live-calling).
- The live queue starts empty, and credentials stay in memory.
