Web components are not supported for admin portal components
vanilla-js exports web components, allowing for integration with frameworks like Vue.js and Svelte,
or no frameworks at all.
Components must first be registered with customElements.define(),
then have a Stytch client and config passed in. They can still appear in HTML
first but they will not render anything until they are registered and
configured.
import { createStytchB2BClient, StytchB2B } from '@stytch/vanilla-js/b2b';
const stytch = createStytchB2BClient("${publicToken}");
customElements.define('stytch-ui', StytchB2B);
// If you have it in the HTML, you can query for it
// <stytch-ui id="stytch-ui"></stytch-ui>
const element = document.getElementById('stytch-ui');
// Or instead of writing <stytch-ui> in HTML, you can also initialize the elements in JS
// and insert it into the DOM manually
const element = new StytchB2B();
document.body.appendChild(element);
// All options can be passed in all at once using the .render() function
element.render({
client: stytch,
config: { ... }
});
// Or set properties individually
element.presentation = {
theme: { ... },
};
Most properties can also be updated. This can be used to, for example, update the component when the user switches themes. For object and array properties, a new object or array must be passed in.
// Updating the background
element.presentation = {
theme: { ...previousTheme, background: '...' },
};
// These will not work
element.presentation.theme.background = '...';
previousTheme.background = '...';
Custom element registration
Custom elements must only be defined once, so when used in reusable components
we recommend adding a check to the customElements.define() call.
if (!customElements.get('stytch-ui')) {
customElements.define('stytch-ui', StytchB2B);
}
Stytch client
We recommend defining the Stytch client as a singleton in a separate file so it
is only initialized once.
import { createStytchB2BClient } from '@stytch/vanilla-js/b2b';
export const stytch = createStytchB2BClient(
import.meta.env.REACT_APP_STYTCH_PUBLIC_TOKEN,
);
Events
For easier binding, Stytch UI also implements callbacks as custom DOM events. These are more verbose than using callbacks directly but your framework may have better syntax for binding listeners.
See callbacks for Login component and callbacks for Identity Provider for more information.
// Using the callbacks property
element.callbacks = {
onEvent: (evt) => {
console.log('Stytch event', evt.type, evt.data);
},
onError: (error) => {
console.log('Stytch error', error);
},
};
// Or the equivalent in custom DOM events
element.addEventListener('stytch-event', (evt) => {
// evt is typed StytchDOMEvent
console.log('Stytch event', evt.stytchEventType, evt.stytchEventData);
});
element.addEventListener('stytch-error', (evt) => {
// evt is typed StytchError
console.log('Stytch error', evt.error);
});
Shadow DOM
To isolate component CSS and DOM from the outside, the shadow attribute or constructor parameter can be used.
This can be useful if you find Stytch UI components being affected by the page’s CSS or JavaScript.
See the MDN article on shadow DOM for more information.
<stytch-ui shadow="true"></stytch-ui>
const element = new StytchB2B({ shadow: true });
flushRender()
Components only update after the next microtask. In the rare case you need the DOM to immediately update, call flushRender() after setting the property.
// Update theme
element.presentation = { theme: { ... } };
// The DOM will be updated immediately after this call rather than after next tick
element.flushRender();
Framework integration examples
Vue.js
Stytch UI can be used directly in Vue.js as a custom element.
To avoid component resolution warnings during development, see how to set isCustomElement compiler option.
import { createStytchB2BClient } from '@stytch/vanilla-js/b2b';
export const stytch = createStytchB2BClient(
import.meta.env.REACT_APP_STYTCH_PUBLIC_TOKEN,
);
<script setup>
import { stytch } from './stytch';
import { B2BProducts, StytchB2B } from '@stytch/vanilla-js/b2b';
if (!customElements.get('stytch-ui')) {
customElements.define('stytch-ui', StytchB2B);
}
const config = {
products: [B2BProducts.oauth, B2BProducts.emailMagicLinks],
// ... more config
};
const handleStytchEvent = (evt) => {
console.log('Stytch event', evt.stytchEventType, evt.stytchEventData);
};
const handleStytchError = (evt) => {
console.log('Stytch error', evt.error);
};
</script>
<template>
<stytch-ui
.client="stytch"
.config="config"
@stytch-event="handleStytchEvent"
@stytch-error="handleStytchError"
/>
</template>
Svelte
Stytch UI can be used directly in Svelte as a custom element.
import { createStytchB2BClient } from '@stytch/vanilla-js/b2b';
export const stytch = createStytchB2BClient(
import.meta.env.REACT_APP_STYTCH_PUBLIC_TOKEN,
);
<script>
import { stytch } from './stytch';
import { B2BProducts, StytchB2B } from '@stytch/vanilla-js/b2b';
if (!customElements.get('stytch-ui')) {
customElements.define('stytch-ui', StytchB2B);
}
const config = {
products: [B2BProducts.oauth, B2BProducts.emailMagicLinks],
// ... more config
};
const handleStytchEvent = (evt) => {
console.log('Stytch event', evt.stytchEventType, evt.stytchEventData);
};
const handleStytchError = (evt) => {
console.log('Stytch error', evt.error);
};
</script>
<stytch-ui client={stytch} {config} onstytch-event={handleStytchEvent} onstytch-error={handleStytchError}
></stytch-ui>