# Theming

*Customize your Ivy [application's](./10_Apps.md) visual appearance with flexible theming support including light/dark modes, custom color schemes, typography, and dynamic theme switching.*

## Overview

Ivy's theming system provides:

```mermaid
graph TD
    A["Theming"] --> B["Theme Modes"]
    A --> C["Custom Themes"]
    A --> D["Dynamic CSS"]
    
    B --> B1["Light/Dark/System"]
    C --> C1["Colors & Typography"]
    D --> D2["Runtime Updates"]
```

## Theme Modes

Control basic light/dark appearance:

```csharp
[App(icon: Icons.Palette)]
public class ThemeSwitcher : ViewBase
{
    public override object? Build()
    {
        var client = UseService<IClientProvider>();
        
        return Layout.Vertical()
            | new Button("Light")
            {
                OnClick = _ => 
                {
                    client.SetThemeMode(ThemeMode.Light);
                    return ValueTask.CompletedTask;
                }
            }
            | new Button("Dark")
            {
                OnClick = _ =>
                {
                    client.SetThemeMode(ThemeMode.Dark);
                    return ValueTask.CompletedTask;
                }
            }
            | new Button("System")
            {
                OnClick = _ =>
                {
                    client.SetThemeMode(ThemeMode.System);
                    return ValueTask.CompletedTask;
                }
            };
    }
}
```

### Options

```mermaid
graph LR
    A["ThemeMode"] --> B["Light"]
    A --> C["Dark"] 
    A --> D["System"]
    
    B --> B1["Bright backgrounds"]
    C --> C1["Dark backgrounds"]
    D --> D1["OS preference"]
```

## Custom Themes

### Server Configuration (Experimental)

The `UseTheme()` method is available for [server](./01_Program.md)-level theme configuration

```csharp
var server = new Server()
    .UseTheme(theme => {
        theme.Name = "Ocean";
        theme.Colors = new ThemeColorScheme
        {
            Light = new ThemeColors
            {
                Primary = "#0077BE",
                PrimaryForeground = "#FFFFFF",
                Secondary = "#5B9BD5",
                SecondaryForeground = "#FFFFFF",
                Background = "#F0F8FF",
                Foreground = "#1A1A1A",
                Destructive = "#DC143C",
                DestructiveForeground = "#FFFFFF",
                Success = "#20B2AA",
                SuccessForeground = "#FFFFFF",
                Warning = "#FFD700",
                WarningForeground = "#1A1A1A",
                Info = "#4682B4",
                InfoForeground = "#FFFFFF",
                Border = "#B0C4DE",
                Input = "#E6F2FF",
                Ring = "#0077BE",
                Muted = "#E0E8F0",
                MutedForeground = "#5A6A7A",
                Accent = "#87CEEB",
                AccentForeground = "#1A1A1A",
                Card = "#FFFFFF",
                CardForeground = "#1A1A1A",
                Popover = "#FFFFFF",
                PopoverForeground = "#1A1A1A"
            },
            Dark = new ThemeColors
            {
                Primary = "#4A9EFF",
                PrimaryForeground = "#001122",
                Secondary = "#2D4F70",
                SecondaryForeground = "#E8F4FD",
                Background = "#001122",
                Foreground = "#E8F4FD",
                Destructive = "#FF6B7D",
                DestructiveForeground = "#FFFFFF",
                Success = "#4ECDC4",
                SuccessForeground = "#001122",
                Warning = "#FFE066",
                WarningForeground = "#001122",
                Info = "#87CEEB",
                InfoForeground = "#001122",
                Border = "#1A3A5C",
                Input = "#0F2A4A",
                Ring = "#4A9EFF",
                Muted = "#0F2A4A",
                MutedForeground = "#8BB3D9",
                Accent = "#1A3A5C",
                AccentForeground = "#E8F4FD",
                Card = "#0F2A4A",
                CardForeground = "#E8F4FD",
                Popover = "#001122",
                PopoverForeground = "#E8F4FD"
            }
        };
    });
```

### Runtime Theme Changes

Use [UseService](../../03_Hooks/02_Core/11_UseService.md) to get `IThemeService` and modify themes dynamically. The `ApplyTheme()` method applies CSS custom properties generated from the theme:

```csharp
[App(icon: Icons.Brush)]
public class ThemeCustomizer : ViewBase
{
    public override object? Build()
    {
        var themeService = UseService<IThemeService>();
        var client = UseService<IClientProvider>();
        
        void ApplyCustomTheme()
        {
            var customTheme = new Theme
            {
                Name = "Ocean Blue",
                Colors = new ThemeColorScheme
                {
                    Light = new ThemeColors
                    {
                        Primary = "#0077be",
                        Background = "#ffffff",
                        Foreground = "#1a1a1a"
                    },
                    Dark = new ThemeColors
                    {
                        Primary = "#0099ff", 
                        Background = "#0d1117",
                        Foreground = "#ffffff"
                    }
                }
            };
            
            // Set the theme and generate CSS custom properties
            themeService.SetTheme(customTheme);
            var css = themeService.GenerateThemeCss();
            
            // Apply the generated CSS variables to the frontend
            client.ApplyTheme(css);
        }
        
        return new Button("Apply Ocean Theme")
        {
            OnClick = _ =>
            {
                ApplyCustomTheme();
                return ValueTask.CompletedTask;
            }
        };
    }
}
```

> **Note:** `ApplyTheme()` only accepts CSS generated by `ThemeService.GenerateThemeCss()`. It does not support arbitrary custom CSS injection.