Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
public class BitThemeBoxShadows
{
public string? Callout { get; set; }
public string? Callout2 { get; set; }
public string? Sm { get; set; }
public string? Nm { get; set; }
public string? Md { get; set; }
public string? Lg { get; set; }
public string? Xl { get; set; }
public string? Xxl { get; set; }
public string? Inner { get; set; }
public string? S1 { get; set; }
public string? S2 { get; set; }
public string? S3 { get; set; }
Expand Down
18 changes: 18 additions & 0 deletions src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,30 @@ public class BitThemeGeneralColorVariants
public string? Primary { get; set; }
public string? PrimaryHover { get; set; }
public string? PrimaryActive { get; set; }
public string? PrimaryDark { get; set; }
public string? PrimaryDarkHover { get; set; }
public string? PrimaryDarkActive { get; set; }
public string? PrimaryLight { get; set; }
public string? PrimaryLightHover { get; set; }
public string? PrimaryLightActive { get; set; }
public string? Secondary { get; set; }
public string? SecondaryHover { get; set; }
public string? SecondaryActive { get; set; }
public string? SecondaryDark { get; set; }
public string? SecondaryDarkHover { get; set; }
public string? SecondaryDarkActive { get; set; }
public string? SecondaryLight { get; set; }
public string? SecondaryLightHover { get; set; }
public string? SecondaryLightActive { get; set; }
public string? Tertiary { get; set; }
public string? TertiaryHover { get; set; }
public string? TertiaryActive { get; set; }
public string? TertiaryDark { get; set; }
public string? TertiaryDarkHover { get; set; }
public string? TertiaryDarkActive { get; set; }
public string? TertiaryLight { get; set; }
public string? TertiaryLightHover { get; set; }
public string? TertiaryLightActive { get; set; }
public string? Disabled { get; set; }
}

Expand Down
49 changes: 49 additions & 0 deletions src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
namespace Bit.BlazorUI;

/// <summary>
/// Optional helpers to populate semantic color steps from a single main color (HSV-based). Explicit non-null values on <paramref name="variants"/> are never overwritten.
/// </summary>
public static class BitThemeColorDerivation
{
/// <summary>Fills unset <see cref="BitThemeColorVariants"/> fields from <paramref name="mainHex"/>.</summary>
public static void FillColorRoleFromMain(BitThemeColorVariants variants, string mainHex)
{
if (variants is null || string.IsNullOrWhiteSpace(mainHex)) return;

try
{
var baseColor = new BitInternalColor(mainHex.Trim());
var (h, s, v) = baseColor.Hsv;

variants.Main ??= baseColor.Hex;
variants.MainHover ??= ToHex(h, s, ScaleV(v, 0.96));
variants.MainActive ??= ToHex(h, s, ScaleV(v, 0.90));
variants.Dark ??= ToHex(h, s, ScaleV(v, 0.82));
variants.DarkHover ??= ToHex(h, s, ScaleV(v, 0.76));
variants.DarkActive ??= ToHex(h, s, ScaleV(v, 0.70));
variants.Light ??= ToHex(h, s, AddV(v, 0.08));
variants.LightHover ??= ToHex(h, s, AddV(v, 0.12));
variants.LightActive ??= ToHex(h, s, AddV(v, 0.16));
variants.Text ??= SuggestOnColorText(baseColor);
}
catch
{
// ignore invalid color strings
}
}

private static string ToHex(double h, double s, double v, double a = 1)
=> new BitInternalColor(h, s, Clamp01(v), a).Hex!;

private static double ScaleV(double v, double factor) => Clamp01(v * factor);

private static double AddV(double v, double delta) => Clamp01(v + delta);

private static double Clamp01(double v) => v < 0 ? 0 : v > 1 ? 1 : v;

private static string SuggestOnColorText(BitInternalColor c)
{
var lum = (0.299 * c.R + 0.587 * c.G + 0.114 * c.B) / 255.0;
return lum > 0.55 ? "#000000" : "#FFFFFF";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal static ValueTask<string> BitThemeToggleThemeDarkLight(this IJSRuntime j
return js.Invoke<string>("BitTheme.toggleDarkLight");
}

internal static ValueTask BitThemeApplyBitTheme(this IJSRuntime js, Dictionary<string, string> theme, ElementReference? element)
internal static ValueTask BitThemeApplyBitTheme(this IJSRuntime js, IReadOnlyDictionary<string, string> theme, ElementReference? element)
{
return js.InvokeVoid("BitTheme.applyBitTheme", theme, element);
}
Expand Down
12 changes: 11 additions & 1 deletion src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
namespace Bit.BlazorUI;

/// <summary>
/// Bridges Blazor to the client <c>BitTheme</c> script: preset names on the <c>bit-theme</c> attribute vs inline CSS variables from <see cref="BitTheme"/>.
/// <see cref="SetThemeAsync"/> selects packaged Fluent CSS for <c>:root[bit-theme]</c>.
/// <see cref="ApplyBitThemeAsync"/> sets <c>--bit-*</c> variables on the target element (default <c>document.body</c>), overriding stylesheet defaults for that subtree.
/// Nested <see cref="BitThemeProvider"/> scopes overrides to its root element.
/// </summary>
public class BitThemeManager
{
private IJSRuntime _js = default!;
Expand All @@ -9,26 +15,30 @@ public BitThemeManager(IJSRuntime js)
_js = js;
}

/// <summary>Returns the active <c>bit-theme</c> name from the document element.</summary>
public async ValueTask<string> GetCurrentThemeAsync()
{
return await _js.BitThemeGetCurrentTheme();
}

/// <summary>Sets the <c>bit-theme</c> attribute (use values from <see cref="BitThemePresets"/> or custom names matching your CSS).</summary>
public async ValueTask<string> SetThemeAsync(string themeName)
{
return await _js.BitThemeSetTheme(themeName);
}

/// <summary>Toggles between configured light and dark theme names.</summary>
public async ValueTask<string> ToggleDarkLightAsync()
{
return await _js.BitThemeToggleThemeDarkLight();
}

/// <summary>Applies <paramref name="bitTheme"/> as CSS custom properties on <paramref name="element"/> (default: body), overriding stylesheet tokens for that subtree.</summary>
public async ValueTask ApplyBitThemeAsync(BitTheme bitTheme, ElementReference? element = null)
{
if (bitTheme is null) return;

await _js.BitThemeApplyBitTheme(BitThemeMapper.MapToCssVariables(bitTheme), element);
await _js.BitThemeApplyBitTheme(BitThemeUtilities.ToCssVariables(bitTheme), element);
Comment thread
msynk marked this conversation as resolved.
}
Comment on lines +36 to 42

public async ValueTask<bool> IsSystemInDarkMode()
Expand Down
Loading
Loading