Theming
Customize the widget appearance to match your brand. The widget uses CSS custom properties organized into categories.
Predefined themes
<!-- Light theme -->
<script data-theme="light" ...></script>
<!-- Dark theme -->
<script data-theme="dark" ...></script>
<!-- Automatic (detects system preference) -->
<script data-theme="auto" ...></script>
<!-- Auto-detect host site styles -->
<script data-theme="detect" ...></script>
All CSS Variables
The widget exposes 50+ CSS variables you can customize:
Surface Colors
.neuroon-widget {
--nrn-surface-base: 15 23 42; /* Main background */
--nrn-surface-elevated: 30 41 59; /* Cards, panels */
--nrn-surface-overlay: 51 65 85; /* Dropdowns, modals */
--nrn-surface-hover: 71 85 105; /* Hover states */
}
| Variable | Dark Mode | Light Mode | Usage |
|---|---|---|---|
--nrn-surface-base | 15 23 42 (#0f172a) | 255 255 255 (#ffffff) | Main background |
--nrn-surface-elevated | 30 41 59 (#1e293b) | 248 250 252 (#f8fafc) | Cards, panels |
--nrn-surface-overlay | 51 65 85 (#334155) | 241 245 249 (#f1f5f9) | Dropdowns |
--nrn-surface-hover | 71 85 105 (#475569) | 226 232 240 (#e2e8f0) | Hover states |
Text Colors
.neuroon-widget {
--nrn-text-primary: 248 250 252; /* Primary text */
--nrn-text-secondary: 226 232 240; /* Secondary text */
--nrn-text-muted: 148 163 184; /* Placeholder text */
--nrn-text-disabled: 100 116 139; /* Inactive text */
}
| Variable | Dark Mode | Light Mode | Usage |
|---|---|---|---|
--nrn-text-primary | 248 250 252 (#f8fafc) | 15 23 42 (#0f172a) | Titles, primary text |
--nrn-text-secondary | 226 232 240 (#e2e8f0) | 51 65 85 (#334155) | Descriptions |
--nrn-text-muted | 148 163 184 (#94a3b8) | 100 116 139 (#64748b) | Placeholders |
--nrn-text-disabled | 100 116 139 (#64748b) | 148 163 184 (#94a3b8) | Disabled |
Border Colors
.neuroon-widget {
--nrn-border-default: 51 65 85; /* Normal borders */
--nrn-border-emphasis: 71 85 105; /* Emphasized borders */
--nrn-border-subtle: 30 41 59; /* Subtle borders */
}
| Variable | Dark Mode | Light Mode | Usage |
|---|---|---|---|
--nrn-border-default | 51 65 85 (#334155) | 226 232 240 (#e2e8f0) | Normal borders |
--nrn-border-emphasis | 71 85 105 (#475569) | 203 213 225 (#cbd5e1) | Active borders |
--nrn-border-subtle | 30 41 59 (#1e293b) | 241 245 249 (#f1f5f9) | Separators |
Semantic Colors
.neuroon-widget {
--nrn-success: 16 185 129; /* Green (emerald-500) */
--nrn-error: 239 68 68; /* Red (red-500) */
--nrn-warning: 251 191 36; /* Amber (amber-400) */
}
| Variable | Value | Usage |
|---|---|---|
--nrn-success | 16 185 129 (#10b981) | In stock, success |
--nrn-error | 239 68 68 (#ef4444) | Out of stock, errors |
--nrn-warning | 251 191 36 (#fbbf24) | Warnings |
Brand Colors (Primary)
.neuroon-widget {
--nrn-primary: 6 182 212; /* Main cyan (cyan-500) */
--nrn-primary-light: 34 211 238; /* Light cyan (cyan-400) */
--nrn-primary-dark: 8 145 178; /* Dark cyan (cyan-600) */
}
| Variable | Value | Usage |
|---|---|---|
--nrn-primary | 6 182 212 (#06b6d4) | Buttons, links, accents |
--nrn-primary-light | 34 211 238 (#22d3ee) | Hover states |
--nrn-primary-dark | 8 145 178 (#0891b2) | Active states |
Secondary Colors
.neuroon-widget {
--nrn-secondary: 59 130 246; /* Blue (blue-500) */
--nrn-secondary-light: 96 165 250; /* Light blue (blue-400) */
--nrn-secondary-dark: 30 64 175; /* Dark blue (blue-700) */
}
Accent Colors
.neuroon-widget {
--nrn-accent-purple: 168 85 247; /* Purple (AI) */
--nrn-accent-emerald: 16 185 129; /* Green (success) */
--nrn-accent-amber: 245 158 11; /* Amber (featured) */
}
| Variable | Value | Usage |
|---|---|---|
--nrn-accent-purple | 168 85 247 (#a855f7) | AI indicators, confidence |
--nrn-accent-emerald | 16 185 129 (#10b981) | Categories, success |
--nrn-accent-amber | 245 158 11 (#f59e0b) | Tags, featured |
Typography
.neuroon-widget {
--nrn-font-family: system-ui, -apple-system, sans-serif;
--nrn-font-size-xs: 0.75rem; /* 12px */
--nrn-font-size-sm: 0.875rem; /* 14px */
--nrn-font-size-base: 1rem; /* 16px */
--nrn-font-size-lg: 1.125rem; /* 18px */
--nrn-font-size-xl: 1.25rem; /* 20px */
--nrn-font-size-2xl: 1.5rem; /* 24px */
}
| Variable | Value | Usage |
|---|---|---|
--nrn-font-family | system-ui, ... | Global font |
--nrn-font-size-xs | 0.75rem (12px) | Small labels |
--nrn-font-size-sm | 0.875rem (14px) | Secondary text |
--nrn-font-size-base | 1rem (16px) | Normal text |
--nrn-font-size-lg | 1.125rem (18px) | Subtitles |
--nrn-font-size-xl | 1.25rem (20px) | Small titles |
--nrn-font-size-2xl | 1.5rem (24px) | Titles |
Spacing
.neuroon-widget {
--nrn-spacing-xs: 0.25rem; /* 4px */
--nrn-spacing-sm: 0.5rem; /* 8px */
--nrn-spacing-md: 1rem; /* 16px */
--nrn-spacing-lg: 1.5rem; /* 24px */
--nrn-spacing-xl: 2rem; /* 32px */
}
Border Radius
.neuroon-widget {
--nrn-radius-sm: 0.375rem; /* 6px */
--nrn-radius-md: 0.5rem; /* 8px */
--nrn-radius-lg: 0.75rem; /* 12px */
--nrn-radius-xl: 1rem; /* 16px */
--nrn-radius-2xl: 1.5rem; /* 24px */
--nrn-radius-full: 9999px; /* Circular */
}
Shadows
.neuroon-widget {
--nrn-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--nrn-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--nrn-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
--nrn-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
}
| Variable | Usage |
|---|---|
--nrn-shadow-sm | Buttons, inputs |
--nrn-shadow-md | Cards |
--nrn-shadow-lg | Dropdowns |
--nrn-shadow-xl | Modals |
Transitions
.neuroon-widget {
--nrn-transition-fast: 150ms ease-in-out;
--nrn-transition-base: 200ms ease-in-out;
--nrn-transition-slow: 300ms ease-in-out;
}
Z-Index
.neuroon-widget {
--nrn-z-dropdown: 10;
--nrn-z-sticky: 20;
--nrn-z-modal-backdrop: 40;
--nrn-z-modal: 50;
--nrn-z-tooltip: 70;
}
Brand Colors
.neuroon-widget {
--nrn-brand-cyan: #06b6d4;
--nrn-brand-cyan-light: #22d3ee;
--nrn-brand-cyan-dark: #0891b2;
--nrn-brand-blue: #3b82f6;
--nrn-brand-gradient: linear-gradient(135deg, #06b6d4, #3b82f6);
--nrn-brand-gradient-hover: linear-gradient(135deg, #22d3ee, #60a5fa);
}
| Variable | Value | Usage |
|---|---|---|
--nrn-brand-cyan | #06b6d4 | Primary brand color |
--nrn-brand-cyan-light | #22d3ee | Hover states |
--nrn-brand-cyan-dark | #0891b2 | Active states |
--nrn-brand-blue | #3b82f6 | Secondary brand color |
--nrn-brand-gradient | linear-gradient(...) | Primary button gradient |
--nrn-brand-gradient-hover | linear-gradient(...) | Hover gradient |
Glow Effects
.neuroon-widget {
--nrn-glow-cyan: 0 0 20px rgba(6, 182, 212, 0.4);
--nrn-glow-cyan-intense: 0 0 35px rgba(6, 182, 212, 0.6);
--nrn-glow-blue: 0 0 20px rgba(59, 130, 246, 0.4);
--nrn-glow-cyan-shadow: 0 4px 15px rgba(6, 182, 212, 0.3);
}
| Variable | Usage |
|---|---|
--nrn-glow-cyan | Subtle glow for active elements |
--nrn-glow-cyan-intense | Intense glow for focus states |
--nrn-glow-blue | Blue glow for secondary elements |
--nrn-glow-cyan-shadow | Elevated shadow with glow |
JavaScript Configuration
Use the styles object to customize without writing CSS:
NeuroonWidget.init({
// ...
styles: {
// Surfaces (hex or RGB string)
surfaceBase: '#0f172a',
surfaceElevated: '#1e293b',
surfaceOverlay: '#334155',
surfaceHover: '#475569',
// Text
textPrimary: '#f8fafc',
textSecondary: '#cbd5e1',
textMuted: '#94a3b8',
textDisabled: '#64748b',
// Borders
borderDefault: '#334155',
borderEmphasis: '#475569',
borderSubtle: '#1e293b',
// Semantic
success: '#10b981',
error: '#ef4444',
warning: '#f59e0b',
// Brand
primary: '#06b6d4',
primaryLight: '#22d3ee',
primaryDark: '#0ea5e9',
// Secondary
secondary: '#3b82f6',
secondaryLight: '#60a5fa',
secondaryDark: '#2563eb',
// Accents
accentPurple: '#a855f7',
accentEmerald: '#10b981',
accentAmber: '#f59e0b',
// Typography
fontFamily: 'Inter, system-ui, sans-serif',
// Border Radius
radiusSm: '0.375rem',
radiusMd: '0.5rem',
radiusLg: '0.75rem',
radiusXl: '1rem',
radius2xl: '1.5rem',
radiusFull: '9999px',
// Font Sizes
fontSizeXs: '0.75rem',
fontSizeSm: '0.875rem',
fontSizeBase: '1rem',
fontSizeLg: '1.125rem',
fontSizeXl: '1.25rem',
fontSize2xl: '1.5rem',
// Spacing
spacingXs: '0.25rem',
spacingSm: '0.5rem',
spacingMd: '1rem',
spacingLg: '1.5rem',
spacingXl: '2rem',
// Shadows
shadowSm: '0 1px 2px 0 rgb(0 0 0 / 0.05)',
shadowMd: '0 4px 6px -1px rgb(0 0 0 / 0.1)',
shadowLg: '0 10px 15px -3px rgb(0 0 0 / 0.1)',
shadowXl: '0 20px 25px -5px rgb(0 0 0 / 0.1)',
// Transitions
transitionFast: '150ms ease-in-out',
transitionBase: '200ms ease-in-out',
transitionSlow: '300ms ease-in-out',
// Z-Index
zDropdown: '10',
zSticky: '20',
zModalBackdrop: '40',
zModal: '50',
zTooltip: '70',
},
});
Custom Theme Examples
Cyan Theme (Default Neuroon)
styles: {
primary: '#06b6d4',
primaryLight: '#22d3ee',
primaryDark: '#0ea5e9',
}
Purple Theme
styles: {
primary: '#8b5cf6',
primaryLight: '#a78bfa',
primaryDark: '#7c3aed',
}
Green Theme
styles: {
primary: '#10b981',
primaryLight: '#34d399',
primaryDark: '#059669',
}
Pink Theme
styles: {
primary: '#ec4899',
primaryLight: '#f472b6',
primaryDark: '#db2777',
}
External CSS Theme
You can override variables directly in your CSS:
/* Your styles.css file */
.neuroon-widget {
/* Your brand */
--nrn-primary: 236 72 153; /* Pink #ec4899 */
--nrn-primary-light: 244 114 182;
--nrn-primary-dark: 219 39 119;
/* Custom font */
--nrn-font-family: 'Poppins', sans-serif;
/* More rounded borders */
--nrn-radius-lg: 1rem;
--nrn-radius-xl: 1.5rem;
}
CSS variables use RGB format without commas: 6 182 212 (not #06b6d4 or rgb(6, 182, 212)).
This allows using rgb(var(--nrn-primary) / 0.5) for transparency.
Auto-Detect Theme
The detect mode automatically analyzes your page's styles:
<script data-theme="detect" ...></script>
Detects:
<body>background color- Main text color
- Accent color (if
--accent-colorexists) - Site font
- Whether site uses dark mode
// JavaScript equivalent
theme: 'detect',
Use detect when integrating the widget into third-party sites where you don't control the styles. The widget will adapt automatically.
Dynamic Theme
You can change the theme dynamically:
const widget = NeuroonWidget.init({ ... });
// Switch to dark theme
widget.setTheme('dark');
// Switch to light theme
widget.setTheme('light');
// Return to auto-detection
widget.setTheme('auto');
Shadow DOM
The widget uses Shadow DOM for style encapsulation. This means:
- Widget styles do not affect your page
- Your page styles do not affect the widget (except variables you override)
- No CSS conflicts
To override styles, use CSS variables or the styles object.
Color Accessibility
Ensure adequate contrast is maintained:
| Usage | Minimum contrast |
|---|---|
| Normal text | 4.5:1 |
| Large text (>18px) | 3:1 |
| Icons, borders | 3:1 |
Use WebAIM Contrast Checker to verify your custom colors.