Web Components
Use DialStack components in any JavaScript application without React. @dialstack/sdk-js provides native Web Components (Custom Elements) that work in vanilla JavaScript, Vue, Angular, Svelte, or any framework.
Quick Start
Using CDN
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/@dialstack/sdk-js"></script>
</head>
<body>
<dialstack-call-logs></dialstack-call-logs>
<dialstack-voicemails></dialstack-voicemails>
<script>
// Initialize DialStack
const dialstack = DialStack.initialize({
publishableKey: 'pk_live_YOUR_KEY',
// Fetch a client secret from your backend
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
});
// Wire the elements to the initialized instance
document.querySelector('dialstack-call-logs').setInstance(dialstack);
document.querySelector('dialstack-voicemails').setInstance(dialstack);
</script>
</body>
</html>
Using ES Modules
For bundled applications without React, import @dialstack/sdk-js — it registers the custom elements for you, and nothing else is needed.
The /pure subpath is the same SDK with that registration left out, for cases where importing a module must not touch the DOM — server-side rendering, or a test that asserts on registration itself. There you call registerComponents() when you want the elements defined:
import { loadDialstackAndInitialize, registerComponents } from '@dialstack/sdk-js/pure';
async function init() {
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',
},
});
// Register the custom elements before creating any of them
await registerComponents();
// Create components programmatically — create() wires the instance for you
const callLogs = dialstack.create('call-logs');
document.getElementById('call-logs-container').appendChild(callLogs);
}
init();
This applies to the /pure subpath only — importing @dialstack/sdk-js registers the
elements on your behalf.
registerComponents() is asynchronous, so await it before calling create() or touching
an element in your markup. Until an element is registered it is an unknown element: it
ignores every property you set on it and renders nothing, and calling a method like
setInstance() on it throws.
Initialization
UMD (Browser Global)
When using the CDN, DialStack is available as a global:
const dialstack = DialStack.initialize({
publishableKey: 'pk_live_YOUR_KEY',
appearance: {
theme: 'light',
variables: {
colorPrimary: '#6772E5',
},
},
});
ES Module (Pure)
For bundled apps, use the pure import:
import { loadDialstackAndInitialize } from '@dialstack/sdk-js/pure';
const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
});
DialStackInstance API
The instance returned from initialize() or loadDialstackAndInitialize() provides these methods:
create(tagName)
Create a component element. If you imported from /pure, await registerComponents() first:
const callLogs = dialstack.create('call-logs');
const voicemails = dialstack.create('voicemails');
// Append to DOM
document.getElementById('container').appendChild(callLogs);
update(options)
Update appearance for all components:
dialstack.update({
appearance: {
theme: 'dark',
variables: {
colorPrimary: '#8B5CF6',
},
},
});
logout()
Clear session and destroy all components:
dialstack.logout();
Component Element Methods
All component elements share these common methods:
| Method | Description |
|---|---|
setInstance(instance) | Set the DialStack instance |
setLocale(locale) | Set UI locale |
setFormatting(options) | Set date/phone formatting |
setIcons(icons) | Set custom icons |
setLayoutVariant(variant) | Set layout density |
setClasses(classes) | Set CSS classes |
setOnLoaderStart(callback) | Set loading callback |
setOnLoadError(callback) | Set error callback |
Available Components
| Tag Name | Description |
|---|---|
<dialstack-call-history> | Compact call history for a phone number |
<dialstack-call-logs> | Call history table |
<dialstack-voicemails> | Voicemail list with playback |
<dialstack-phone-numbers> | Unified phone number list with search |
Event Handling
Set event handlers using setter methods:
const callLogs = document.querySelector('dialstack-call-logs');
callLogs.setOnLoadError((event) => {
console.error('Load failed:', event.error);
});
callLogs.setOnRowClick((event) => {
console.log('Clicked call:', event.callId);
});
Framework Integration
Vue.js
<template>
<div>
<dialstack-call-logs ref="callLogs"></dialstack-call-logs>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
// The root entry registers the custom elements on import
import { loadDialstackAndInitialize } from '@dialstack/sdk-js';
const callLogs = ref(null);
onMounted(async () => {
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;
},
});
callLogs.value.setInstance(dialstack);
});
</script>
Angular
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
// The root entry registers the custom elements on import
import { loadDialstackAndInitialize } from '@dialstack/sdk-js';
@Component({
selector: 'app-voice-dashboard',
template: ` <dialstack-call-logs #callLogs></dialstack-call-logs> `,
})
export class VoiceDashboardComponent implements OnInit {
@ViewChild('callLogs') callLogsRef!: ElementRef;
async ngOnInit() {
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;
},
});
this.callLogsRef.nativeElement.setInstance(dialstack);
}
}
Svelte
<script>
import { onMount } from 'svelte';
// The root entry registers the custom elements on import
import { loadDialstackAndInitialize } from '@dialstack/sdk-js';
let callLogsEl;
onMount(async () => {
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;
},
});
callLogsEl.setInstance(dialstack);
});
</script>
<dialstack-call-logs bind:this={callLogsEl}></dialstack-call-logs>
Next Steps
- call-history Element - Compact call history reference
- call-logs Element - Call logs reference
- voicemails Element - Voicemails reference
- phone-numbers Element - Phone numbers reference
- Theming - Customize appearance