Chat widget chrome
Own the Inbox launcher and panel from src/layout/chat.tsx using the platform parts in @poltura/theme-sdk/inbox.
On this page
The storefront's Inbox chat widget is theme chrome, like the promo bar. The
platform keeps the session, the live connection, message delivery and attachments
behind @poltura/theme-sdk/inbox. The theme decides
how the pieces are arranged.
Where it is
Put the widget in src/layout/chat.tsx as the file's default export. The
storefront mounts it from that path. Without the file, the platform's complete
widget mounts instead, the same one <InboxWidget /> draws. The default theme
ships this file:
import {
InboxChatGlyph,
InboxComposer,
InboxConversation,
InboxLauncher,
InboxOfflineForm,
InboxPanel,
InboxPanelHeader,
InboxRoot,
InboxStatusLine,
} from '@poltura/theme-sdk/inbox';
export default function ThemeChatWidget() {
return (
<InboxRoot className='pol-chat'>
<InboxPanel className='pol-chat__panel'>
<InboxPanelHeader className='pol-chat__header' />
<InboxConversation className='pol-chat__conversation' />
<InboxStatusLine className='pol-chat__status' />
<InboxOfflineForm className='pol-chat__offline' />
<InboxComposer className='pol-chat__composer' />
</InboxPanel>
<InboxLauncher className='pol-chat__launcher'>
<InboxChatGlyph />
</InboxLauncher>
</InboxRoot>
);
}Every part must render inside <InboxRoot>, which renders nothing when the
store offers no chat. useInbox() reads the view and actions from that context.
Render InboxConversation as the panel body. It shows the message list, and
shows the open help article in its place once a shopper picks one. A layout that renders
InboxMessageList directly must switch to InboxKnowledgeArticle itself while
view.knowledge.article is set, or picking an article does nothing visible.
Parts
| Component | Props | Role |
|---|---|---|
InboxRoot | children, className? | Fixed wrapper, CSS variables, state and context |
InboxWidget | none | The complete widget, built from the parts below |
InboxLauncher | className?, children? | Button; children replace the default glyph |
InboxPanel | className?, children | Dialog (id="poltura-inbox-panel") |
InboxPanelHeader | className?, title?, children? | Accent header: title, reply-time / offline status, close icon |
InboxConversation | className?, renderMessage? | Panel body: InboxMessageList, or the open article in its place |
InboxMessageList | className?, renderMessage? | Scroll log, empty-state greeting and help, typing, jump to latest |
InboxMessageBubble | message, className? | Default bubble |
InboxComposer | className?, placeholder? | Pill with attach, text field and send icon |
InboxOfflineForm | className? | Email and message fields when view.online === false |
InboxStatusLine | className? | Reconnecting / preview bar above the composer |
InboxChatGlyph | size?, className? | Default launcher icon |
InboxKnowledgeSearch | className?, placeholder? | Debounced help-article search (store knowledge base) |
InboxKnowledgeArticle | className? | Open article body with back |
InboxKnowledgeSuggestions | className?, limit? | Top articles above the greeting when the thread is empty |
useInbox() returns { view, actions }:
view.copyholds the widget's wording, already resolved: the theme'schattexts first, then the platform'sinbox.*messages.actions.send,attach,removeAttachmentandretryare the only chat actions a theme calls.actions.open,closeandtoggledrive the panel.view.appearancecarries the merchant's side, colour mode and colours.- The store's help articles live on
view.knowledge(enabled,query,results,loading,article), withactions.searchKnowledge,openArticleandcloseArticle.enabledis true when the store has at least one published article. An article links to/guides/{category}/{slug}when that page exists. Otherwise the panel shows its sanitized body inline.
The platform widget (InboxWidget) shows an empty thread as a greeting card and
one Help section: a search field, then up to three suggested articles.
InboxMessageList draws that empty state when help articles are on.
InboxConversation replaces the list with InboxKnowledgeArticle while an
article is open. "Still need help? Send a message" closes the article and
focuses the composer. In the Customizer, the help search returns sample results.
The launcher stays visible on desktop while the panel is open, and hides on
screens narrower than 640px.
Stable classes
Restyle from src/styles/theme.css with :where(), same as the other chrome
hooks. See Chrome stable classes.
| Class | Node |
|---|---|
inbox-root | fixed wrapper (data-poltura-inbox, data-open, data-online, data-connection) |
inbox-launcher | launcher button (aria-expanded, data-unread) |
inbox-launcher__badge | unread count pill on the launcher |
inbox-panel | dialog |
inbox-panel__header | header row |
inbox-panel__title | header title |
inbox-panel__status | one-line reply-time / offline status |
inbox-panel__status-dot | online (green) / offline (grey) dot |
inbox-panel__close | header close icon button |
inbox-messages | role="log" |
inbox-greeting | empty-thread greeting card |
inbox-help | empty-thread Help section (search and suggestions) |
inbox-help__label | the single "Help" section label |
inbox-message-row | message wrapper containing author, bubble and metadata; --system for centred system text |
inbox-message | actual bubble only; plus --customer, --staff, --ai |
inbox-message__author | staff / AI name row |
inbox-message__disclosure | AI disclosure line |
inbox-message__meta | relative time and delivery ticks |
inbox-message__time | relative timestamp |
inbox-message__ticks | delivery copy on the last customer message |
inbox-day | optional day separator in the log |
inbox-typing | three-dot typing indicator |
inbox-jump | jump-to-latest control |
inbox-composer | composer form |
inbox-composer__input | auto-growing textarea |
inbox-composer__attach | paperclip button |
inbox-composer__send | paper-plane submit |
inbox-composer__chip | pending attachment chip |
inbox-status | reconnecting / preview bar |
inbox-offline | offline capture form |
inbox-offline--success | offline form success copy |
inbox-knowledge-search | help search field and results |
inbox-knowledge-suggestions | empty-thread article rows |
inbox-knowledge-article | open article panel |
inbox-knowledge-article__body | sanitized article HTML |
inbox-knowledge-article__back | article back control |
inbox-knowledge-article__cta | "Still need help" control |
Colours are CSS variables on the root: --inbox-accent, --inbox-accent-text,
--inbox-bg and --inbox-text.
Settings
The theme settings group chat (and chat_dark for the dark mode colours)
styles the widget in the Customizer. It does not turn chat on for the store:
that is the store's Inbox setting.
| Setting | What it does |
|---|---|
chat.enabled | hides the launcher when false (selecting the chat in the Customizer still opens it) |
chat.position | right or left |
chat.appearance_mode | auto, light, dark |
chat.accent / accent_text / background / text | panel colours |
chat.launcher_label / title / greeting / offline_message | copy overrides |
Selecting the chat in the Customizer opens the panel on sample data. InboxRoot
does this, so theme code needs nothing for it.
Next
- Chrome stable classes: the override pattern for every platform part.
- inbox reference: every export of
@poltura/theme-sdk/inbox.