Articles in this section
Category / Section

How to change the theme with customizable color values within a Blazor Application?

10 mins read

This section outlines how to implement a dynamic theme changing with customizable color values within a Blazor Application. Here, we have prepared a sample application incorporating the “bootstrap5-dark” and “tailwind-dark” themes.

Please find the following code snippet and sample for reference:

Here, the Syncfusion Dropdown list and ColorPicker components are utilized for switching between themes and updating colors for the theme variables.

Home.razor

@page "/"

<PageTitle>Index</PageTitle>

@inject DynamicTheming.Shared.ThemeGenerator themeHelper
@inject NavigationManager uriHelper

<h1>Dynamic Theming</h1>

<div>
   <table>
       <tbody>
           <tr>
               <td>
                   CHOOSE THEME
               </td>
               <td>
                   <SfDropDownList TItem="Theme" TValue="string" @bind-value="themeHelper.currentTheme" DataSource="@Themes" Placeholder="CHOOSE THEME">
                       <DropDownListEvents TItem="Theme" TValue="string" ValueChange="OnThemeChange"></DropDownListEvents>
                       <DropDownListFieldSettings Text="Text" Value="Value"></DropDownListFieldSettings>
                   </SfDropDownList>
               </td>
           </tr>
           <tr>
               <td>
                   Primary color
               </td>
               <td>
                   <SfColorPicker @bind-Value="themeVariables.PrimaryColor" Mode="ColorPickerMode.Palette"></SfColorPicker>
               </td>
           </tr>
           <tr>
               <td>
                   Primary font
               </td>
               <td>
                   <SfColorPicker @bind-Value="themeVariables.PrimaryFont" Mode="ColorPickerMode.Palette"></SfColorPicker>
               </td>
           </tr>
           <tr>
               <td>
                   Secondary color
               </td>
               <td>
                   <SfColorPicker @bind-Value="themeVariables.SecondaryColor" Mode="ColorPickerMode.Palette"></SfColorPicker>
               </td>
           </tr>
           <tr>
               <td>
                   Secondary font
               </td>
               <td>
                   <SfColorPicker @bind-Value="themeVariables.SecondaryFont" Mode="ColorPickerMode.Palette"></SfColorPicker>
               </td>
           </tr>
           <tr>
               <td>
                   <SfButton Content="Update theme" OnClick="UpdateTheme"></SfButton>
               </td>
               <td>
               </td>
           </tr>
       </tbody>
   </table>
</div>

<br />
<br />

<SfButton IsPrimary=true>Button</SfButton>
<br />
<br />

<SfCalendar TValue="DateTime"></SfCalendar>

@code {
   private List<Theme> Themes = new List<Theme>() {
       new Theme(){ Text = "TailWind Dark", Value = "tailwind-dark" },
       new Theme(){ Text = "Bootstrap5 Dark", Value = "bootstrap5-dark" },
   };

   private ThemeVariable themeVariables = new ThemeVariable();

   protected override void OnInitialized()
   {
       string url = uriHelper.Uri;
       int index = url.IndexOf("?theme=");
       themeHelper.currentTheme = index > -1 ? url.Substring(index + 7) : Themes[0].Value;
       themeVariables = themeHelper.GetThemeVariables();
   }

   public void OnThemeChange(ChangeEventArgs<string, Theme> args)
   {
       themeVariables = themeHelper.GetThemeVariables();
   }

   public void UpdateTheme()
   {
       themeHelper.RefreshTheme(themeVariables);
   }

   public class Theme
   {
       public string Value { get; set; }
       public string Text { get; set; }
   }
}


<style>
   th, td {
       padding: 15px;
   }
</style> 

The new color value for the theme variables will be retrieved, compiled, and refreshed to dynamically update the theme.

ThemeGenerator.cs

using DartSassHost;
using DartSassHost.Helpers;
using JavaScriptEngineSwitcher.ChakraCore;
using Microsoft.AspNetCore.Components;
using System.Text.RegularExpressions;


namespace DynamicTheming.Shared
{
   public class ThemeGenerator
   {
       private IHostEnvironment env;

       private NavigationManager uriHelper;

       public string currentTheme { get; set; }

