Custom message types
Register a LitElement to render any type string. When an incoming message arrives with that type, your component is mounted and messageData is set to the message's data payload.
Implement IMessageRenderer
import { LitElement, html, css } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ChatbotMixin } from "@chativa/ui"; // re-exports I18nMixin too
import { MessageTypeRegistry } from "@chativa/core";
@customElement("product-card-message")
export class ProductCardMessage extends ChatbotMixin(LitElement) {
@property({ type: Object }) messageData: Record<string, unknown> = {};
static styles = css`
:host { display: block; }
.card { border: 1px solid var(--chativa-border-color); border-radius: 12px; padding: 12px; }
`;
render() {
const { name, price, image } = this.messageData as {
name: string; price: string; image?: string;
};
return html`
<div class="card">
${image ? html`<img src=${image} alt="" />` : null}
<h3>${name}</h3>
<p>${price}</p>
</div>
`;
}
}
// Side-effect register on import
MessageTypeRegistry.register("product-card", ProductCardMessage);
Then any incoming { type: "product-card", data: { name, price, image } } is rendered with your component.
Override a built-in
Built-in types are registered when @chativa/ui loads. Re-registering after that point overrides them:
import "@chativa/ui"; // built-ins register here
import { MessageTypeRegistry } from "@chativa/core";
import { MyFancyTextMessage } from "./MyFancyTextMessage";
MessageTypeRegistry.register("text", MyFancyTextMessage); // overrides default text
Tips
- Extend
ChatbotMixin(LitElement)— it bringsI18nMixinand styling tokens. - Read CSS variables (
--chativa-primary-color,--chativa-bubble-bot-bg, …) in your styles to inherit the active theme. - Need to send a message back from inside your component? Use the
chativa-actioncustom event:
this.dispatchEvent(new CustomEvent("chativa-action", {
bubbles: true, composed: true,
detail: { value: "buy_now", label: "Buy now" },
}));
The widget converts that into an outgoing text message via the chat input.
Tip — use the scaffolder
The /new-message-type slash command creates the LitElement file, sibling test, and updates the packages/ui/src/index.ts side-effect imports. See .claude/commands/new-message-type.md.