Theming
Customize the appearance of DialStack components using CSS variables, theme presets, and layout variants.
Quick Start
const dialstack = initialize({
publishableKey: 'pk_live_YOUR_KEY',
appearance: {
theme: 'light',
variables: {
colorPrimary: '#6772E5',
fontFamily: 'Inter, system-ui, sans-serif',
borderRadius: '8px',
},
},
});
Theme Variants
Choose a base theme:
| Theme | Description |
|---|---|
'light' | Light background with dark text |
'dark' | Dark background with light text |
'auto' | Follows system preference (prefers-color-scheme) |
// Follow system preference
initialize({
publishableKey: 'pk_live_YOUR_KEY',
appearance: {
theme: 'auto',
},
});
Layout Variants
Adjust component density with layoutVariant:
| Variant | Description |
|---|---|
'compact' | Minimal padding, dense layout |
'default' | Standard spacing |
'comfortable' | Extra padding, breathing room |
<CallLogs layoutVariant="compact" />
<Voicemails layoutVariant="comfortable" />
CSS Variables
Customize components using CSS variables in the variables option:
Colors
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
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
variables: {
spacingUnit: '8px',
spacingXs: '4px',
spacingSm: '8px',
spacingMd: '16px',
spacingLg: '24px',
spacingXl: '32px',
}
Border & Effects
variables: {
borderRadius: '6px',
borderRadiusSmall: '4px',
borderRadiusLarge: '12px',
transitionDuration: '150ms',
focusRingColor: 'rgba(59, 130, 246, 0.5)',
focusRingWidth: '2px',
}
Component-Specific
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
| Variable | Default (Light) | Description |
|---|---|---|
| Colors | ||
colorPrimary | #2563eb | Primary brand color |
colorPrimaryHover | #1d4ed8 | Primary color on hover |
colorBackground | #ffffff | Background color |
colorText | #111827 | Primary text color |
colorTextSecondary | #6b7280 | Secondary text color |
colorDanger | #dc2626 | Error/danger color |
colorSuccess | #16a34a | Success color |
colorWarning | #d97706 | Warning color |
colorSurfaceSubtle | #f9fafb | Subtle surface color |
colorBorder | #e5e7eb | Border color |
colorBorderSubtle | #f3f4f6 | Subtle border color |
| Typography | ||
fontFamily | system-ui, sans-serif | Font family |
fontSizeBase | 14px | Base font size |
fontSizeSmall | 12px | Small text |
fontSizeLarge | 16px | Large text |
fontSizeXLarge | 18px | Extra large text |
fontWeightNormal | 400 | Normal weight |
fontWeightMedium | 500 | Medium weight |
fontWeightBold | 600 | Bold weight |
lineHeight | 1.5 | Line height |
| Spacing | ||
spacingUnit | 8px | Base spacing unit |
spacingXs | 4px | Extra small |
spacingSm | 8px | Small |
spacingMd | 16px | Medium |
spacingLg | 24px | Large |
spacingXl | 32px | Extra large |
| Border | ||
borderRadius | 6px | Default radius |
borderRadiusSmall | 4px | Small radius |
borderRadiusLarge | 12px | Large radius |
| Effects | ||
transitionDuration | 150ms | Animation duration |
focusRingColor | rgba(59, 130, 246, 0.5) | Focus outline color |
focusRingWidth | 2px | Focus outline width |
CSS Class Overrides
Apply custom CSS classes using the classes prop:
CallLogs Classes
<CallLogs
classes={{
base: 'rounded-lg shadow-md',
loading: 'animate-pulse',
error: 'border-red-500 bg-red-50',
empty: 'text-gray-400 italic',
table: 'min-w-full divide-y',
header: 'bg-gray-50 font-semibold',
row: 'hover:bg-gray-100 cursor-pointer',
rowInbound: 'border-l-4 border-green-500',
rowOutbound: 'border-l-4 border-blue-500',
pagination: 'flex justify-between mt-4',
}}
/>
Voicemails Classes
<Voicemails
userId="user_123"
classes={{
base: 'bg-white rounded-lg',
loading: 'opacity-50',
error: 'text-red-600',
empty: 'text-center py-8',
list: 'divide-y divide-gray-200',
item: 'p-4 transition-colors',
itemExpanded: 'bg-blue-50',
itemUnread: 'border-l-4 border-blue-500 bg-blue-50/50',
player: 'bg-gray-100 rounded p-2',
actions: 'flex gap-2 mt-2',
}}
/>
Updating Theme at Runtime
Use the update() method to change appearance after initialization:
const dialstack = initialize({
publishableKey: 'pk_live_YOUR_KEY',
appearance: { theme: 'light' },
});
// Later: switch to dark mode
dialstack.update({
appearance: {
theme: 'dark',
variables: {
colorPrimary: '#8B5CF6',
},
},
});
Custom Icons
Replace default icons with custom SVG:
<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
<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
<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
import { initialize, DialstackComponentsProvider, CallLogs, Voicemails } from '@dialstack/sdk';
const dialstack = initialize({
publishableKey: 'pk_live_YOUR_KEY',
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() {
return (
<DialstackComponentsProvider dialstack={dialstack} clientSecret={secret}>
<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="user_123"
layoutVariant="comfortable"
classes={{
base: 'bg-white rounded-xl shadow-lg',
itemUnread: 'border-l-4 border-indigo-500',
}}
/>
</section>
</div>
</DialstackComponentsProvider>
);
}
Next Steps
- i18n - Internationalization
- CallLogs - CallLogs component reference
- Voicemails - Voicemails component reference