Skip to main content

Theming

The Lovina Chat SDK is designed to blend into your brand. You can go from a one-line color change to a fully custom branded experience.

One-Color Theming

The fastest way to brand the widget. Set primaryColor and the SDK derives the primary color ramp and the launcher bubble automatically.

window.lovinaSettings = {
theme: {
primaryColor: '#6366F1', // Your brand color
},
};

The auto-derived brand palette includes: the primary color ramp and the launcher bubble color, generated by interpolating lightness relative to your primary color's own lightness so every stop stays visually coherent (not a WCAG contrast guarantee against fixed text/icon colors elsewhere in the widget — pick a primary with reasonable contrast in mind). Message bubbles and surface colors (background, input, text, border) are not auto-derived from primaryColor -- they follow the active colorScheme scheme unless you explicitly override them (see Full Custom Theme below).

How Auto-Generation Works

The SDK derives the brand ramp from your primaryColor:

  1. Converts primaryColor to HSL.
  2. primaryColor itself becomes the 900 ramp stop.
  3. Each remaining stop (700/500/400/100/50) interpolates lightness toward white by a fixed fraction of the room between 900's lightness and white, holding hue and saturation constant -- so every stop stays strictly between the primary and white, for any primary color, without inverting or collapsing for very light or very dark inputs.

Message bubbles and surface colors (background, input, text, border) are intentionally left out of this step -- they follow colorScheme instead, so a light-mode-tuned background (or a dark-mode-tuned message bubble) never gets stuck showing in the wrong scheme.

For example, setting primaryColor: '#FF6B00' automatically produces a coordinated orange brand ramp and a matching launcher bubble; the chat panel's background and message bubbles still follow light/dark.

Full Custom Theme

For pixel-perfect control, override individual colors:

window.lovinaSettings = {
theme: {
primaryColor: '#6366F1',
primaryTextColor: '#FFFFFF',
backgroundColor: '#FAFAFA',
agentBubbleColor: '#F3F4F6',
agentBubbleTextColor: '#1F2937',
userBubbleColor: '#6366F1',
userBubbleTextColor: '#FFFFFF',
textColor: '#1A1A1A',
secondaryTextColor: '#6B7280',
inputColor: '#FFFFFF',
borderColor: '#E5E7EB',
fontFamily: 'Inter, system-ui, sans-serif',
fontSize: 14,
borderRadius: 16,
bubbleRadius: 18,
buttonRadius: 8,
bubbleSize: 60,
bubbleColor: '#6366F1',
bubbleIconColor: '#FFFFFF',
bubbleShadow: true,
},
};

agentBubbleColor is opt-in: setting it enables agent-message bubble chrome (background, padding, rounded corners); leaving it unset renders agent messages as bare text with no bubble, as today. primaryTextColor is auto-derived for WCAG AA contrast against primaryColor when omitted, so you only need to set it to override that derived value.

agentBubbleColor and agentBubbleTextColor should always be set together: the agent-bubble text color is not auto-derived from the bubble background, so customizing agentBubbleColor alone can leave agent message text with insufficient contrast against it.

CSS Variable Overrides

The widget applies theme colors as CSS custom properties. These are the variables set internally:

:root {
/* Brand — always derived from primaryColor, identical in light & dark */
--lv-primary-900: #1B2E1F;
--lv-primary-700: #2D4A32;
--lv-primary-500: #3D6B45;
--lv-primary-400: #4A8B55;
--lv-primary-100: #E8F5E9;
--lv-primary-50: #F1F8F2;
--lv-primary-text: #FFFFFF;

/* Surface — follows light/dark; only changes if explicitly overridden */
--lv-bg-white: #FFFFFF;
--lv-bg-warm: #FAFAF7;
--lv-bg-cream: #F5F5F0;

--lv-gray-900: #1A1A1A;
--lv-gray-500: #6B7280;
--lv-gray-200: #E5E5E0;
--lv-gray-50: #F5F5F0;

/* Agent bubble chrome — override-only: unlike the surface vars above,
these have no static light/dark default and are absent entirely
unless agentBubbleColor / agentBubbleTextColor is set */
--lv-agent-bubble-bg: #F3F4F6;
--lv-agent-bubble-color: #1F2937;
--lv-agent-bubble-padding: 12px 16px;
--lv-agent-bubble-radius: 16px 16px 16px 4px;

--lv-font-family: 'Raleway', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--lv-radius-sm: 8px;
--lv-radius-md: 12px;
--lv-radius-lg: 16px;
}

Setting primaryColor overrides the primary ramp variables to match, in both light and dark mode. Surface variables (background, gray scale, message bubbles) are left to light/dark mode unless you explicitly set backgroundColor, textColor, secondaryTextColor, inputColor, borderColor, userBubbleColor, or userBubbleTextColor in theme -- see Full Custom Theme.

Dark Mode

