Skip to content

Method Theme Classes

teociaps edited this page Nov 27, 2025 · 2 revisions

Custom Theme Classes

Create theme classes for a type-safe, object-oriented approach with full IDE support.

Overview

Theme classes are the recommended way to create custom themes. They provide the most powerful and flexible approach with compile-time safety, auto-discovery for theme switcher, and easy reusability across your application.

Tip

This is the recommended approach for production applications. Theme Classes offer all features of Embedded Files plus type-safety, flexible folder location, and automatic theme switcher discovery.

Creating a Custom Theme

public class CustomTheme : Theme
{
    protected CustomTheme(string fileName) : base(fileName)
    {
    }

    public static CustomTheme Corporate => new("corporate.css");
    public static CustomTheme Minimal => new("minimal.css");
}

File Structure

Unlike Embedded Files which require the SwaggerThemes folder, Theme Classes can be placed anywhere in your project. The only requirement is that the CSS file must be in the same folder as your theme class.

Example - Custom location:

YourProject/
├── Themes/               ← Any folder name works!
│   ├── CustomTheme.cs
│   ├── corporate.css
│   ├── corporate.min.css
│   ├── minimal.css
│   └── minimal.min.css
└── Program.cs

Tip

Key advantage over Embedded Files: You don't need to specify the assembly when using Theme Classes - the library automatically resolves it from the class. You also have complete freedom over folder naming and location.

Build Configuration

Ensure CSS files are embedded in your .csproj. The path depends on where you placed your theme class and styles:

<ItemGroup>
  <!-- If using custom folder (e.g., Themes/Styles/) -->
  <EmbeddedResource Include="Themes\Styles\your-theme.css" />

  <!-- If using SwaggerThemes folder -->
  <EmbeddedResource Include="SwaggerThemes\your-theme.css" />
</ItemGroup>

Tip

See Custom Themes - Organizing Your Themes for nested folder structure patterns and standalone variant setup.

Usage

// Simple usage
app.UseSwaggerUI(CustomTheme.Corporate, options => { });

// With advanced options
app.UseSwaggerUI(CustomTheme.Minimal, options =>
{
    options.EnableAllAdvancedOptions();
});

Benefits

No assembly required - Unlike Embedded Files, no need to pass Assembly.GetExecutingAssembly()
Flexible location - Place themes anywhere, not limited to SwaggerThemes folder
Type-safe - Compile-time checking prevents typos
Reusable - Define once, use anywhere in your application
All features available - Advanced options, CSS variables, theme switcher
Organized - Clean, structured project layout
Refactoring-friendly - Rename safely with IDE tools

Minification

You can use minified CSS files for better performance. The library does not automatically minify your CSS - you need to create minified versions yourself.

Creating minified files:

Use tools like:

Controlling Minification

Theme Classes provide a useMinified parameter to easily switch between regular and minified CSS files.

Use the useMinified parameter to control which CSS file is loaded:

public class CustomTheme : Theme
{
    // Always use minified for a better performance
    public CustomTheme() : base("my-theme.css", useMinified: true)
    {
    }

    // No minification
    public static CustomTheme Dev => new CustomTheme("my-theme.css", useMinified: false);
}

How Minification Works

// These load my-theme.min.css:
new CustomTheme("my-theme.css", useMinified: true)
new CustomTheme("my-theme.min.css", useMinified: true)

// These load my-theme.css:
new CustomTheme("my-theme.css", useMinified: false)
new CustomTheme("my-theme.min.css", useMinified: false)

Note

The constructor automatically handles .min.css - just pass your base filename!

Environment-Based Minification

public class SmartTheme : Theme
{
    public SmartTheme() : base("my-theme.css", useMinified: !Debugger.IsAttached)
    {
        // Uses .css when debugging, .min.css in production
    }
}

Configuration-Based Minification

public class ProductionTheme : Theme
{
    public ProductionTheme(IConfiguration config)
        : base("my-theme.css", useMinified: config.GetValue<bool>("UseMinifiedAssets"))
    {
    }
}

Important

Remember to generate and embed both .css and .min.css files when using minification. Only one version will be loaded based on the useMinified flag.

