Hello,
I have my app set up so that I can dynamically switch between the built in themes and it works well.
I've used your theme studio to modify the material theme but I would like to save it as it's own theme so that I can pick it from the list just like any built in theme. I tried renaming the modified scss and editing the skin-name in the scss but it just results in a mess when applied.
How would I go about making a custom theme that can be included just like the built in themes so I can switch between them dynamically?
Thanks
Any suggestions on this? I want to make a custom theme and then be able to treat it like one of the built in themes so I can swap between several custom themes and the built in themes dynamically.
Sheldon
No reply at all to this? You guys are usually pretty quick..
Hi Sheldon,
Based on the details you have provided, we have prepared a sample application incorporating the bootstrap5-dark, tailwind and tailwind-dark built-in themes. This implementation allows for dynamic theme changing with both built-in and customized themes.
Please refer to the following code snippet, video and sample for clarification:
_Host.cshtml
@page "/" @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.WebUtilities; @namespace DynamicTheming.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = null; @*Pass the URL query to select the theme name *@ QueryHelpers.ParseQuery(Request.QueryString.Value).TryGetValue("theme", out var themeName); themeName = themeName.Count > 0 ? themeName.First() : "tailwind-dark"; } <!DOCTYPE html> <html lang="en"> <head> //… @*Sets the selected theme name into styles*@ @if (themeName == "bootstrap5-dark" || themeName == "tailwind" || themeName == "tailwind-dark") { <link rel='nofollow' href=@("_content/Syncfusion.Blazor.Themes/" + themeName + ".css") rel="stylesheet" /> } else { <link rel='nofollow' href=@("css/custom-theme/" + themeName + ".css") rel="stylesheet" /> }
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>
//… </head> //… |
Index.razor
@page "/"
<PageTitle>Index</PageTitle>
@inject DynamicTheming.Shared.ThemeGenerator themeHelper @inject NavigationManager uriHelper @using Microsoft.AspNetCore.WebUtilities; @inject IJSRuntime JSRuntime;
<h1>Dynamic Theming</h1>
<div> <table> <tbody> <tr> <td> CHOOSE THEME </td> <td> <SfDropDownList TItem="Theme" TValue="string" @bind-value="themeHelper.currentTheme" DataSource="themeHelper.Themes" Placeholder="CHOOSE THEME"> <DropDownListEvents TItem="Theme" TValue="string" ValueChange="OnThemeChange"></DropDownListEvents> <DropDownListFieldSettings Text="Text" Value="Value"></DropDownListFieldSettings> </SfDropDownList> </td> </tr> @if(themeHelper.currentTheme == "tailwind-dark" || themeHelper.currentTheme == "tailwind" || themeHelper.currentTheme == "bootstrap5-dark"){ <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> <SfTextBox Placeholder="Enter custom theme name" @bind-Value="CustomThemeName"></SfTextBox> </td> <td> </td> </tr> <tr> <td> <SfButton Content="Generate theme" OnClick="GenerateTheme"></SfButton> </td> <td> </td> </tr> } </tbody> </table> </div>
<br />
<br />
<br />
<br />
<div style="margin: 20px"><SfButton IsPrimary=true>Button</SfButton></div>
<br /> <br />
<div style="margin: 20px"><SfCalendar TValue="DateTime"></SfCalendar></div>
@code {
private string CustomThemeName; 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) : themeHelper.Themes[0].Value; @if (themeHelper.currentTheme == "tailwind-dark" || themeHelper.currentTheme == "tailwind" || themeHelper.currentTheme == "bootstrap5-dark") { themeVariables = themeHelper.GetThemeVariables(); } }
/// <summary> /// The switcher OnChange event handler. /// </summary> public void OnThemeChange(ChangeEventArgs<string, Theme> args) { var theme = GetThemeName(); if (theme != args.ItemData.Value) { uriHelper.NavigateTo(GetUri(args.ItemData.Value), true); } @if (themeHelper.currentTheme == "tailwind-dark" || themeHelper.currentTheme == "tailwind" || themeHelper.currentTheme == "bootstrap5-dark") { themeVariables = themeHelper.GetThemeVariables(); } }
/// <summary> /// Returns the theme name from Uri QueryString. /// </summary> private string GetThemeName() { var uri = uriHelper.ToAbsoluteUri(uriHelper.Uri); QueryHelpers.ParseQuery(uri.Query).TryGetValue("theme", out var theme); theme = theme.Count > 0 ? theme.First() : "bootstrap4"; return theme; }
/// <summary> /// Returns the new Uri to navigate with theme changes. /// </summary> private string GetUri(string themeName) { var uri = uriHelper.ToAbsoluteUri(uriHelper.Uri); return uri.AbsolutePath + "?theme=" + themeName; }
public void GenerateTheme() { themeHelper.RefreshTheme(themeVariables, CustomThemeName); } }
<style>
th, td { padding: 15px; }
</style> |
ThemeGenerator.cs
using DartSassHost; using DartSassHost.Helpers; using JavaScriptEngineSwitcher.ChakraCore; using Microsoft.AspNetCore.Components; using System.Text.RegularExpressions;
namespace DynamicTheming.Shared { public class Theme { public string Value { get; set; } public string Text { get; set; } } public class ThemeGenerator: ComponentBase { 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; } private string FolderPath { get; set; } private string[] FileNames { get; set; } public ThemeGenerator(IHostEnvironment hostingEnvironment, NavigationManager navigationManager) { env = hostingEnvironment; uriHelper = navigationManager; OutputCssFile = env.ContentRootPath + @"\wwwroot\css\custom-theme\.css"; FolderPath = env.ContentRootPath + @"\wwwroot\css\custom-theme"; FileNames = Directory.GetFiles(FolderPath).Select(Path.GetFileNameWithoutExtension).ToArray(); foreach (var file in FileNames) { Themes.Add(new Theme() { Text = file, Value = file }); } }
public List<Theme> Themes = new List<Theme>() { new Theme(){ Text = "TailWind Dark", Value = "tailwind-dark" }, new Theme(){ Text = "TailWind", Value = "tailwind" }, new Theme(){ Text = "Bootstrap5 Dark", Value = "bootstrap5-dark" }, };
public ThemeVariable GetThemeVariables() { themeVariables.PrimaryColor = GetValue(PrimaryColorVariable); themeVariables.PrimaryFont = GetValue(PrimaryFontVariable); themeVariables.SecondaryFont = GetValue(SecondaryFontVariable); themeVariables.SecondaryColor = GetValue((currentTheme == "tailwind-dark") || (currentTheme == "tailwind") ? 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 CustomThemeName) { 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") || (currentTheme == "tailwind") ? SecondaryBgColorVariable : SecondaryColorVariable; output = Regex.Replace(output, $\\{secondaryColor}:(.*);, $"{secondaryColor}: {themeVariables.SecondaryColor} !default;");
//to create new custom theme string modifiedOutputCssFile = OutputCssFile.Replace(".css", CustomThemeName.ToLower() + ".css"); 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(modifiedOutputCssFile, 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; } } }
|
Video: https://www.syncfusion.com/downloads/support/directtrac/general/ze/DynamicThemeSwitching-849626594
Sample: https://www.syncfusion.com/downloads/support/directtrac/general/ze/DynamicTheming1940471352
Please let us know if you have any concerns.
Regards,
Bharat Ram H