       protected ThemeVariable themeVariables = new ThemeVariable();

       private string PrimaryColorVariable = "$primary";

       private string PrimaryFontVariable = "$primary-text-color";

       private string SecondaryColorVariable = "$secondary";

       private string SecondaryBgColorVariable = "$secondary-bg-color";

       private string SecondaryFontVariable = "$secondary-text-color";

       private string OutputCssFile { get; set; }

       public ThemeGenerator(IHostEnvironment hostingEnvironment, NavigationManager navigationManager)
       {
           env = hostingEnvironment;
           uriHelper = navigationManager;
           OutputCssFile = env.ContentRootPath + @"\wwwroot\css\custom-theme.css";
       }

       public ThemeVariable GetThemeVariables()
       {
           themeVariables.PrimaryColor = GetValue(PrimaryColorVariable);
           themeVariables.PrimaryFont = GetValue(PrimaryFontVariable);
           themeVariables.SecondaryFont = GetValue(SecondaryFontVariable);
           themeVariables.SecondaryColor = GetValue(currentTheme == "tailwind-dark" ? SecondaryBgColorVariable : SecondaryColorVariable);

           return themeVariables;
       }

       public string GetInputScssFile()
       {
           return env.ContentRootPath + @"\wwwroot\scss\custom-" + currentTheme + ".scss";
       }

       public string GetValue(string prop)
       {
           string value = null;
           string themeContent = File.ReadAllText(GetInputScssFile());
           Match matchedValue = Regex.Match(themeContent, $\\{prop}: (.*) !default;);

           if (matchedValue.Groups[1] != null)
           {
               value = matchedValue.Groups[1].Value.Trim();
           }
           return value;
       }

       public void RefreshTheme(ThemeVariable themeVariables)
       {
           string InputScssFile = GetInputScssFile();
           string output = File.ReadAllText(InputScssFile);

           output = Regex.Replace(output, $\\{PrimaryColorVariable}:(.*);, $"{PrimaryColorVariable}: {themeVariables.PrimaryColor} !default;");
           output = Regex.Replace(output, $\\{PrimaryFontVariable}:(.*);, $"{PrimaryFontVariable}: {themeVariables.PrimaryFont} !default;");
           output = Regex.Replace(output, $\\{SecondaryFontVariable}:(.*);, $"{SecondaryFontVariable}: {themeVariables.SecondaryFont} !default;");


           string secondaryColor = currentTheme == "tailwind-dark" ? SecondaryBgColorVariable : SecondaryColorVariable;
           output = Regex.Replace(output, $\\{secondaryColor}:(.*);, $"{secondaryColor}: {themeVariables.SecondaryColor} !default;");


           try
           {
               using (var sassCompiler = new SassCompiler(new ChakraCoreJsEngineFactory()))
               {
                   CompilationResult result = sassCompiler.Compile(output,false);
                   if (result.CompiledContent != null)
                   {
                       //Write compiled content to output css file.
                       File.WriteAllText(OutputCssFile, result.CompiledContent);

                       //Write updated content to input scss file.
                       File.WriteAllText(InputScssFile, output);
                   }
               }
           }
           catch (SassCompilerLoadException e)
           {
               Console.WriteLine("During loading of Sass compiler an error occurred. See details:");
               Console.WriteLine();
               Console.WriteLine(SassErrorHelpers.GenerateErrorDetails(e));
           }
           catch (SassCompilationException e)
           {
               Console.WriteLine("During compilation of SCSS code an error occurred. See details:");
               Console.WriteLine();
               Console.WriteLine(SassErrorHelpers.GenerateErrorDetails(e));
           }
           catch (SassException e)
           {
               Console.WriteLine("During working of Sass compiler an unknown error occurred. See details:");
               Console.WriteLine();
               Console.WriteLine(SassErrorHelpers.GenerateErrorDetails(e));
           }

           uriHelper.NavigateTo(uriHelper.BaseUri + "?theme=" + currentTheme, forceLoad: true);
       }
   }

   public class ThemeVariable
   {
       public string PrimaryColor { get; set; }
       public string PrimaryFont { get; set; }
       public string SecondaryColor { get; set; }
       public string SecondaryFont { get; set; }
   }
} 
Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied