Presets
Picklight (default), dark, or auto (follows the visitor’s prefers-color-scheme):
Theme tokens
Layer per-property overrides on top of a preset. The same keys work everywhere:CSS variables
The widget exposes a--ww-* namespace that pierces the Shadow DOM boundary, so the script embed can be themed from your page’s own CSS:
floating mode there is no container of your own, so declare the variables on any ancestor — :root is the simplest. They inherit down into the widget either way.
Unset variables fall back to the preset’s defaults, and your overrides win in both light and dark modes.
borderWidth and boxShadow are the panel’s opt-in chrome — both are no-ops until you set them, so a widget slotted into your own bordered container doesn’t draw a second border. In the script embed they apply to the [data-waniwani-embed] container rather than the chat inside it, since the container clips anything drawn within.
glassTint and glassTintStrength tint the floating bar’s frosted-glass surface — the expanded suggestion card and open panel in floating mode — layering a colour over the existing backdrop blur. glassTint takes any CSS colour string; glassTintStrength is a unitless string from "0" to "1" setting how strongly the tint is applied. Both are set programmatically through appearance.variables:
borderWidth and boxShadow, they’re additive: leave them unset and the floating bar renders exactly as before.
Assistant message bubble (opt-in)
Assistant replies render as plain text by default. Turn them into filled bubbles — styled byassistantBubbleColor / assistantBubbleTextColor, sharing the user bubble’s radius and padding — with assistantBubble:
Deep customization
Tokens cover colors, typography, and bubble shape. To restyle an element beyond what a token exposes, target it directly. React — passclassNames (available on ChatEmbed directly, or overrides.classNames on WaniwaniChat). Each string is merged onto that slot:
root, header, message, userBubble, assistantBubble, input.
Script embed — the widget renders in a Shadow DOM, so your page’s own selectors cannot reach inside. Inject a stylesheet with data-css and target the stable semantic classes:
.ww-message, .ww-message-user, .ww-message-assistant, .ww-bubble, .ww-header, .ww-input. These are guaranteed selectors — the internal ww:-prefixed utility classes are not.
What is not themeable
To set expectations for a full rebrand, these are intentionally fixed today:- Typographic scale beyond the base —
fontSize/lineHeightset the message base; per-heading sizes inside markdown and built-in label sizes/weights are not individually exposed. - Chrome corner radii —
messageBorderRadiusshapes message bubbles only; tool-call cards, the chain-of-thought accordion, menus, and welcome-screen buttons keep their fixed radii. - Floating launcher accent — the dock’s animated border-glow uses a fixed accent gradient.
- “Powered by” mark — the footer logo is not removable via theming.
ChatTheme and ChatClassNames.