Example Theme Definitions

Simple Theme Collection

public class CompanyThemes : Theme
{
    protected CompanyThemes(string fileName) : base(fileName)
    {
    }

    public static CompanyThemes Light => new("light.css");
    public static CompanyThemes Dark => new("dark.css");
    public static CompanyThemes HighContrast => new("high-contrast.css");
}

Advanced Theme with Variants

public class BrandTheme : Theme
{
    private BrandTheme(string fileName, bool useMinified = true)
        : base(fileName, useMinified)
    {
    }

    // Production variants (minified)
    public static BrandTheme Primary => new("brand-primary.css");
    public static BrandTheme Secondary => new("brand-secondary.css");

    // Development variants (non-minified)
    public static BrandTheme PrimaryDev => new("brand-primary.css", useMinified: false);
    public static BrandTheme SecondaryDev => new("brand-secondary.css", useMinified: false);
}

Multi-Environment Theme

public class EnvironmentTheme : Theme
{
    private EnvironmentTheme(string fileName, bool useMinified)
        : base(fileName, useMinified)
    {
    }

    public static EnvironmentTheme ForEnvironment(string environment)
    {
        var isDev = environment.Equals("Development", StringComparison.OrdinalIgnoreCase);
        return new EnvironmentTheme($"{environment.ToLower()}.css", useMinified: !isDev);
    }
}

// Usage:
app.UseSwaggerUI(EnvironmentTheme.ForEnvironment(env.EnvironmentName), options => { });

Theme Classes and Dynamic Switcher

Theme classes are automatically discovered by the Dynamic Theme Switcher:

How It Works:

public class CompanyThemes : Theme
{
    protected CompanyThemes(string fileName) : base(fileName) { }

    public static CompanyThemes Corporate => new("corporate.css"); // ✅ Discovered
    public static CompanyThemes Tech => new("tech.css");           // ✅ Discovered
    public static CompanyThemes Minimal => new("minimal.css");     // ✅ Discovered
}

// All static properties are auto-discovered
app.UseSwaggerUI(CompanyThemes.Corporate, options =>
{
    options.EnableThemeSwitcher(); // Shows Corporate, Tech, Minimal
});

Display Names: Property names are used as display names:

  • Corporate → "Corporate"
  • Tech → "Tech"
  • DarkMode → "Dark Mode"

Custom Configuration:

app.UseSwaggerUI(CompanyThemes.Corporate, options =>
{
    options.EnableThemeSwitcher(new ThemeSwitcherOptions()
        .WithThemes(
            CompanyThemes.Corporate,
            CompanyThemes.Tech
        )
        .ExcludeThemes(CompanyThemes.Minimal));
});

Learn more about theme switcher configuration.

Best Practices

1. Use Static Properties

// Good
public static CustomTheme Corporate => new("corporate.css");

// Avoid
var theme = new CustomTheme("corporate.css");

2. Organize by Purpose

public class AppThemes : Theme
{
    protected AppThemes(string fileName) : base(fileName) { }

    // Customer-facing themes
    public static AppThemes Customer => new("customer.css");

    // Admin panel themes
    public static AppThemes Admin => new("admin.css");

    // Developer documentation themes
    public static AppThemes Docs => new("docs.css");
}

3. Version Your Themes

public class BrandTheme : Theme
{
    protected BrandTheme(string fileName) : base(fileName) { }

    public static BrandTheme V1 => new("brand-v1.css");
    public static BrandTheme V2 => new("brand-v2.css");
    public static BrandTheme Latest => V2;
}

4. Document Your Themes

/// <summary>
/// Official company branding themes for Swagger UI.
/// These themes must match the design system defined in our brand guidelines.
/// </summary>
public class OfficialThemes : Theme
{
    protected OfficialThemes(string fileName) : base(fileName) { }

    /// <summary>
    /// Primary brand theme - use for customer-facing APIs
    /// </summary>
    public static OfficialThemes Primary => new("primary.css");

    /// <summary>
    /// Internal theme - use for internal/admin APIs
    /// </summary>
    public static OfficialThemes Internal => new("internal.css");
}

Next Steps


Back to Custom Themes Overview

Clone this wiki locally