Themes & locale
Brand color, light/dark mode, locale and time, fonts, and every design token.
Brand color (themeColor)
themeColor accepts any CSS color. The package turns it into a full accessible palette - accent, fills, soft bubbles, selected and hover washes - for both light and dark mode.
<ChatMain {...chatConfig} themeColor="#7c3aed" /><ChatMain {...chatConfig} themeColor="royalblue" /><ChatMain {...chatConfig} themeColor="var(--primary)" /> // host design token<ChatMain {...chatConfig} themeColor="hsl(220 70% 50%)" />At runtime it updates --chat-theme, --chat-theme-fill, --chat-theme-fg, --chat-theme-5…--chat-theme-60, --chat-selected, --chat-hover and the outgoing-bubble tokens.
Light / dark mode
Switching animates surfaces, text, borders, bubbles and brand washes over about 250ms, and respects prefers-reduced-motion. The toggle lives in Account settings, next to push notifications.
Date / time
<ChatMain {...chatConfig} locale="en-GB" timeZone="Europe/London" hour12={false} showDateTimeSettings={false} onDateTimePreferencesChange={(prefs) => console.log(prefs)}/>Font family & size
fontFamilyis any CSS font-family value and applies to the whole chat - the page shell and portalled menus, dialogs and drawers alike. Leave it out and chat keeps inheriting your app's font.
<ChatMain {...chatConfig} fontFamily="Inter, system-ui, sans-serif" />fontSize works per text role, so a bigger conversation title doesn't also blow up timestamps:
One value sets base and scales the rest with it (title ×1.08, subtitle ×0.92, description ×0.85). An object sets roles independently - roles you leave out keep the package default:
<ChatMain {...chatConfig} fontSize={15} /> // px<ChatMain {...chatConfig} fontSize="1rem" /> // any CSS length <ChatMain {...chatConfig} fontFamily="Inter, sans-serif" fontSize={{ base: 14, title: 18, subtitle: 13, description: 11 }}/> // Only titles change; everything else stays as shipped<ChatMain {...chatConfig} fontSize={{ title: "1.25rem" }} />These set --chat-font-family, --chat-font-size, --chat-font-size-title, --chat-font-size-subtitle and --chat-font-size-description on the chat root. Custom slots pick them up through the exported class recipes (chatSheetTitleClass, chatSheetSubtitleClass, chatDetailLabelClass, …) or by reading the variables:
.my-custom-drawer-title { font-size: var(--chat-font-size-title, 13px);}Design tokens (themeTokens)
Every color, border, radius and shadow reads a --chat-* token. themeTokens overrides any of them, separately for light and dark. They apply everywhere - sidebar, header, bubbles, menus, drawers, modals, tooltips, the in-call UI and the call pop-up window - and win over both the defaults and the palette from themeColor.
<ChatMain {...chatConfig} themeColor="#0f766e" themeTokens={{ light: { "--chat-incoming-bubble": "#f1f5f9", "--chat-outgoing-bubble": "#ccfbf1", "--chat-bubble-radius": "18px", "--chat-border-color": "#e2e8f0", "--chat-main-bg": "#ffffff", }, dark: { "--chat-incoming-bubble": "#1e293b", "--chat-outgoing-bubble": "#134e4a", "--chat-bubble-radius": "18px", "--chat-border-color": "rgba(255,255,255,0.08)", }, }}/>For a value in both modes, put it in both maps (spread one shared object into each). Keys that don't start with --chat- are ignored.