Theming sets the look of the whole widget at once: colours, type, dark mode and layout. To change one part only, use Component styles, which always win over theming.

Colours

Brand colour

The brand colour paints the accents: the launcher, the send button, links and focus rings. Text on it is set to black or white, whichever reads better.
AttributeDescriptionDefault
data-brand-colorYour brand colour, such as #6306B6#343CED
data-brand-color-darkThe brand colour in dark modeThe light one

Colour palette

The palette sets surfaces, text and borders, separately from the brand colour.
AttributeWhat it paintsLight defaultDark default
data-surface-colorPanel background#ffffff#17171a
data-surface-elevated-colorCards, the question box, code blocks#f8fafc#212124
data-surface-hover-colorHover states#f1f5f9#2a2a2e
data-text-colorBody text#0f172a#e4e4e7
data-text-secondary-colorSecondary text#64748b#a1a1a9
data-text-muted-colorThe faintest text. Also sets secondary text when that is not set#94a3b8#71717a
data-border-colorBorders and dividers#e2e8f0#3f3f45
data-anchor-colorLinks inside an answerBrand colourBrand colour
data-overlay-colorThe dimmed backdrop behind the panelrgba(15,23,42,.35)rgba(0,0,0,.55)

Colour scheme

AttributeDescriptionDefault
data-color-scheme"light", "dark", or "auto" to follow the reader’s operating system"light"
The widget stays light even when the reader’s system is dark, unless you ask for "auto". Every palette attribute has a dark version: add -dark to the name, such as data-surface-color-dark.
  • Palette values apply to one mode. data-surface-color is used in light mode only, data-surface-color-dark in dark mode only. A mode you leave unset keeps its default. The light value is never reused in dark mode.
  • The brand colour and component styles apply to both modes. Their -dark version overrides them in dark mode only.

Syncing with your site’s theme

If your site has its own dark-mode switch, point the widget at what that switch sets. The widget follows it on load and every time the reader flips it.
AttributeDescriptionDefault
data-color-scheme-selectorA CSS selector that matches only while your page is dark. Match: the widget is dark. No match: light. Wins over data-color-schemeNot set
The selector is checked against the whole page, so a class on <html>, <body> or a wrapper all work. A selector that is not valid counts as “not dark”.
Site usesIts switch setsSelector
Docusaurusdata-theme="dark" on <html>[data-theme='dark']
Tailwind, Mintlifya dark class on <html>html.dark
Bootstrapdata-bs-theme="dark" on <html>[data-bs-theme='dark']
GitHub-styledata-color-mode="dark"[data-color-mode='dark']
A Support Form Deflector on the same script tag uses the same two settings, so both always match.

Per-component dark overrides

This header is light grey in light mode and near-black in dark mode:
<script
  async
  src="https://widget.kelu.dev/kelu-widget.js"
  data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
  data-client-key="kl_pk_..."
  data-color-scheme="auto"
  data-modal-header-background-color="#f0f0f0"
  data-modal-header-background-color-dark="#1a1a1a"
  data-modal-header-color="#333333"
  data-modal-header-color-dark="#ffffff"
></script>
Every component-style property and state takes the -dark suffix.

Example: a full light and dark theme

<script
  async
  src="https://widget.kelu.dev/kelu-widget.js"
  data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
  data-client-key="kl_pk_..."
  data-color-scheme="auto"
  data-brand-color="#6306B6"
  data-brand-color-dark="#9d5bd2"
  data-surface-color="#ffffff"
  data-surface-elevated-color="#f8f9fa"
  data-text-color="#111111"
  data-text-muted-color="#666666"
  data-border-color="#dee2e6"
  data-surface-color-dark="#17171a"
  data-surface-elevated-color-dark="#25252a"
  data-text-color-dark="#e4e4e7"
  data-text-muted-color-dark="#a1a1aa"
  data-border-color-dark="#3f3f45"
></script>

Typography and scale

AttributeDescriptionDefault
data-font-familyAny CSS font stackThe system font
data-font-size-xsSmallest text11.5px
data-font-size-smSmall text13px
data-font-size-mdBody text14px
data-font-size-lgLarge text15px
data-scale-factorMultiplies every text size and control size. "1.1" makes the widget 10% larger1
data-border-radiusCorner rounding of the panel and its cards16px
Give font sizes and the radius a unit, such as 15px: a bare number does not work here. The widget sizes everything in pixels, so your site’s base font size does not affect it. data-font-size-xl is accepted but changes nothing: no text uses that step.

View modes

data-view-mode changes the whole layout. Other options and component styles still apply on top.
ValueLayout
modal (default)A centred panel, 760px wide and 780px tall. Closes on Esc or a click outside it. The ⤢ header button widens it to data-modal-expanded-size (1500px)
sidebarA 460px panel (data-sidebar-width) that slides in from the right and fills the window’s height. The ⤢ button moves it to the centre of the screen
searchA panel near the top of the page, like a command palette, with no launcher. data-search-input="#your-search-box" attaches it to your own search field. See the search view mode
On screens under 600px, every mode fills the width of the screen. The widget remembers per knowledge base whether the reader expanded the panel. A panel docked to the right edge, so the assistant stays in view:
<script
  async
  src="https://widget.kelu.dev/kelu-widget.js"
  data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
  data-client-key="kl_pk_..."
  data-view-mode="sidebar"
  data-modal-open-by-default="true"
  data-launcher-button-hidden="true"
></script>
The sidebar always slides in from the right. See Sidebar style.