Skip to main content

Voicemails

Display a list of voicemails with audio playback, transcription, and action buttons.

Basic Usage

import { Voicemails } from '@dialstack/sdk';

function Dashboard() {
return <Voicemails userId="user_123" />;
}
Required Prop

The userId prop is required. Without it, the component will display an error state.

Automatic Pagination

Pagination is handled automatically by the component using cursor-based pagination. The component automatically loads more voicemails as users scroll or interact with the list. See the Pagination Guide for details.

Props

PropTypeDefaultDescription
userIdstringRequiredUser ID to fetch voicemails for
localeLocaleEnglishCustom locale for UI strings
formattingFormattingOptions-Date/phone formatting options
iconsComponentIcons-Custom SVG icons
layoutVariant'compact' | 'comfortable' | 'default''default'Layout density
classesVoicemailsClasses-Custom CSS classes
displayOptionsVoicemailDisplayOptions-Show/hide UI elements
behaviorOptionsVoicemailBehaviorOptions-Playback and interaction behavior
customRowRenderer(voicemail) => string-Custom row rendering
onLoaderStart(event) => void-Loading started callback
onLoadError(event) => void-Loading failed callback
onVoicemailSelect(event) => void-Voicemail selected callback
onVoicemailPlay(event) => void-Playback started callback
onVoicemailPause(event) => void-Playback paused callback
onVoicemailDelete(event) => void-Voicemail deleted callback
onCallBack(event) => void-Call back button clicked
onDeleteRequest(id) => Promise<boolean>-Custom delete confirmation

Display Options

Control which UI elements are visible:

<Voicemails
userId="user_123"
displayOptions={{
showDuration: true, // Show voicemail duration
showTranscription: true, // Show transcription when available
showCallbackButton: true, // Show call back button
showDeleteButton: true, // Show delete button
showProgressBar: true, // Show playback progress bar
showTimestamp: true, // Show received timestamp
}}
/>

VoicemailDisplayOptions

OptionTypeDefaultDescription
showDurationbooleantrueDisplay voicemail length
showTranscriptionbooleantrueShow transcription text
showCallbackButtonbooleantrueEnable call back action
showDeleteButtonbooleantrueEnable delete action
showProgressBarbooleantrueShow audio progress bar
showTimestampbooleantrueDisplay received time

Behavior Options

Control playback and interaction behavior:

<Voicemails
userId="user_123"
behaviorOptions={{
autoPlayOnExpand: true, // Auto-play when expanded
confirmBeforeDelete: true, // Show delete confirmation
markAsReadOnPlay: true, // Mark as read when played
allowSeeking: true, // Allow seeking in audio
}}
/>

VoicemailBehaviorOptions

OptionTypeDefaultDescription
autoPlayOnExpandbooleantrueStart playback when expanding
confirmBeforeDeletebooleantrueShow confirmation dialog
markAsReadOnPlaybooleantrueMark as read on first play
allowSeekingbooleantrueEnable seeking in progress bar

Callbacks

onVoicemailSelect

Triggered when a voicemail is expanded:

<Voicemails
userId="user_123"
onVoicemailSelect={(event) => {
console.log('Selected voicemail:', event.voicemailId);
}}
/>

onVoicemailPlay / onVoicemailPause

Track playback state:

<Voicemails
userId="user_123"
onVoicemailPlay={(event) => {
analytics.track('voicemail_played', { id: event.voicemailId });
}}
onVoicemailPause={(event) => {
analytics.track('voicemail_paused', { id: event.voicemailId });
}}
/>

onCallBack

Handle call back button clicks:

<Voicemails
userId="user_123"
onCallBack={(event) => {
// Initiate call to the number
initiateCall(event.phoneNumber);
}}
/>

onVoicemailDelete

Triggered after a voicemail is deleted:

<Voicemails
userId="user_123"
onVoicemailDelete={(event) => {
showToast('Voicemail deleted');
}}
/>

onDeleteRequest

Custom delete confirmation logic:

