Embed reference
Every attribute, CSS token, custom event, and imperative method exposed by the <breeze-buddy-assist> custom element.
<breeze-buddy-assist> is a Svelte 5 custom element that renders inside a Shadow DOM, so host-page CSS cannot bleed in and widget CSS cannot bleed out.
Attributes
All attributes map to Svelte component props. Attribute names are kebab-case; the internal prop name is camelCase.
Required
| Attribute | Type | Description |
|---|---|---|
tenant | string | The public_widget_key from your widget_config row. Identifies the merchant and the allowed-origin list to verify against. |
api-base | string | Base URL of the Clairvoyance backend. Default: https://clairvoyance.breezelabs.app. |
Session
| Attribute | Type | Default | Description |
|---|---|---|---|
shop | string | "unknown.myshopify.com" | The .myshopify.com permanent domain of the Shopify store. Forwarded to the template as template_vars.shop_url and used to scope the Shopify MCP tools. Required for Shopify storefronts; safe to omit on non-Shopify sites. |
customer-token | string | "" | Optional short-lived token minted by your backend that carries customer identity (e.g. Shopify customer ID, email). Forwarded to the template as template_vars.shopify_customer_token; not validated by the widget itself. |
Modes
| Attribute | Type | Default | Description |
|---|---|---|---|
modes | string | "text,voice" | Comma-separated list of enabled channels. Currently supported values are text and voice. Pass "text" to hide the voice button. |
default-mode | "text" \| "voice" | "text" | Which mode is active when the panel first opens. |
Appearance
| Attribute | Type | Default | Description |
|---|---|---|---|
theme | "light" \| "dark" | "light" | Colour scheme. The widget respects this attribute, not the OS prefers-color-scheme; sync them yourself if you want auto dark mode. |
position | "bottom-right" \| "bottom-left" | "bottom-right" | Which viewport corner the launcher anchors to. |
offset-x | CSS length | "24px" | Horizontal distance from the chosen edge. Accepts any CSS length (24px, 2%, 3vh, calc(…)). |
offset-y | CSS length | "24px" | Vertical distance from the bottom edge. |
launcher-style | "mascot" \| "solid" | "mascot" | "mascot" — pearly orb with eyes. "solid" — oil-slick sunset orb, no face. |
launcher-label | string | "Talk to an Agent" | CTA text on the launcher pill. Set to "" to collapse the pill to a bare orb. |
Header
| Attribute | Type | Default | Description |
|---|---|---|---|
header-title | string | "Buddy Assist" | Text shown next to the logo in the chat header. Set to your merchant / brand name. |
header-logo-url | string | — | URL of a square merchant logo image shown in the chat header. Replaces the default mascot orb. Rendered at 22 × 22 px with a circular crop; use a 44 × 44 px image at 2× for sharpness on retina screens. |
Theming
Each prop sets a CSS custom property on the shadow host. If unset the widget falls back to its built-in light/dark token defaults. A pinned brand colour wins over both light and dark defaults, so the colour won’t shift when theme flips.
| Attribute | CSS variable | Affects |
|---|---|---|
primary-color | --primary-color | Accent colour — send button, active states, focus rings |
surface-color | --surface-color | Chat panel background |
text-color | --text-color | Primary text |
muted-text-color | --muted-text-color | Secondary / placeholder text |
user-bubble-bg | --user-bubble-bg | User message bubble background |
user-bubble-fg | --user-bubble-fg | User message bubble text |
For finer control, set any --bb-* / --fg-* / --surface-* token directly via an inline style attribute on the host element:
<breeze-buddy-assist
style="--bb-launcher-glow-color: #6c47ff40"
tenant="…"
api-base="…"
></breeze-buddy-assist> Development
| Attribute | Type | Default | Description |
|---|---|---|---|
mock | boolean | false | Deprecated as of client-sdk 0.3.0 — the mock transport was retired with the SpecStream migration. Setting mock="true" logs a console warning and falls through to the real transport. |
Declarative open
Add the bare open HTML attribute to start the widget open on page load. This is a one-shot read on mount — toggling the attribute after mount has no effect; use the imperative API instead.
<breeze-buddy-assist open tenant="…" api-base="…"></breeze-buddy-assist> Imperative API
After the widget mounts it exposes three ways to control it from any script on the page. All three support the same actions: open, close, reset.
1 — DOM method (same-page scripts)
The simplest option. Query the element and call the method directly:
const el = document.querySelector('breeze-buddy-assist');
el.open(); // open the panel
el.close(); // close the panel (session + history preserved)
el.reset(); // close and destroy the current session reset() is client-side only — the server session stays ACTIVE until idle-timeout. Call POST /widget/session/{id}/end for immediate server cleanup.
2 — window.BreezeAssist global
The widget publishes a global so any script — including ones that load before or after the element — can call it without querying the DOM:
window.BreezeAssist.open();
window.BreezeAssist.close();
window.BreezeAssist.reset();
window.BreezeAssist.isOpen(); // returns boolean This is the recommended option for Shopify theme scripts, GTM custom HTML tags, and third-party snippets that don’t own the element reference.
3 — CustomEvent (GTM / tag managers)
Dispatch a breeze-buddy-assist:command event on document. Works from Google Tag Manager custom HTML tags, Segment, or any tool that can run document.dispatchEvent:
document.dispatchEvent(
new CustomEvent('breeze-buddy-assist:command', {
detail: { action: 'open' } // 'open' | 'close' | 'reset'
})
); 4 — postMessage (iframes)
If your page embeds the storefront in an iframe, or you need to trigger from a cross-origin context, post a message to the parent window:
// From inside an iframe:
window.parent.postMessage(
{ type: 'breeze-buddy-assist', action: 'open' }, // 'open' | 'close' | 'reset'
'*'
); Trigger from a button
The most common use-case — a CTA button elsewhere on the page opens the widget:
<button id="open-chat">Chat with us</button>
<breeze-buddy-assist
tenant="pk_live_…"
api-base="https://clairvoyance.breezelabs.app"
></breeze-buddy-assist>
<script src="https://widget.breezebuddy.com/assist.js" async></script>
<script>
document.getElementById('open-chat').addEventListener('click', () => {
window.BreezeAssist.open();
});
</script> To hide the default launcher FAB when using your own button, listen for ready and then hide it:
document.querySelector('breeze-buddy-assist').addEventListener(
'breeze-buddy-assist:ready',
() => document.getElementById('open-chat').style.display = 'none'
); React / framework usage
import { useEffect } from 'react';
export function ChatButton() {
return (
<button onClick={() => (window as any).BreezeAssist?.open()}>
Chat with us
</button>
);
} Or typed properly:
declare global {
interface Window {
BreezeAssist?: {
open(): void;
close(): void;
reset(): void;
isOpen(): boolean;
};
}
} Custom events
All events are dispatched on the host element (outside the Shadow DOM) with bubbles: true and composed: true, so standard addEventListener on the element or any ancestor catches them.
Event names are prefixed with breeze-buddy-assist:.
| Event | detail shape | When |
|---|---|---|
breeze-buddy-assist:ready | undefined | Element mounted. Fires before any session is created. |
breeze-buddy-assist:open | undefined | Panel opened. |
breeze-buddy-assist:close | undefined | Panel closed. |
breeze-buddy-assist:message | { role: "user" \| "assistant", content: string, sessionId: string \| null } | A message was sent or received. Fires for both sides of the conversation. |
breeze-buddy-assist:error | { error: string, code: string } | An error occurred. See error codes below. |
breeze-buddy-assist:open-url | { url: string, target: "_self" \| "_blank", reason?: string, lifecycle?: string } | The agent asked to navigate to a URL (via a generative-UI action). The event is cancelable — call event.preventDefault() to intercept the navigation. If not cancelled the widget opens the URL via window.open. |
Error codes
| Code | Description |
|---|---|
voice_live_conflict | A chat message was sent while a voice attachment was live, or vice versa. The two channels are mutually exclusive. |
turn_exception | An unhandled exception was thrown during the chat turn. |
session_error | A generic error emitted by the SDK session. |
Example — analytics tap
document.querySelector('breeze-buddy-assist').addEventListener(
'breeze-buddy-assist:message',
(e) => {
analytics.track('chat_message', {
role: e.detail.role,
sessionId: e.detail.sessionId
});
}
); Example — intercept link navigation
document.querySelector('breeze-buddy-assist').addEventListener(
'breeze-buddy-assist:open-url',
(e) => {
e.preventDefault(); // stop the widget from calling window.open
myRouter.push(e.detail.url); // handle with your SPA router
}
);