Skip to content

Feature Dynamic Theme Switcher

teociaps edited this page Nov 27, 2025 · 2 revisions

Dynamic Theme Switcher

Allow users to switch between themes at runtime without reloading the page. The theme switcher automatically discovers available themes and persists user preferences.

Why Use It?

  • User Preference - Let users choose their preferred theme
  • No Page Reload - Instant theme switching
  • Auto-Discovery - Automatically finds all available themes
  • Persistent - Remembers user choice
  • Accessible - Better for light/dark mode preferences

Visual Example

theme switcher gif

Configuration used in this example:

options.EnableAllAdvancedOptions(new ThemeSwitcherOptions()
    .WithThemes(Theme.Dark, Theme.Light)
    .WithCustomThemes(CustomThemeMode.None));

Quick Start

Swashbuckle

using AspNetCore.Swagger.Themes;

app.UseSwaggerUI(Theme.Dark, options =>
{
    options.EnableThemeSwitcher();
});

NSwag

using AspNetCore.Swagger.Themes;

app.UseSwaggerUi(Theme.Dark, settings =>
{
    settings.EnableThemeSwitcher();
});

How It Works

The theme switcher operates in three phases:

1. Discovery Phase

Automatically scans your assembly for available themes:

  • All predefined themes (Theme.Dark, Theme.Light, etc.)
  • Custom themes from SwaggerThemes folder (including nested folders)
  • Theme classes inheriting from BaseTheme wherever they are defined

2. Registration Phase

Creates HTTP endpoints for each discovered theme:

  • /styles/dark.css
  • /styles/light.css
  • /styles/your-custom-theme.css
  • /themes/metadata.json - List of all available themes

3. Runtime Switching

JavaScript dynamically loads the selected theme:

  • Updates CSS link in document head
  • Saves preference to localStorage
  • Applies instantly without page reload

Configuration Options

Default (All Themes)

Shows all predefined and auto-discovered custom themes:

app.UseSwaggerUI(Theme.Dark, options =>
{
    options.EnableThemeSwitcher(); // All themes available
});

Predefined Themes Only

Show only the built-in themes:

app.UseSwaggerUI(Theme.Dark, options =>
{
    options.EnableThemeSwitcher(ThemeSwitcherOptions.PredefinedOnly());
});

Custom Themes Only

Show only your custom themes:

app.UseSwaggerUI(CustomTheme.Corporate, options =>
{
    options.EnableThemeSwitcher(ThemeSwitcherOptions.CustomOnly());
});

Specific Themes Selection

Choose exactly which themes to include:

app.UseSwaggerUI(Theme.Dark, options =>
{
    options.EnableThemeSwitcher(new ThemeSwitcherOptions()
        .WithThemes(
            Theme.Dark,
            Theme.Light,
            Theme.Forest,
            CompanyThemes.Corporate
        ));
});

Complex Filtering

Combine multiple configuration options:

app.UseSwaggerUI(Theme.Dark, options =>
{
    options.EnableThemeSwitcher(new ThemeSwitcherOptions()
        .WithAllPredefinedThemes(true)
        .ExcludeThemes(Theme.Futuristic, Theme.Desert)
        .WithCustomThemes(CustomThemeMode.AutoDiscover));
});

Tip

Theme switcher options can also be passed to EnableAllAdvancedOptions() if you're enabling all features at once:

options.EnableAllAdvancedOptions(new ThemeSwitcherOptions()
    .WithThemes(Theme.Dark, Theme.Light));

Theme Auto-Discovery

How Themes Are Discovered

The switcher automatically finds themes through different methods:

1. Theme Classes (Recommended) - Full auto-discovery

Theme Classes inheriting from BaseTheme are automatically discovered:

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

    public static CompanyThemes Corporate => new("corporate.css"); // ✅ Auto-discovered
    public static CompanyThemes Tech => new("tech.css");           // ✅ Auto-discovered
}

2. Embedded Files - Manual selection only

Embedded CSS files in SwaggerThemes folder are not auto-discovered. Only the explicitly selected theme will be available alongside predefined themes:

var assembly = Assembly.GetExecutingAssembly();

// Only "corporate.css" + predefined themes available in switcher
app.UseSwaggerUI(assembly, "corporate.css", options =>
{
    options.EnableThemeSwitcher();
});

Tip

For full auto-discovery of custom themes, use Theme Classes instead of Embedded Files.

3. Naming Convention File names are converted to display names:

  • corporate-blue.css → "Corporate Blue"
  • dark-mode.css → "Dark Mode"
  • myCustomTheme.css → "My Custom Theme"

Custom Display Format

Customize how theme names are displayed:

app.UseSwaggerUI(Theme.Dark, options =>
{
    options.EnableThemeSwitcher(new ThemeSwitcherOptions()
        .WithDisplayFormat("🎨 {name}")); // "🎨 Dark", "🎨 Light", etc.
});

Browser Compatibility

The theme switcher requires:

  • LocalStorage API - For persisting user preferences
  • JavaScript enabled - For dynamic theme switching
  • Modern browsers - Chrome 60+, Firefox 55+, Safari 11+, Edge 79+

Fallback: If JavaScript is disabled, the initial theme specified in UseSwaggerUI() is used.

Performance Considerations

Theme Loading

  • Lazy loading - Themes are loaded only when selected
  • Cached - Browser caches theme CSS files
  • Minified - Uses minified CSS (by default only for predefined themes)

Optimization Tips

For many themes:

  • Use WithThemes() to limit available options
  • Pre-load frequently used themes
  • Use minified themes in production

For large applications:

  • Enable browser caching headers
  • Consider limiting the number of available themes

Troubleshooting

Switcher Not Appearing

Check these common issues:

  1. JavaScript errors - Open browser console (F12) and check for errors
  2. Caching - Hard refresh your browser clearing the cache
  3. Theme compatibility - Ensure themes are properly embedded (not standalone themes)
  4. Configuration - Verify EnableThemeSwitcher() is called

Important

Clear browser cache after changing theme switcher configuration. The theme metadata is cached for performance optimization.

Themes Not Switching

Verify:

  1. Theme files exist - Check that CSS files are embedded resources
  2. Correct naming - File names match what's registered
  3. No CSS conflicts - Custom styles aren't overriding theme
  4. Browser console - Check for 404 errors when loading themes

User Preference Not Persisting

Check:

  1. LocalStorage enabled - Browser privacy settings allow localStorage
  2. Browser support - Private/incognito mode may block localStorage
  3. Clear storage - Try clearing localStorage and setting preference again

Auto-Discovery Not Finding Themes

Ensure:

  1. Embedded resources - CSS files are set as embedded resources
  2. Naming convention - Files are in SwaggerThemes or SwaggerThemes.* namespaces or inherit from BaseTheme
  3. Assembly reference - Using the correct assembly in UseSwaggerUI()
  4. Build action - Files have "Embedded resource" build action
  5. Not standalone - Standalone themes lack JavaScript support required for the switcher

Compatibility

Works with:

Does NOT work with:

Next Steps


Back to Advanced Options

Clone this wiki locally