- Developers
- Dialer SDK
- Optional interface
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.
npm install @trellusrelease/dialer-sdk @twilio/voice-sdk
npm install @trellusrelease/dialer-ui
mountDialer
Create one dialer, load tasks, then mount the interface into an element that already exists.
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 or the live transport from 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.
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
| 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 adestroy()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 asynchronousdestroy(). Await the returned promise if you need to wait for cleanup. - Set
maxLinesonce on the SDK. UsemaxParallelLinesonly when the interface should offer a lower limit. - The interface reads
snapshot.maxLinesand 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:
#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.
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.
| 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:
npx --no-install trellus-dialer-demo
- Open the address the command prints, load the dialer, then connect and dial. Nothing is called.
- Adding the
--liveflag enables real telephony. That needs@twilio/voice-sdkinstalled in the application and live access. - The live queue starts empty, and credentials stay in memory.