Voicemails
A user's voicemail inbox: audio playback, transcriptions, AI summaries, and call-back and delete actions.
Usage
- React
- Web Component
import { Voicemails } from '@dialstack/sdk-react/voicemails';
function Inbox({ userId }: { userId: string }) {
return <Voicemails userId={userId} />;
}
<dialstack-voicemails></dialstack-voicemails>
<script>
// `dialstack` is your initialized instance (see Setup)
const voicemails = document.querySelector('dialstack-voicemails');
voicemails.setUserId(userId);
voicemails.setInstance(dialstack);
</script>
Set the user whose voicemails to show (the userId prop or setUserId()). Without it the component shows an error state.
The list loads 20 voicemails at a time, with a Load more button at the end. See Pagination.
Options
These are specific to voicemails. The common options (locale, formatting, icons, layout variant, classes, load callbacks) apply too.
| React prop | Web Component method | Type | Default | Description |
|---|---|---|---|---|
userId | setUserId(userId) | string | Required | User whose voicemails to show |
displayOptions | setDisplayOptions(options) | VoicemailDisplayOptions | — | Show or hide parts of the UI (see below) |
behaviorOptions | setBehaviorOptions(options) | VoicemailBehaviorOptions | — | Playback and interaction behavior (see below) |
customRowRenderer | setCustomRowRenderer(renderer) | (voicemail) => string | — | Return your own HTML for each row |
classes | setClasses(classes) | VoicemailsClasses | — | Extra CSS classes (see Styling) |
VoicemailDisplayOptions
| Option | Type | Default | Description |
|---|---|---|---|
showDuration | boolean | true | Voicemail length |
showTranscription | boolean | true | Transcription, when available |
showCallbackButton | boolean | true | Call back button |
showDeleteButton | boolean | true | Delete button |
showProgressBar | boolean | true | Playback progress bar |
showTimestamp | boolean | true | When the voicemail was received |
VoicemailBehaviorOptions
| Option | Type | Default | Description |
|---|---|---|---|
autoPlayOnExpand | boolean | true | Start playback when a voicemail is opened |
confirmBeforeDelete | boolean | true | Ask for confirmation before deleting |
markAsReadOnPlay | boolean | true | Mark as read when played |
allowSeeking | boolean | true | Allow seeking in the progress bar |
- React
- Web Component
<Voicemails
userId={userId}
displayOptions={{ showDeleteButton: false }}
behaviorOptions={{ autoPlayOnExpand: false }}
/>
voicemails.setDisplayOptions({ showDeleteButton: false });
voicemails.setBehaviorOptions({ autoPlayOnExpand: false });
Events
| React prop | Web Component method | Event | When |
|---|---|---|---|
onVoicemailSelect | setOnVoicemailSelect(cb) | { voicemailId } | A voicemail is opened |
onVoicemailPlay | setOnVoicemailPlay(cb) | { voicemailId } | Playback starts |
onVoicemailPause | setOnVoicemailPause(cb) | { voicemailId } | Playback pauses |
onVoicemailDelete | setOnVoicemailDelete(cb) | { voicemailId } | A voicemail has been deleted |
onCallBack | setOnCallBack(cb) | { phoneNumber } | The call back button is clicked |
onDeleteRequest | setOnDeleteRequest(cb) | voicemailId | Before deleting. Resolve true to delete, false to cancel |
Use onDeleteRequest to show your own confirmation dialog, and set confirmBeforeDelete: false so the built-in one doesn't show too.
- React
- Web Component
<Voicemails
userId={userId}
behaviorOptions={{ confirmBeforeDelete: false }}
onDeleteRequest={async (voicemailId) => showConfirmDialog('Delete this voicemail?')}
onCallBack={(event) => startCall(event.phoneNumber)}
onVoicemailPlay={(event) => analytics.track('voicemail_played', { id: event.voicemailId })}
/>
voicemails.setBehaviorOptions({ confirmBeforeDelete: false });
voicemails.setOnDeleteRequest(async (voicemailId) => showConfirmDialog('Delete this voicemail?'));
voicemails.setOnCallBack((event) => startCall(event.phoneNumber));
voicemails.setOnVoicemailPlay((event) => {
analytics.track('voicemail_played', { id: event.voicemailId });
});
Custom row renderer
The renderer receives { id, from_name, from_number, created_at, duration_seconds, is_read, transcription?, summary? } and returns an HTML string. Escape any value you interpolate: caller names and transcriptions come from the caller.
const escape = (s) => String(s ?? '').replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
const renderRow = (voicemail) => `
<div class="voicemail-row ${voicemail.is_read ? '' : 'unread'}">
<strong>${escape(voicemail.from_name || 'Unknown')}</strong>
<span>${escape(voicemail.from_number)}</span>
<span>${new Date(voicemail.created_at).toLocaleDateString()}</span>
${voicemail.transcription ? `<p>${escape(voicemail.transcription)}</p>` : ''}
</div>
`;
// React: <Voicemails userId={userId} customRowRenderer={renderRow} />
voicemails.setCustomRowRenderer(renderRow);
Styling
classes adds your own CSS class names to parts of the component. For colors, fonts and spacing, see Theming.
| Key | Applied to |
|---|---|
loading | Loading state |
error | Error state |
empty | The "no voicemails" message |
list | List container |
item | Each voicemail |
itemExpanded | The open voicemail |
itemUnread | An unread voicemail |
player | Audio player |
actions | Action buttons |
- React
- Web Component
<Voicemails userId={userId} classes={{ itemUnread: 'border-l-4 border-blue-500' }} />
voicemails.setClasses({ itemUnread: 'border-l-4 border-blue-500' });
Accessibility
The component has ARIA labels on every interactive element, keyboard navigation (Tab, Enter, Space), focus management when opening and closing a voicemail, screen reader announcements for state changes, and visible focus indicators.
Next steps
- Call logs — the account's call table
- Component basics — shared options
- Theming — customize appearance