Match your brand
Introduction
Section titled “Introduction”You will point the kit’s colours at your own design tokens, so the chat looks like part of your app, and add a light, dark and system switch. The kit styles itself with CSS variables, so a re-theme is a few lines of CSS.
What you need
Section titled “What you need”- The stylesheet setup from Add chat to a React app:
tokens.cssimported after Tailwind, and the@sourceline.
1. Import the tokens, then override them
Section titled “1. Import the tokens, then override them”Load tokens.css first, then redefine variables after it. Your rules win by order.
@import "tailwindcss";@import "@pilotoo/ui/tokens.css";
@source "../node_modules/@pilotoo/ui/dist";2. Map the variables you care about
Section titled “2. Map the variables you care about”Start with the accent and the surfaces. Each variable is a plain colour, so you can alias your own tokens.
:root { --primary: var(--brand-600); --primary-hover: var(--brand-700); --primary-active: var(--brand-700); --primary-weaker: color-mix(in srgb, var(--brand-600) 8%, transparent); --primary-weak: color-mix(in srgb, var(--brand-600) 25%, transparent); --primary-foreground: #ffffff;
--fill-bg-master: var(--surface-page); --surface-canvas: var(--surface-page); --surface-card: var(--surface-raised);}Import brand.css after styles.css.
3. Cover dark mode too
Section titled “3. Cover dark mode too”tokens.css defines dark in two places: the system preference, unless the page forces light, and an explicit data-theme="dark". Override both, or the chat keeps the kit’s dark colours.
@media (prefers-color-scheme: dark) { :root:not([data-theme='light']) { --primary: var(--brand-400); --primary-foreground: #101018; --fill-bg-master: var(--surface-page-dark); --surface-canvas: var(--surface-page-dark); --surface-card: var(--surface-raised-dark); }}
:root[data-theme='dark'] { --primary: var(--brand-400); --primary-foreground: #101018; --fill-bg-master: var(--surface-page-dark); --surface-canvas: var(--surface-page-dark); --surface-card: var(--surface-raised-dark);}4. Add a theme switch
Section titled “4. Add a theme switch”data-theme="light" or "dark" on the root element forces a scheme. No attribute follows the operating system. applyTheme does exactly that.
import { useState } from 'react';import { applyTheme } from '@pilotoo/ui/settings';
type Theme = 'light' | 'dark' | 'system';
export function ThemeSwitch() { const [theme, setTheme] = useState<Theme>('system');
return ( <select value={theme} onChange={(event) => { const next = event.target.value as Theme; setTheme(next); applyTheme(next); }} > <option value="system">System</option> <option value="light">Light</option> <option value="dark">Dark</option> </select> );}To remember the choice, keep it in your own storage and call applyTheme at startup. The demo web app does this with themeControl from @pilotoo/ui/settings and a themePreferenceStore from @pilotoo/chat-core.
5. Theme an embedded chat
Section titled “5. Theme an embedded chat”For the embed, pass theme to mountChat. It sets data-theme on the mount element only, and the scoped stylesheet matches it there. To use your own colours in the embed, build the bundle from an app whose stylesheet contains your overrides.
How it works
Section titled “How it works”- Components read only variables such as
--primaryand--surface-card, surfaced to Tailwind through@theme. Changing a variable re-colours every component that uses it. - Light is the base. Dark follows the system until
data-themeforces one. applyTheme(preference, root = document.documentElement)accepts any element, which is how a scoped chat gets its own theme.
Next steps
Section titled “Next steps”- Theming: the full token list and the fonts.
- Add chat to a React app: the stylesheet setup.
- Packages: ui: what
@pilotoo/uiexports.