<Voicemails
userId="user_123"
onDeleteRequest={async (voicemailId) => {
// Show custom confirmation dialog
const confirmed = await showConfirmDialog({
title: 'Delete Voicemail',
message: 'Are you sure? This cannot be undone.',
});
return confirmed; // Return true to proceed, false to cancel
}}
/>

Custom Styling

CSS Classes

Apply custom classes:

<Voicemails
userId="user_123"
classes={{
base: 'rounded-lg shadow',
loading: 'animate-pulse',
error: 'border-red-500',
empty: 'text-gray-400 p-8',
list: 'divide-y',
item: 'p-4 hover:bg-gray-50',
itemExpanded: 'bg-gray-50',
itemUnread: 'border-l-4 border-blue-500',
player: 'mt-2',
actions: 'flex gap-2 mt-2',
}}
/>

VoicemailsClasses

ClassDefaultDescription
base'dialstack-component'Container element
loading'dialstack-component--loading'Loading state
error'dialstack-component--error'Error state
empty'dialstack-component--empty'No voicemails state
list'dialstack-voicemail-list'List container
item'dialstack-voicemail-item'Voicemail item
itemExpanded'dialstack-voicemail-item--expanded'Expanded item
itemUnread'dialstack-voicemail-item--unread'Unread item
player'dialstack-voicemail-player'Audio player
actions'dialstack-voicemail-actions'Action buttons

Layout Variants

<Voicemails userId="user_123" layoutVariant="compact" />
<Voicemails userId="user_123" layoutVariant="default" />
<Voicemails userId="user_123" layoutVariant="comfortable" />

Voicemail Data Model

interface Voicemail {
id: string;
from_name: string;
from_number: string;
created_at: string;
duration_seconds: number;
is_read: boolean;
transcription?: string;
}

Complete Example

import { Voicemails } from '@dialstack/sdk';
import { useCallback, useState } from 'react';

function VoicemailInbox({ userId }: { userId: string }) {
const [lastPlayed, setLastPlayed] = useState<string | null>(null);

const handleCallBack = useCallback((event: { phoneNumber: string }) => {
// Open phone dialer or initiate WebRTC call
window.location.href = `tel:${event.phoneNumber}`;
}, []);

const handleDeleteRequest = useCallback(async (voicemailId: string) => {
const confirmed = window.confirm('Are you sure you want to delete this voicemail?');
return confirmed;
}, []);

return (
<div className="max-w-2xl mx-auto">
<h1 className="text-2xl font-bold mb-4">Voicemails</h1>

<Voicemails
userId={userId}
layoutVariant="comfortable"
displayOptions={{
showDuration: true,
showTranscription: true,
showCallbackButton: true,
showDeleteButton: true,
showProgressBar: true,
showTimestamp: true,
}}
behaviorOptions={{
autoPlayOnExpand: true,
confirmBeforeDelete: false, // Use custom handler
markAsReadOnPlay: true,
allowSeeking: true,
}}
formatting={{
defaultCountry: 'US',
dateLocale: 'en-US',
use24HourTime: false,
}}
classes={{
base: 'bg-white rounded-lg shadow-lg',
list: 'divide-y divide-gray-200',
item: 'p-4 cursor-pointer transition-colors',
itemExpanded: 'bg-blue-50',
itemUnread: 'border-l-4 border-blue-500 bg-blue-50/50',
}}
onVoicemailSelect={(event) => {
console.log('Selected:', event.voicemailId);
}}
onVoicemailPlay={(event) => {
setLastPlayed(event.voicemailId);
}}
onCallBack={handleCallBack}
onDeleteRequest={handleDeleteRequest}
onVoicemailDelete={(event) => {
console.log('Deleted:', event.voicemailId);
}}
onLoadError={(event) => {
console.error('Load error:', event.error);
}}
/>
</div>
);
}

Accessibility

The Voicemails component includes:

  • ARIA labels for all interactive elements
  • Keyboard navigation (Tab, Enter, Space)
  • Focus management when expanding/collapsing items
  • Screen reader announcements for state changes
  • Visible focus indicators

Next Steps