> ## Documentation Index
> Fetch the complete documentation index at: https://stytch.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Web Component

> How to use Stytch UI web components and integrate with other frameworks

<Warning>Web components are not supported for admin portal components</Warning>

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.

```js theme={null}
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.

```ts theme={null}
// 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.

```js theme={null}
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.

```js stytch.js theme={null}
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](./callbacks) and [callbacks for Identity Provider](../identity-provider/callbacks) for more information.

```js theme={null}
// 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](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM#high-level_view) for more information.

```html theme={null}
<stytch-ui shadow="true"></stytch-ui>
```

```js theme={null}
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.

```js theme={null}
// 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](https://vuejs.org/guide/extras/web-components.html#skipping-component-resolution).

```js stytch.js theme={null}
import { createStytchB2BClient } from '@stytch/vanilla-js/b2b';

export const stytch = createStytchB2BClient(
  import.meta.env.REACT_APP_STYTCH_PUBLIC_TOKEN,
);
```

```vue StytchLogin.vue theme={null}
<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.

```js stytch.js theme={null}
import { createStytchB2BClient } from '@stytch/vanilla-js/b2b';

export const stytch = createStytchB2BClient(
  import.meta.env.REACT_APP_STYTCH_PUBLIC_TOKEN,
);
```

```svelte StytchLogin.svelte theme={null}
<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>
```
