Documentation
Theming
Customize Angular AI Kit components with CSS variables and Tailwind classes.
Overview
How theming works in Angular AI Kit
Angular AI Kit uses CSS custom properties (variables) for theming. This approach provides:
- Automatic light/dark mode switching
- Easy customization without rebuilding
- Consistent styling across all components
- Full Tailwind CSS v4 compatibility
CSS Variables Reference
All available CSS custom properties
Core Colors
| Variable | Description | Light | Dark |
|---|---|---|---|
--background | Page/app background color | white | zinc-950 |
--foreground | Primary text color | zinc-950 | zinc-50 |
--card | Card backgrounds | zinc-50 | zinc-900 |
--card-foreground | Text on cards | zinc-950 | zinc-50 |
--muted | Muted/subtle backgrounds | zinc-100 | zinc-900 |
--muted-foreground | Muted text color | zinc-500 | zinc-400 |
--accent | Accent/hover backgrounds | zinc-100 | zinc-800 |
--accent-foreground | Text on accent backgrounds | zinc-900 | zinc-50 |
Border & Input
| Variable | Description | Light | Dark |
|---|---|---|---|
--border | Default border color | zinc-200 | zinc-800 |
--border-hover | Border on hover/focus | zinc-300 | zinc-600 |
--input | Input field backgrounds | zinc-50 | zinc-900 |
--ring | Focus ring color | zinc-400 | zinc-500 |
Actions & Buttons
| Variable | Description | Light | Dark |
|---|---|---|---|
--primary | Primary actions/buttons | zinc-900 | zinc-50 |
--primary-foreground | Text on primary | zinc-50 | zinc-900 |
--secondary | Secondary actions | zinc-100 | zinc-800 |
--secondary-foreground | Text on secondary | zinc-900 | zinc-50 |
--destructive | Destructive/danger actions | red-500 | red-500 |
--destructive-foreground | Text on destructive | zinc-50 | zinc-50 |
Message Components
| Variable | Description | Light | Dark |
|---|---|---|---|
--message-user-bg | User message background | zinc-100 | zinc-800 |
--message-assistant-bg | Assistant message background | white | zinc-900 |
--avatar-user | User avatar color | zinc-700 | zinc-600 |
--avatar-assistant | Assistant avatar color | zinc-800 | zinc-700 |
Basic Setup
Add CSS variables to your styles.css
Light Theme (Default)
1:root {2 /* Core Colors */3 --background: theme('colors.white');4 --foreground: theme('colors.zinc.950');5 6 /* Card */7 --card: theme('colors.zinc.50');8 --card-foreground: theme('colors.zinc.950');9 10 /* Muted */11 --muted: theme('colors.zinc.100');12 --muted-foreground: theme('colors.zinc.500');13 14 /* Border */15 --border: theme('colors.zinc.200');16 --ring: theme('colors.zinc.400');17 18 /* Primary */19 --primary: theme('colors.zinc.900');20 --primary-foreground: theme('colors.zinc.50');21}Dark Theme
1.dark {2 /* Core Colors */3 --background: theme('colors.zinc.950');4 --foreground: theme('colors.zinc.50');5 6 /* Card */7 --card: theme('colors.zinc.900');8 --card-foreground: theme('colors.zinc.50');9 10 /* Muted */11 --muted: theme('colors.zinc.900');12 --muted-foreground: theme('colors.zinc.400');13 14 /* Border */15 --border: theme('colors.zinc.800');16 --ring: theme('colors.zinc.500');17 18 /* Primary (inverted for dark) */19 --primary: theme('colors.zinc.50');20 --primary-foreground: theme('colors.zinc.900');21}Using Tailwind Classes
How to use semantic color classes
Use Tailwind's semantic color classes which automatically reference CSS variables:
1<!-- Use semantic classes (recommended) -->2<div class="bg-background text-foreground">3 <div class="border border-border rounded-lg bg-card p-4">4 <h2 class="text-foreground font-semibold">Title</h2>5 <p class="text-muted-foreground">Description</p>6 <button class="bg-primary text-primary-foreground px-4 py-2 rounded">7 Click me8 </button>9 </div>10</div>11 12<!-- These classes auto-switch between light/dark themes! -->Key Classes
bg-background - Page background bg-card - Card backgroundsbg-muted - Muted backgroundsbg-primary - Primary buttonstext-foreground - Main texttext-muted-foreground - Subtle text border-border - Bordersring-ring - Focus ringsDark Mode Implementation
How to implement theme switching
Dark mode is activated by adding the .dark class to the <html> element.
Theme Toggle Component
1import { Component, signal, inject, PLATFORM_ID } from '@angular/core';2import { isPlatformBrowser, DOCUMENT } from '@angular/common';3 4@Component({5 selector: 'app-theme-toggle',6 template: `7 <button8 (click)="toggleTheme()"9 class="rounded-lg border border-border p-2 hover:bg-muted"10 [attr.aria-label]="isDark() ? 'Switch to light mode' : 'Switch to dark mode'"11 >12 @if (isDark()) {13 <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">14 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"15 d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />16 </svg>17 } @else {18 <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">19 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"20 d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />21 </svg>22 }23 </button>24 `,25})26export class ThemeToggleComponent {27 private document = inject(DOCUMENT);28 private platformId = inject(PLATFORM_ID);29 30 isDark = signal(false);31 32 constructor() {33 if (isPlatformBrowser(this.platformId)) {34 // Check system preference35 const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;36 // Check saved preference37 const savedTheme = localStorage.getItem('theme');38 const isDark = savedTheme === 'dark' || (!savedTheme && prefersDark);39 40 this.isDark.set(isDark);41 this.updateTheme(isDark);42 }43 }44 45 toggleTheme() {46 const newValue = !this.isDark();47 this.isDark.set(newValue);48 this.updateTheme(newValue);49 localStorage.setItem('theme', newValue ? 'dark' : 'light');50 }51 52 private updateTheme(isDark: boolean) {53 if (isDark) {54 this.document.documentElement.classList.add('dark');55 } else {56 this.document.documentElement.classList.remove('dark');57 }58 }59}Key Points
- Check
prefers-color-schemefor system preference - Store user preference in
localStorage - Toggle
.darkclass on<html> - All components automatically adapt!
Custom Color Schemes
Create your own color theme
Override the default zinc color scheme with your own colors:
1:root {2 /* Custom Blue Theme */3 --primary: theme('colors.blue.600');4 --primary-foreground: theme('colors.white');5 6 /* Custom accent */7 --accent: theme('colors.blue.100');8 --accent-foreground: theme('colors.blue.900');9 10 /* Keep neutral tones for backgrounds */11 --background: theme('colors.slate.50');12 --foreground: theme('colors.slate.900');13 --card: theme('colors.white');14 --muted: theme('colors.slate.100');15}16 17.dark {18 --primary: theme('colors.blue.400');19 --primary-foreground: theme('colors.blue.950');20 21 --accent: theme('colors.blue.950');22 --accent-foreground: theme('colors.blue.100');23 24 --background: theme('colors.slate.950');25 --foreground: theme('colors.slate.50');26 --card: theme('colors.slate.900');27 --muted: theme('colors.slate.800');28}Tips
- Use
theme('colors.xxx')to reference Tailwind colors - Keep neutral backgrounds for readability
- Ensure sufficient contrast for accessibility
- Test both light and dark modes
Component Customization
Override styles on individual components
Most components accept a customClasses input for additional styling:
1import { Component } from '@angular/core';2import { ChatInputComponent } from '@angular-ai-kit/core';3 4@Component({5 selector: 'app-custom-chat',6 imports: [ChatInputComponent],7 template: `8 <ai-chat-input9 placeholder="Send a message..."10 customClasses="rounded-full border-2 border-blue-500"11 />12 `,13})14export class CustomChatComponent {}