Skip to main content

Theming

Customize the visual appearance of your vertical application.

CSS Variables

The template uses CSS custom properties for theming, allowing runtime theme switching.

Base Theme

/* src/app/globals.css */
:root {
/* Colors */
--background: 0 0% 100%;
--foreground: 222.2 47.4% 11.2%;

--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;

--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;

--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;

--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;

/* Borders */
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 47.4% 11.2%;

/* Layout */
--radius: 0.5rem;
}

Dark Theme

[data-theme="dark"] {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;

--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;

/* ... other dark mode values */
}

Tenant Branding

Each tenant can have custom colors and assets.

Per-Tenant CSS

Create tenant-specific styles:

/* src/app/tenants/my-tenant.css */
[data-tenant="my-tenant"] {
--primary: 250 100% 50%;
--primary-foreground: 0 0% 100%;
}

Import in your layout:

// src/app/layout.tsx
import './tenants/my-tenant.css';

Tenant Config Theming

Add theme to your tenant config:

export const myTenantConfig: EAIConfig = {
tenantId: 'my-tenant',
displayName: 'My Application',

theme: {
primaryColor: '#6366f1',
secondaryColor: '#f1f5f9',
logo: '/logos/my-tenant-logo.svg',
favicon: '/favicons/my-tenant.ico',
},

// ... rest of config
};

Logo and Assets

Logo Placement

{
component: 'Header',
props: {
logo: '/logos/my-logo.svg',
logoAlt: 'My Company',
logoWidth: 150,
},
}

Favicon

Set per-tenant favicons:

// src/app/layout.tsx
export const metadata = {
icons: {
icon: getTenantFavicon(tenantId),
},
};

Theme Switching

Store-Based Theme

Use the store to manage theme preference:

// Tenant config
store: {
ui: {
initialState: {
theme: 'light', // or 'dark', 'system'
},
persist: true,
},
}

Theme Toggle Component

'use client';

import { useStoreValue, useSetStore } from '@enterpriseaigroup/client';

export function ThemeToggle() {
const theme = useStoreValue('ui.theme');
const setStore = useSetStore();

const toggleTheme = () => {
const newTheme = theme === 'light' ? 'dark' : 'light';
setStore('ui.theme', newTheme, 'ThemeToggle');
document.documentElement.setAttribute('data-theme', newTheme);
};

return (
<button onClick={toggleTheme}>
{theme === 'light' ? '🌙' : '☀️'}
</button>
);
}

Tailwind Configuration

Extend Tailwind with your brand colors:

// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
brand: {
50: '#f0f9ff',
100: '#e0f2fe',
// ... full palette
900: '#0c4a6e',
},
},
},
},
};

Use in components:

<button className="bg-brand-500 hover:bg-brand-600">
Click me
</button>

Component Variants

Use variants for consistent styling:

// src/components/ui/button.tsx
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground',
destructive: 'bg-destructive text-destructive-foreground',
outline: 'border border-input bg-background',
secondary: 'bg-secondary text-secondary-foreground',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: 'h-10 px-4 py-2',
sm: 'h-9 px-3',
lg: 'h-11 px-8',
icon: 'h-10 w-10',
},
},
}
);

Best Practices

  1. Use CSS variables for colors that need to change
  2. Use Tailwind classes for layout and spacing
  3. Keep themes simple - fewer variables are easier to maintain
  4. Test both themes - ensure readability in light and dark
  5. Respect system preference - support prefers-color-scheme