Theming and dark mode
The Appilot Widget renders in a closed Shadow DOM, so it never inherits your page's styles by accident, and your page never inherits the widget's. You stay in control of its appearance through configuration.
This page covers light/dark theming and brand color, both fully supported today. Layout modes beyond the floating bubble are tracked separately (see Layout modes).
Theme modes
Set the theme policy with the data-theme attribute (or the theme option in
the JS API). Four values:
| Value | Behavior |
|---|---|
auto | Default. Follows the visitor's operating-system preference (prefers-color-scheme), and updates live if they change it. |
light | Always light. |
dark | Always dark. |
host | Follows your site's own light/dark state, live. See Match your site's theme. |
<script
type="module"
src="https://cdn.appilot.com/widget/v1/appilot.esm.js"
data-theme="auto"
async
></script>
import { initAppilot } from '@appilot/widget';
initAppilot({ theme: 'auto' });
The default is now auto (it used to be light). If you relied on the widget
always rendering light regardless of the visitor's OS, set data-theme="light"
explicitly.
Match your site's theme
Most applications already have their own light/dark toggle. You have two ways to keep the assistant in lockstep with it.
Option A: data-theme="host" (no code)
Set data-theme="host" and the widget mirrors your page's own theme signal,
live, with no JavaScript on your side. It reads, in order:
<html data-theme="dark">or<html data-theme="light"><html data-color-scheme="dark|light">- a
dark/theme-dark/dark-modeclass on<html>(and the light twins) - otherwise, the OS preference
It watches those with a MutationObserver, so the instant your toggle flips the
attribute or class, the widget flips too. This is the recommended approach if
your site advertises its scheme on the <html> element (the common convention,
including Tailwind's dark class and the data-theme attribute pattern).
<!-- Your site sets <html data-theme="dark"> when the user picks dark mode -->
<script
type="module"
src="https://cdn.appilot.com/widget/v1/appilot.esm.js"
data-theme="host"
async
></script>
Option B: Appilot.setTheme() (explicit)
If your theme state does not live on <html> (for example it is held in a
framework store), drive the widget explicitly from your own toggle:
// Whenever your app's theme changes:
window.Appilot.setTheme('dark'); // 'light' | 'dark' | 'auto' | 'host'
setTheme takes effect immediately and does not re-mount the widget, so the
open conversation is preserved. It is available as soon as the bundle has
loaded.
Use data-theme="host" when your scheme is reflected on <html> (most sites).
Use Appilot.setTheme() when it is not, or when you want full programmatic
control. They are interchangeable, not exclusive.
Built-in palettes
Each mode uses Appilot's built-in palette, tuned for contrast and consistency with the rest of the assistant UI (the same design tokens the Chrome extension uses). Light renders on a white surface with a cyan accent; dark renders on a near-black surface with a brighter cyan accent. You do not need to define any colors to get a polished result in either mode.
Brand color
By default the assistant uses Appilot's cyan accent. To make it adopt your brand
color, set --appilot-brand (and, optionally, a dark-mode variant
--appilot-brand-dark). The accent recolors the primary surfaces (the header,
the send button, selection highlights) in both themes.
There are two equivalent ways to set it.
data-accent (no CSS)
<script
type="module"
src="https://cdn.appilot.com/widget/v1/appilot.esm.js"
data-accent="#e0457b"
data-accent-dark="#ff7aa8"
async
></script>
data-accent applies to both light and dark. Add data-accent-dark only when
you want a distinct (usually lighter) accent in dark mode; if you omit it, the
single data-accent is used in both.
CSS custom property
The channel is a CSS custom property, and custom properties DO inherit through
the Shadow DOM boundary, so you can also set it from your own stylesheet on the
appilot-assistant element, including per-theme:
appilot-assistant { --appilot-brand: #e0457b; }
html[data-theme="dark"] appilot-assistant { --appilot-brand-dark: #ff7aa8; }
This is the supported brand channel. (Setting --appilot-primary directly still
has no effect: the widget defines that token inside its Shadow DOM :host, which
out-specifies an inherited value. --appilot-brand is read by the widget
precisely so the inheritance works.)
The accent sits behind white text in the header and on the primary button. Pick
a color with enough contrast against white (a mid-to-dark tone). If your brand
color is very light, use a darker data-accent and reserve the light tone for
data-accent-dark.
Bubble size
The floating bubble defaults to 400px wide and up to 680px tall (capped to the
viewport). Override with data-width / data-height. A bare number is treated
as pixels; any CSS length (px, vh, min(...)) is accepted:
<script
type="module"
src="https://cdn.appilot.com/widget/v1/appilot.esm.js"
data-width="420"
data-height="90vh"
async
></script>
On small screens the bubble is automatically capped to the viewport regardless of these values.
Brand name
The header shows your organization's name by default. Override the displayed
text with data-brand-name:
<script
type="module"
src="https://cdn.appilot.com/widget/v1/appilot.esm.js"
data-brand-name="Acme Support"
async
></script>
Layout modes
Layout modes beyond the floating bubble (a docked sidebar, an inline embed) are
on the roadmap and not yet available. The bubble is the supported placement
today; position it with data-position="bottom-left" / "bottom-right".