REFERENCE
SDK Demos
How to use @asgard-js/core and @asgard-js/react, with demos you can try on the page.
Message Composition Primitives
The custom renderer lets you take over how a message is drawn entirely. But most of the time what you want to change is the content, not the layout — full-width bot text, a right-aligned user bubble, the placement of quick replies and the message-action row should all stay as they are.
So the SDK exports the primitives its default rows are built from, ready to compose.
The Primitives
Primitive Role TemplateBoxThe row frame — alignment and direction ( type: 'user' | 'bot')TemplateBoxContentThe bot row's content container; handles quick replies and message actions BotMessageTextThe bot text body, with Markdown rendering and theme colors UserMessageTextThe user text bubble TimeDeprecated — renders nothing (see below) Usage
Use them from
renderMessageContent, and fall back withrenderDefaultContent()for rows you don't handle:import {
TemplateBox,
TemplateBoxContent,
BotMessageText,
UserMessageText,
} from "@asgard-js/react";
import { MessageTemplateType } from "@asgard-js/core";
<Chatbot
renderMessageContent={({ message, renderDefaultContent }) => {
// User row: turn the leading mention into a chip, keep everything else
if (message.type === "user" && message.text.startsWith(MENTION)) {
return (
<TemplateBox type="user" direction="horizontal">
<UserMessageText>
<span className="mention-chip">{MENTION}</span>
{message.text.slice(MENTION.length)}
</UserMessageText>
</TemplateBox>
);
}
// Bot text row
if (message.type === "bot") {
const template = message.message?.template;
const isText = template?.type === MessageTemplateType.TEXT || !template?.type;
const text = message.isTyping ? message.typingText : message.message?.text;
if (isText && text) {
return (
<TemplateBox type="bot" direction="horizontal">
<TemplateBoxContent
message={message}
quickReplies={template?.quickReplies}
references={template?.references}
>
<BotMessageText>{text}</BotMessageText>
</TemplateBoxContent>
</TemplateBox>
);
}
}
return renderDefaultContent();
}}
/>Text While Streaming
When
message.isTypingis true, readmessage.typingTextrather thanmessage.message.text— the latter is only populated once the message completes. The example above already handles this.Why Not Just Hand-roll It
Hand-rolled rows drift from these, and keep drifting every time the SDK changes:
- Bot text is full-width with no bubble; only user rows are bubbles — different layout rules
TemplateBoxContentalso positions quick replies and the message-action row- Alignment, direction and theme colors all hang off
TemplateBoxrather than being scattered
In short: change the content, keep the layout.
TimeNo Longer Renders AnythingThe chat surface no longer shows message timestamps anywhere.
<Time />is kept as a no-op and everyTimePropsfield is ignored, purely so existing callers keep compiling; delete your<Time />when convenient.The value it used to render was never the message's own time: the SDK stamped
new Date()as each frame arrived, and a GET rejoin replays the whole history at once, so every replayed message was re-stamped with the moment the page opened. The backend carries no per-message timestamp to put in its place.The
timefield onConversationMessageis deprecated for the same reason — nothing in the SDK renders it.ChatHeaderThe same idea applies to the heading bar.
ChatHeaderis exported for use withrenderHeader; to swap only the title area while keeping the rest of the structure, userenderTitle. See Custom Header.See Also
- Custom Renderer — take over a message entirely
- Message Actions — the action row under a message
- Custom Header — the heading bar's three customization tiers