Documentation

Theming

Match the widget's look to your brand.

The widget renders with Tailwind classes on top of a small set of design tokens you can override. Three knobs cover most cases: a built-in theme name, CSS variable overrides, and arbitrary class names on the outer container.

Built-in themes

Pass theme: 'light' or theme: 'dark' to the React wrapper or to window.AppmintChat.init. Light is the default. The dark theme inverts the panel background, message bubbles, and header.

<AppmintChat orgId="..." configId="..." appId="..." theme="dark" />

Inside the bundle, the active theme is stored in the chat store and read by every component.

CSS variable overrides

The widget exposes its colour and spacing tokens as CSS variables on the panel root. Override them in your host stylesheet to match your brand:

.appmint-chat-root {
  --amc-primary: #6d28d9;          /* purple-700 — accent and "send" button */
  --amc-primary-hover: #5b21b6;
  --amc-bubble-self: #ede9fe;      /* visitor's message background */
  --amc-bubble-other: #ffffff;     /* agent's message background */
  --amc-text: #111827;
  --amc-muted: #6b7280;
  --amc-bg: #ffffff;
  --amc-border: #e5e7eb;
  --amc-radius: 1rem;
}

These names mirror the tokens in src/styles/global.dev.css. The exact list moves over time — check the source for the canonical set, especially the section above @layer components.

The dark variant uses the same variables under a .appmint-chat-root.dark selector. To customise dark mode, scope your overrides:

.appmint-chat-root.dark {
  --amc-bg: #0f172a;
  --amc-text: #f8fafc;
}

Class name overrides

Both the React wrapper and the init call accept a className prop. Tailwind classes are merged onto the widget's outer container with tailwind-merge, so later classes win:

<AppmintChat
  orgId="..."
  configId="..."
  appId="..."
  className="bottom-32 right-12"   // moves the bubble higher and further from the edge
/>

The default position is bottom-24 right-10 (left when chatBubblePosition is set in the chat config). Use this to avoid clashing with cookie banners, intercom widgets, or footer CTAs.

Theme object

For deeper customisation pass theme as an object instead of a string. The shape is shallow-merged onto the token map:

<AppmintChat
  orgId="..."
  configId="..."
  appId="..."
  theme={{
    name: 'light',
    primary: '#6d28d9',
    bubbleSelf: '#ede9fe',
    bubbleOther: '#ffffff',
    radius: '1rem',
  }}
/>

The widget's renderers map these into CSS variables on the panel root, so the result is the same as setting them in your host stylesheet — but it travels with the component.

Dark mode following the system preference

If you want the widget to follow the user's system preference rather than a hard-coded value, switch on the media query at mount time:

const [theme, setTheme] = useState<'light' | 'dark'>('light');

useEffect(() => {
  const mq = window.matchMedia('(prefers-color-scheme: dark)');
  setTheme(mq.matches ? 'dark' : 'light');
  const onChange = (e: MediaQueryListEvent) => setTheme(e.matches ? 'dark' : 'light');
  mq.addEventListener('change', onChange);
  return () => mq.removeEventListener('change', onChange);
}, []);

return <AppmintChat orgId="..." configId="..." appId="..." theme={theme} />;

Server-side dark mode is also possible by reading the cookie or Sec-CH-Prefers-Color-Scheme header from a Next.js server component and forwarding theme through your wrapper.

Custom logo and welcome content

Most branding doesn't need code — it lives in the chat-config record. logo.url, welcome.title, welcome.subtitle, and headerContent are all read by the widget on boot. Edit them in the admin UI and every visitor sees the new values on the next page load.

There is no slot/render-prop API today for replacing internal subtrees of the panel (message bubble, header, composer). See Slots for the current state.