Files
pos-system/microservices/.agent/skills/blazor-theme-patterns/SKILL.md
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

4.6 KiB

name, description
name description
blazor-theme-patterns Best practices for implementing Light/Dark themes in Blazor (MudBlazor) applications, ensuring synchronization between C# and CSS.

Blazor Theme Patterns

This skill documents the patterns and best practices for implementing robust Light/Dark theming in Blazor applications, specifically when using MudBlazor alongside Custom CSS.

1. The Hybrid Theming Problem

Blazor apps often have two sources of truth for styling:

  1. MudBlazor Theme (MudTheme in C#): Controls MudBlazor components (AppBar, Drawer, Buttons).
  2. CSS Variables (app.css): Controls native HTML elements (body, h1, custom divs) and global layout.

Risk: If these two are not synchronized, you get "partial themes" (e.g., Dark Header but Light Body).

2. Solution: synchronization Pattern

Always synchronize the Blazor theme state with the DOM via JavaScript Interop.

Step 1: Define CSS Variables with Data Attribute

In your app.css, define variables using the [data-theme="dark"] selector.

:root {
    /* Light Mode Defaults */
    --bg-primary: #ffffff;
    --text-primary: #18181b;
}

[data-theme="dark"], :root[data-theme="dark"] {
    /* Dark Mode Overrides */
    --bg-primary: #09090b;
    --text-primary: #fafafa;
}

/* Enforce Body Background */
body {
    background-color: var(--bg-primary) !important;
    color: var(--text-primary) !important;
    transition: background-color 0.3s ease;
}

Step 2: Add JS Helper

In index.html (before MudBlazor.min.js), add a lightweight helper to switch attributes.

<script>
    window.setTheme = (theme) => {
        document.documentElement.setAttribute('data-theme', theme);
    }
</script>

Step 3: call from Blazor Layout

In MainLayout.razor, inject IJSRuntime and call the helper when toggling the theme.

@inject IJSRuntime JSRuntime

<MudThemeProvider @bind-IsDarkMode="_isDarkMode" Theme="_theme" />

@code {
    private bool _isDarkMode;
    private MudTheme _theme = new();

    private async Task ToggleDarkMode()
    {
        _isDarkMode = !_isDarkMode;
        // Sync with CSS
        await JSRuntime.InvokeVoidAsync("setTheme", _isDarkMode ? "dark" : "light");
    }
}

3. Common Pitfalls & Solutions

A. "Invisible" Text in Dark Mode (White on White)

Issue: MudBlazor's Primary color might be White in Dark Mode (e.g., #fafafa). If the PrimaryContrastText is not set, it might default to White, making text invisible on a Primary Filled Button. Fix: Explicitly set PrimaryContrastText in your PaletteDark.

PaletteDark = new PaletteDark()
{
    Primary = "#fafafa",
    PrimaryContrastText = "#18181b", // Force Black text on White Primary button
    // ...
}

CSS Hardening: If C# palette fails, force it locally in CSS:

[data-theme="dark"] .mud-button-filled-primary {
    color: #18181b !important;
}

B. AppBar Color Mismatch

Issue: MudAppBar defaults to Color.Primary (often black/dark). In Light Mode, if you want a white AppBar, Color.Primary might conflict. Fix: Use Color="Color.Default" and let the Theme Palette handle the background color (AppbarBackground).

<MudAppBar Color="Color.Default" Elevation="0" ... />

C. Development Workflow (Hot Reload)

Recommendation: Use dotnet watch during development to instantly see CSS and Razor changes without restarting.

dotnet watch --project src/WebClientBase.Client

Note:

  • CSS Changes: Applied instantly.
  • Razor Markup: Applied instantly.
  • C# Logic (@code): usually applied instantly, but complex logic changes (like modifying OnInitialized) may require a manual restart (Ctrl+R).
  • Full Rebuild: Required if you add constant fields or change method signatures that Hot Reload cannot handle.

4. Verification Checklist

When implementing themes, verify these points using the Browser Tool across multiple devices:

A. Core Theme Checks

  1. Body Background: Does it change hex codes when toggled?
  2. Primary Button Text: Is it readable (Contrast Ratio) in both Light and Dark modes?
  3. Headings: Do standard h1-h6 tags invert color correctly?

B. Responsive Checks (Crucial)

  1. Desktop (> 960px): Check standard navigation bar and layout.
  2. Tablet (768px - 960px): Check if layout adapts (e.g. grid changes).
  3. Mobile (< 768px):
    • Hamburger Menu: Is the icon visible in both themes?
    • Drawer/Sidebar: Does the drawer background match the theme (especially in Dark Mode)?
    • Mobile Navigation: are links readable?