Configuration

Enable dark mode via the colorScheme setting:

window.lovinaSettings = {
colorScheme: 'dark', // Always dark
// or
colorScheme: 'auto', // Follow OS preference via prefers-color-scheme
};

Runtime Toggle

Switch color scheme programmatically:

window.$lovina.setColorScheme('dark');
window.$lovina.setColorScheme('light');
window.$lovina.setColorScheme('auto');

Dark Mode Palette

In dark mode, the SDK applies a coordinated dark palette:

ElementLightDark
Background#FFFFFF#0F1117
Card / warm bg#FAFAF7#1A1D27
Input#F5F5F0#252836
Primary text#1A1A1A#F9FAFB
Secondary text#6B7280#9CA3AF
Border#E5E5E0#2D3142

Branding Options

Custom Logo and Name

Replace the default header branding:

window.lovinaSettings = {
branding: {
brandName: 'Acme Support',
logoUrl: 'https://example.com/logo.svg',
},
};

Custom Bubble Icon

Replace the default chat icon on the launcher bubble:

window.lovinaSettings = {
branding: {
bubbleIconUrl: 'https://example.com/your-icon.svg',
},
};

The icon should be SVG or PNG, ideally 24x24 or 32x32 px, with a transparent background.

Remove "Powered by" Branding

For a fully white-labeled experience:

window.lovinaSettings = {
branding: {
poweredBy: false,
},
};

Native SDKs

Everything above -- theme, branding, texts, and colorScheme -- applies identically on the native SDKs. The field names and values are the same; you just pass them through each platform's typed config object instead of window.lovinaSettings.

Flutter

LovinaChatConfig(
websiteToken: 'your-website-token',
baseUrl: 'https://chat.lovina.app',
colorScheme: 'auto',
theme: LovinaThemeConfig(
primaryColor: '#6366F1',
fontFamily: 'Inter, sans-serif',
borderRadius: 16,
),
branding: LovinaBrandingConfig(
brandName: 'Acme Support',
logoUrl: 'https://example.com/logo.svg',
poweredBy: false,
),
)

iOS (Swift)

LovinaChatConfig(
websiteToken: "your-website-token",
baseUrl: "https://chat.lovina.app",
colorScheme: "auto",
theme: LovinaThemeConfig(
primaryColor: "#6366F1",
fontFamily: "Inter, sans-serif",
borderRadius: 16
),
branding: LovinaBrandingConfig(
logoUrl: "https://example.com/logo.svg",
brandName: "Acme Support",
poweredBy: false
)
)

LovinaThemeConfig colors are hex strings (e.g. "#6366F1"), not UIColor.

Android (Kotlin)

LovinaChatConfig(
websiteToken = "your-website-token",
baseUrl = "https://chat.lovina.app",
colorScheme = "auto",
theme = LovinaThemeConfig(
primaryColor = "#6366F1",
fontFamily = "Inter, sans-serif",
borderRadius = 16
),
branding = LovinaBrandingConfig(
brandName = "Acme Support",
logoUrl = "https://example.com/logo.svg",
poweredBy = false
)
)

LovinaThemeConfig colors are hex strings (e.g. "#6366F1"), not ARGB Ints.

React Native

const config: LovinaChatConfig = {
websiteToken: 'your-website-token',
baseUrl: 'https://chat.lovina.app',
colorScheme: 'auto',
theme: {
primaryColor: '#6366F1',
fontFamily: 'Inter, sans-serif',
borderRadius: 16,
},
branding: {
brandName: 'Acme Support',
logoUrl: 'https://example.com/logo.svg',
poweredBy: false,
},
};

Preset Themes

The SDK ships with 8 built-in color presets as reference palettes:

PresetPrimary ColorDescription
lovina#1B2E1FDefault deep green
midnight#1E293BDark slate blue
ocean#0369A1Professional blue
coral#BE185DVibrant pink
emerald#059669Fresh green
amber#D97706Warm amber
violet#7C3AEDRich purple
slate#475569Neutral gray

To use a preset's color:

window.lovinaSettings = {
theme: {
primaryColor: '#0369A1', // Ocean preset
},
};

Complete White-Label Example

A fully branded widget with no trace of Lovina's default branding:

window.lovinaSettings = {
branding: {
brandName: 'Acme Help Desk',
logoUrl: 'https://example.com/acme-logo.svg',
bubbleIconUrl: 'https://example.com/acme-icon.svg',
faviconUrl: 'https://example.com/favicon.ico',
poweredBy: false,
},
theme: {
primaryColor: '#FF6B00',
fontFamily: 'Inter, sans-serif',
borderRadius: 12,
bubbleSize: 56,
},
texts: {
header: { title: 'Acme Help' },
welcome: {
title: 'Welcome!',
message: 'How can we assist you today?',
},
input: { placeholder: 'Type your question...' },
},
};