Skip to main content

Theming

Customize the appearance of DialStack components using CSS variables, theme presets, and layout variants.

Quick Start​

TypeScript
const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
appearance: {
theme: 'light',
variables: {
colorPrimary: '#6772E5',
fontFamily: 'Inter, system-ui, sans-serif',
borderRadius: '8px',
},
},
});

Theme Variants​

Choose a base theme:

ThemeDescription
'light'Light background with dark text
'dark'Dark background with light text
'auto'Follows system preference (prefers-color-scheme)
TypeScript
// Follow system preference
const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
appearance: {
theme: 'auto',
},
});

Layout Variants​

Adjust component density with layoutVariant:

VariantDescription
'compact'Minimal padding, dense layout
'default'Standard spacing
'comfortable'Extra padding, breathing room
TypeScript
<CallLogs layoutVariant="compact" />
<CallHistory phoneNumber="+14155551234" layoutVariant="comfortable" />

CSS Variables​

Customize components using CSS variables in the variables option:

Colors​

TypeScript
variables: {
// Primary brand color
colorPrimary: '#6772E5',
colorPrimaryHover: '#5469D4',

// Base colors
colorBackground: '#ffffff',
colorText: '#1a1a1a',
colorTextSecondary: '#6b7280',

// Semantic colors
colorDanger: '#e5484d',
colorSuccess: '#30a46c',
colorWarning: '#f5a623',

// Surface colors
colorSurfaceSubtle: '#f9fafb',
colorBorder: '#e5e7eb',
colorBorderSubtle: '#f3f4f6',
}

Typography​

TypeScript
variables: {
fontFamily: 'Inter, system-ui, sans-serif',
fontSizeBase: '14px',
fontSizeSmall: '12px',
fontSizeLarge: '16px',
fontSizeXLarge: '18px',
fontWeightNormal: '400',
fontWeightMedium: '500',
fontWeightBold: '600',
lineHeight: '1.5',
}

Spacing​

TypeScript
variables: {
spacingUnit: '8px',
spacingXs: '4px',
spacingSm: '8px',
spacingMd: '16px',
spacingLg: '24px',
spacingXl: '32px',
}

Border & Effects​

TypeScript
variables: {
borderRadius: '6px',
borderRadiusSmall: '4px',
borderRadiusLarge: '12px',
transitionDuration: '150ms',
focusRingColor: 'rgba(59, 130, 246, 0.5)',
focusRingWidth: '2px',
}

Component-Specific​

TypeScript
variables: {
// Icons
iconSize: '20px',
iconSizeSmall: '16px',

// Audio player
playerButtonSize: '40px',
playerProgressHeight: '4px',
playerProgressHandleSize: '12px',

// Indicators
unreadIndicatorSize: '8px',
spinnerSize: '24px',

// Time display
timeDisplayWidth: '48px',
}

Complete Variables Reference​

VariableDefault (Light)Description
Colors
colorPrimary#2563ebPrimary brand color
colorPrimaryHover#1d4ed8Primary color on hover
colorBackground#ffffffBackground color
colorText#111827Primary text color
colorTextSecondary#6b7280Secondary text color
colorDanger#dc2626Error/danger color
colorSuccess#16a34aSuccess color
colorWarning#d97706Warning color
colorSurfaceSubtle#f9fafbSubtle surface color
colorBorder#e5e7ebBorder color
colorBorderSubtle#f3f4f6Subtle border color
Typography
fontFamilysystem-ui, sans-serifFont family
fontSizeBase14pxBase font size
fontSizeSmall12pxSmall text
fontSizeLarge16pxLarge text
fontSizeXLarge18pxExtra large text
fontWeightNormal400Normal weight
fontWeightMedium500Medium weight
fontWeightBold600Bold weight
lineHeight1.5Line height
Spacing
spacingUnit8pxBase spacing unit
spacingXs4pxExtra small
spacingSm8pxSmall
spacingMd16pxMedium
spacingLg24pxLarge
spacingXl32pxExtra large
Border
borderRadius6pxDefault radius
borderRadiusSmall4pxSmall radius
borderRadiusLarge12pxLarge radius
Effects
transitionDuration150msAnimation duration
focusRingColorrgba(59, 130, 246, 0.5)Focus outline color
focusRingWidth2pxFocus outline width

CSS Class Overrides​

Each component accepts a classes option that adds your own class names to its parts, such as the table, rows or pagination. The keys differ per component; each component page lists them:

Updating Theme at Runtime​

Use the update() method to change appearance after initialization:

TypeScript
const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
appearance: { theme: 'light' },
});

// Later: switch to dark mode
dialstack.update({
appearance: {
theme: 'dark',
variables: {
colorPrimary: '#8B5CF6',
},
},
});

Custom Icons​

Replace default icons with custom SVG:

TypeScript
<CallLogs
icons={{
inbound: '<svg>...</svg>',
outbound: '<svg>...</svg>',
play: '<svg>...</svg>',
pause: '<svg>...</svg>',
phone: '<svg>...</svg>',
trash: '<svg>...</svg>',
chevronLeft: '<svg>...</svg>',
chevronRight: '<svg>...</svg>',
chevronDown: '<svg>...</svg>',
spinner: '<svg>...</svg>',
}}
/>

Framework Integration​

Tailwind CSS​

TypeScript
<CallLogs
classes={{
base: 'bg-white rounded-xl shadow-lg overflow-hidden',
table: 'min-w-full divide-y divide-gray-200',
header: 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider',
row: 'px-6 py-4 whitespace-nowrap hover:bg-gray-50 transition-colors',
pagination: 'px-6 py-3 flex items-center justify-between bg-gray-50',
}}
/>

Bootstrap​

TypeScript
<CallLogs
classes={{
base: 'card',
table: 'table table-hover mb-0',
header: 'bg-light',
row: 'cursor-pointer',
pagination: 'd-flex justify-content-between p-3',
}}
/>

Complete Example​

TypeScript
import { loadDialstackAndInitialize } from '@dialstack/sdk-js';
import { DialstackComponentsProvider } from '@dialstack/sdk-react';
import { CallLogs } from '@dialstack/sdk-react/call-logs';
import { Voicemails } from '@dialstack/sdk-react/voicemails';

const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
appearance: {
theme: 'auto',
variables: {
// Brand colors
colorPrimary: '#6366F1',
colorPrimaryHover: '#4F46E5',

// Typography
fontFamily: '"Inter", -apple-system, sans-serif',
fontSizeBase: '14px',

// Spacing
spacingUnit: '8px',
borderRadius: '8px',

// Focus states
focusRingColor: 'rgba(99, 102, 241, 0.5)',
focusRingWidth: '3px',
},
},
});

function App({ userId }: { userId: string }) {
return (
<DialstackComponentsProvider dialstack={dialstack}>
<div className="max-w-4xl mx-auto p-6">
<h1 className="text-2xl font-bold mb-6">Voice Dashboard</h1>

<section className="mb-8">
<h2 className="text-xl mb-4">Recent Calls</h2>
<CallLogs
layoutVariant="comfortable"
classes={{
base: 'bg-white rounded-xl shadow-lg',
row: 'cursor-pointer hover:bg-indigo-50',
}}
/>
</section>

<section>
<h2 className="text-xl mb-4">Voicemails</h2>
<Voicemails
userId={userId}
layoutVariant="comfortable"
classes={{
base: 'bg-white rounded-xl shadow-lg',
itemUnread: 'border-l-4 border-indigo-500',
}}
/>
</section>
</div>
</DialstackComponentsProvider>
);
}

Next Steps​