Theming & Styling
The Incode Web SDK uses CSS custom properties (variables) for theming, making it easy to match your brand.
This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation here. We strongly recommend upgrading - contact your Incode Representative for upgrade information.
The Incode Web SDK uses CSS custom properties (variables) for theming, making it easy to match your brand.
Quick Start
Import the base tokens and override the variables you want to customize:
/* Import the SDK theme (defines all CSS variables you can override) */
@import '@incodetech/web/themes/light.css';
/* Override with your brand color — easiest path */
:root {
--primitive-color-brand-500: #0066cc;
--primitive-color-brand-400: #1f7fdf; /* slightly lighter, used on hover */
--primitive-color-brand-600: #0052a3; /* slightly darker, used on press */
}Note: The SDK ships two themes —
@incodetech/web/themes/light.cssand@incodetech/web/themes/dark.css. Pick one as your base, then override variables to match your brand. Component layout/structure CSS lives separately in@incodetech/web/base.cssand per-module CSS such as@incodetech/web/flow/styles.css. The full token catalog is documented below.
Token Hierarchy
The SDK uses a layered token system:
Primitives → Semantic → Component-specific
Each layer references the layer above. Most overrides target the primitive or component layer; touching the semantic layer cascades broadly so use it intentionally.
1. Primitive Tokens
Concrete values that nothing else customizes:
:root {
/* Color scales (50, 100, 200, ..., 900, 1000) for: gray, brand, brand-secondary, positive, warning, negative */
--primitive-color-gray-0: #ffffff;
--primitive-color-gray-500: #6b7280;
--primitive-color-gray-900: #1f2937;
--primitive-color-brand-500: #0066cc;
/* Spacing scale (--primitive-scale-*) and the friendly --spacing-* aliases */
--primitive-scale-4: 4px;
--spacing-4: var(--primitive-scale-4);
--spacing-16: var(--primitive-scale-16);
/* Typography */
--primitive-typography-family-rethink-sans: 'Rethink Sans';
--primitive-typography-size-16: 16px;
--primitive-typography-weight-regular: 400;
--primitive-typography-weight-medium: 500;
/* Border radius scale (--primitive-border-radius-0/4/8/16/24/40/64/9999) and aliases */
--border-radius-medium: var(--primitive-border-radius-16);
--border-radius-full: var(--primitive-border-radius-9999);
}2. Semantic Tokens
Purpose-based names that reference primitives. Different values resolve in @incodetech/web/themes/light.css vs. dark.css, so overriding a semantic token affects whichever theme you're on:
:root {
/* Surfaces — backgrounds */
--surface-neutral-0: var(--primitive-color-gray-0); /* base background */
--surface-neutral-50: var(--primitive-color-gray-50); /* subtle elevated surface */
--surface-neutral-900: var(--primitive-color-gray-900); /* highest contrast */
--surface-brand-500: var(--primitive-color-brand-500); /* brand fill */
--surface-status-negative-500: var(--primitive-color-negative-500);
--surface-status-warning-500: var(--primitive-color-warning-500);
--surface-status-positive-500: var(--primitive-color-positive-500);
/* Text — foreground colors */
--text-body-800-primary: var(--primitive-color-gray-800); /* primary body text */
--text-body-500-secondary: var(--primitive-color-gray-500); /* secondary / muted */
--text-body-400: var(--primitive-color-gray-400); /* placeholders, disabled */
--text-link-default: var(--primitive-color-brand-500);
--text-link-hover: var(--primitive-color-brand-300);
--text-accent-brand: var(--primitive-color-brand-500);
/* Borders */
--border-neutral-100: var(--primitive-color-gray-100);
--border-neutral-400: var(--primitive-color-gray-400);
--border-status-negative: var(--primitive-color-negative-500);
--border-status-focus: var(--primitive-color-brand-500);
}Many tokens have a -static variant that stays fixed across light/dark themes (used for elements that should look identical regardless of theme, like a brand-coloured button). For example --surface-brand-500-static does not switch in dark mode the way --surface-brand-500 might.
3. Component Tokens
Specific to individual components. These reference semantic tokens, so overriding a component token gives you targeted control without affecting other components:
:root {
/* Primary button */
--button-primary-surface-default: var(--surface-brand-500-static);
--button-primary-surface-hover: var(--surface-brand-400-static); /* lighter on hover */
--button-primary-surface-pressed: var(--surface-brand-600-static); /* darker on press */
--button-primary-surface-disabled: var(--surface-neutral-100);
--button-primary-text-default: var(--text-body-0-static);
--button-primary-border-radius: var(--border-radius-medium);
/* Inputs */
--input-surface-default: var(--surface-neutral-50);
--input-surface-disabled: var(--surface-neutral-100);
--input-border-default: var(--border-neutral-400);
--input-border-focused: var(--border-status-focus);
--input-border-negative: var(--border-status-negative);
--input-text-field-default: var(--text-body-800-primary);
--input-text-field-placeholder: var(--text-body-400);
/* Spinner */
--spinner-surface-primary: var(--surface-brand-500-static);
--spinner-surface-secondary: var(--surface-brand-50);
--spinner-text-title: var(--text-body-800-primary);
--spinner-text-subtitle: var(--text-body-500-secondary);
}button-* tokens come in primary, secondary, and tertiary variants, each with surface, text, and border properties across default / hover / pressed / disabled states.
Common Customizations
Brand colors
The simplest path is to override the primitive brand scale. Everything semantic (--surface-brand-*, --text-accent-brand, button colors, focus rings, etc.) inherits automatically:
:root {
--primitive-color-brand-50: #e6f0ff;
--primitive-color-brand-100: #cce0ff;
--primitive-color-brand-300: #4d9aff;
--primitive-color-brand-400: #1f7fdf; /* button hover */
--primitive-color-brand-500: #0066cc; /* main brand */
--primitive-color-brand-600: #0052a3; /* button pressed */
}If you need finer control, override the component tokens directly:
:root {
--button-primary-surface-default: #0066cc;
--button-primary-surface-hover: #1f7fdf;
--button-primary-surface-pressed: #0052a3;
}Dark mode
The SDK already ships a dark theme — import it instead of rolling your own:
@import '@incodetech/web/themes/dark.css';If you want to switch themes per user preference, gate the import or apply it conditionally:
/* Default to light, switch to dark when the user prefers dark */
@import '@incodetech/web/themes/light.css';
@media (prefers-color-scheme: dark) {
@import '@incodetech/web/themes/dark.css';
}Typography
The SDK uses Rethink Sans by default. Override the primitive family if you want a different font everywhere:
:root {
--primitive-typography-family-rethink-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}Sizes (--primitive-typography-size-12 through --primitive-typography-size-80) and weights (--primitive-typography-weight-regular, --primitive-typography-weight-medium, --primitive-typography-weight-semibold, --primitive-typography-weight-bold) are also override-able primitive tokens.
Border radius
The radius scale is --border-radius-{none,x-small,small,medium,large,x-large,xx-large,full}. Components reference these via component tokens:
:root {
/* Round all primary buttons more aggressively */
--button-primary-border-radius: var(--border-radius-large);
/* Or change the underlying scale */
--primitive-border-radius-16: 12px; /* shrinks --border-radius-medium */
}Container Styling
The SDK elements fill their container. Style the parent for layout control:
<!-- Full viewport height -->
<div style="height: 100vh;">
<incode-flow></incode-flow>
</div>
<!-- Fixed height modal -->
<div style="height: 600px; width: 400px;">
<incode-flow></incode-flow>
</div>Spinner Customization
The loading spinner displayed during flow initialization, module loading, and transitions exposes four tokens:
:root {
/* Spinner icon colors */
--spinner-surface-primary: #0066cc; /* foreground arc */
--spinner-surface-secondary: #e6f0ff; /* track */
/* Spinner text */
--spinner-text-title: #1a1a1a;
--spinner-text-subtitle: #666666;
}The full-screen overlay background uses --surface-neutral-0 from the active theme — override that primitive (or the corresponding --primitive-color-gray-0) if you want a different overlay color, rather than reaching for a dedicated token (there isn't one).
Spinner Sizes
The spinner component supports three sizes that you can configure via the spinnerConfig prop:
| Size | Icon Dimension |
|---|---|
small | 24px |
medium | 48px (default) |
large | 64px |
CSS Class Targeting
You can also target spinner classes directly:
/* Main spinner container */
.IncodeSpinner {
/* your styles */
}
/* Full-screen spinner overlay */
.IncodeSpinnerFullScreen {
/* your styles */
}
/* Spinner content wrapper */
.IncodeSpinnerContent {
/* your styles */
}
/* Wrapper around title + subtitle */
.IncodeSpinnerText {
/* your styles */
}
/* Title and subtitle text */
.IncodeSpinnerTitle {
/* your styles */
}
.IncodeSpinnerSubtitle {
/* your styles */
}Key CSS Variables
A high-level cheat sheet of the categories you'll most often override. The full inventory ships in @incodetech/web/themes/light.css and @incodetech/web/themes/dark.css — inspect them in your browser's devtools or your bundler's source view to see every variable.
| Category | Examples |
|---|---|
| Brand | --primitive-color-brand-{50..600} (override these to re-skin everything) |
| Surfaces | --surface-neutral-{0..1000}, --surface-brand-{50,100,500,500-static,600-static}, --surface-status-{negative,warning,positive}-{50,500} |
| Text | --text-body-{0,400,500-secondary,800-primary}, --text-link-{default,hover,visited,disabled}, --text-accent-brand, --text-status-{negative,warning,positive} |
| Borders | --border-neutral-{100,400}, --border-status-{negative,warning,positive,focus} |
| Buttons | --button-{primary,secondary,tertiary}-{surface,text,border}-{default,hover,pressed,disabled}, --button-*-border-radius |
| Inputs | --input-{surface,border,icon,text-field,text-helper,text-label}-{default,focused,disabled,negative} |
| Spinner | --spinner-surface-{primary,secondary}, --spinner-text-{title,subtitle} |
| Layout | --spacing-{2..96}, --border-radius-{none,x-small,small,medium,large,x-large,xx-large,full} |
| Type | --primitive-typography-family-*, --primitive-typography-size-{12..80}, --primitive-typography-weight-{regular,medium,semibold,bold} |
Updated 1 day ago
