Skip to content
Merged
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 @@ -3318,7 +3318,7 @@
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDesignTheme.Id">
<summary>
Gets or sets the identifier for the component.
</summary>
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDesignTheme.Mode">
<summary>
Expand Down Expand Up @@ -3353,12 +3353,12 @@
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDesignTheme.StorageName">
<summary>
Gets or sets the local storage name to save and retrieve the <see cref="P:Microsoft.FluentUI.AspNetCore.Components.FluentDesignTheme.Mode"/> and the <see cref="P:Microsoft.FluentUI.AspNetCore.Components.FluentDesignTheme.OfficeColor"/> / <see cref="P:Microsoft.FluentUI.AspNetCore.Components.FluentDesignTheme.CustomColor"/>.
</summary>
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDesignTheme.Direction">
<summary>
Gets or sets the body.dir value.
</summary>
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDesignTheme.OnLuminanceChanged">
<summary>
Expand Down Expand Up @@ -7850,6 +7850,9 @@
<member name="T:Microsoft.FluentUI.AspNetCore.Components.FluentOverlay">
<summary />
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentOverlay.GlobalState">
<summary />
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentOverlay.LibraryConfiguration">
<summary />
</member>
Expand Down Expand Up @@ -7896,6 +7899,7 @@
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentOverlay.Opacity">
<summary>
Gets or sets the opacity of the overlay.
Default is 0.4.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentOverlay.Alignment">
Expand Down Expand Up @@ -7935,9 +7939,9 @@
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentOverlay.BackgroundColor">
<summary>
Gets or sets the background color.
Needs to be formatted as an HTML hex color string (#rrggbb or #rgb).
Default is '#ffffff'.
Gets or sets the background color.
Needs to be formatted as an HTML hex color string (#rrggbb or #rgb)
Default NeutralBaseColor token value (#808080).
</summary>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentOverlay.DisposeAsync">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<FluentButton Appearance="Appearance.Accent" @onclick="() => visible = !visible">Show Overlay</FluentButton>

<FluentOverlay @bind-Visible=@visible
Opacity="0.4"
Transparent="false"
Alignment="@alignment"
Justification="@justification"
OnClose="HandleOnClose">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,17 @@

<style>
#my-zone {
background-color: white;
background-color: var(--neutral-base-color);
width: 200px;
height: 160px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#my-zone p {
color: var(--neutral-foregrond-rest);
}
</style>

@code {
Expand Down
2 changes: 1 addition & 1 deletion examples/Demo/Shared/Pages/Overlay/OverlayPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<h2 id="example">Examples</h2>

<DemoSection Title="Default" Component="typeof(OverlayDefault)">
<Description>Overlay with a default white background</Description>
<Description>Overlay with a default background (= NeutralBaseColor (#808080)) and default opacity (0.4). </Description>
</DemoSection>

<DemoSection Title="Timed" Component="typeof(OverlayTimed)">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public partial class FluentDesignTheme : ComponentBase

/// <summary>
/// Gets or sets the identifier for the component.
/// </summary>
/// </summary>
[Parameter]
public string Id { get; set; }

Expand Down Expand Up @@ -85,13 +85,13 @@ public partial class FluentDesignTheme : ComponentBase

/// <summary>
/// Gets or sets the local storage name to save and retrieve the <see cref="Mode"/> and the <see cref="OfficeColor"/> / <see cref="CustomColor"/>.
/// </summary>
/// </summary>
[Parameter]
public string? StorageName { get; set; }

/// <summary>
/// Gets or sets the body.dir value.
/// </summary>
/// </summary>
[Parameter]
public LocalizationDirection? Direction
{
Expand Down Expand Up @@ -183,10 +183,7 @@ public async Task OnChangeRaisedAsync(string name, string value)

break;
case "neutral-color":
if (value.StartsWith('#'))
{
GlobalDesign.SetNeutralColor(value);
}
GlobalDesign.SetNeutralColor(value);
break;
}
}
Expand Down Expand Up @@ -270,13 +267,10 @@ private async Task ApplyLocalStorageValuesAsync(DataLocalStorage? theme)
}

// Neutral base color
if (!string.IsNullOrEmpty(theme?.NeutralBaseColor))
if (!string.IsNullOrEmpty(theme?.NeutralColor))
{
if (theme.NeutralBaseColor.StartsWith('#'))
{
GlobalDesign.SetNeutralColor(theme.NeutralBaseColor);
}
await OnChangeRaisedAsync("neutral-base-color", theme.NeutralBaseColor);
GlobalDesign.SetNeutralColor(theme.NeutralColor);
await OnChangeRaisedAsync("neutral-color", theme.NeutralColor);
}
}

Expand All @@ -285,7 +279,7 @@ private class DataLocalStorage
{
public string? Mode { get; set; }
public string? PrimaryColor { get; set; }
public string? NeutralBaseColor { get; set; }
public string? NeutralColor { get; set; }
}

/// <summary />
Expand Down
84 changes: 49 additions & 35 deletions src/Core/Components/Overlay/FluentOverlay.razor.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

using System.Globalization;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Components;
Expand All @@ -16,8 +20,14 @@ public partial class FluentOverlay : IAsyncDisposable
private int _r, _g, _b;

private const string JAVASCRIPT_FILE = "./_content/Microsoft.FluentUI.AspNetCore.Components/Components/Overlay/FluentOverlay.razor.js";
private const string DEFAULT_NEUTRAL_COLOR = "#808080";

private DotNetObjectReference<FluentOverlay>? _dotNetHelper = null;

/// <summary />
[Inject]
private GlobalState GlobalState { get; set; } = default!;

/// <summary />
[Inject]
private LibraryConfiguration LibraryConfiguration { get; set; } = default!;
Expand All @@ -38,6 +48,7 @@ public partial class FluentOverlay : IAsyncDisposable
protected string? StyleValue => new StyleBuilder()
.AddStyle("cursor", "auto", () => Transparent)
.AddStyle("background-color", $"rgba({_r}, {_g}, {_b}, {Opacity.ToString()!.Replace(',', '.')})", () => !Transparent)
//.AddStyle("opacity", Opacity.ToString()!.Replace(',', '.'), CheckCSSVariableName().IsMatch(BackgroundColor))
.AddStyle("cursor", "default", () => !Transparent)
.AddStyle("position", FullScreen ? "fixed" : "absolute")
.AddStyle("display", "flex")
Expand Down Expand Up @@ -84,6 +95,7 @@ public partial class FluentOverlay : IAsyncDisposable

/// <summary>
/// Gets or sets the opacity of the overlay.
/// Default is 0.4.
/// </summary>
[Parameter]
public double? Opacity { get; set; }
Expand Down Expand Up @@ -130,12 +142,12 @@ public partial class FluentOverlay : IAsyncDisposable
public bool Dismissable { get; set; } = true;

/// <summary>
/// Gets or sets the background color.
/// Needs to be formatted as an HTML hex color string (#rrggbb or #rgb).
/// Default is '#ffffff'.
/// Gets or sets the background color.
/// Needs to be formatted as an HTML hex color string (#rrggbb or #rgb)
/// Default NeutralBaseColor token value (#808080).
/// </summary>
[Parameter]
public string BackgroundColor { get; set; } = "#ffffff";
public string? BackgroundColor { get; set; }

[Parameter]
public bool PreventScroll { get; set; } = false;
Expand All @@ -152,20 +164,19 @@ protected override async Task OnParametersSetAsync()
Id = _defaultId;
}

// Add a document.addEventListener when Visible is true
if (Visible)
{
// Add a document.addEventListener when Visible is true
await InvokeOverlayInitializeAsync();
}

// Remove a document.addEventListener when Visible is false
else
{
// Remove a document.addEventListener when Visible is false
await InvokeOverlayDisposeAsync();
}
}

if (!Transparent && Opacity == 0)
if (!Transparent && Opacity is null)
{
Opacity = 0.4;
}
Expand All @@ -175,33 +186,37 @@ protected override async Task OnParametersSetAsync()
Transparent = false;
}

if (!string.IsNullOrWhiteSpace(BackgroundColor))
BackgroundColor ??= GlobalState.NeutralColor ?? DEFAULT_NEUTRAL_COLOR;

if (!CheckRGBString().IsMatch(BackgroundColor))
{
throw new ArgumentException("BackgroundColor must be a valid HTML hex color string (#rrggbb or #rgb)");
}

#if NET7_0_OR_GREATER
if (!CheckRGBString().IsMatch(BackgroundColor))
#else
if (!Regex.IsMatch(BackgroundColor, "^(?:#([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))"))
#endif
throw new ArgumentException("BackgroundColor must be a valid HTML hex color string (#rrggbb or #rgb).");
else
{
_color = BackgroundColor[1..];
}
_color = BackgroundColor[1..];

if (_color.Length == 6)
{
_r = int.Parse(_color[..2], NumberStyles.HexNumber);
_g = int.Parse(_color[2..4], NumberStyles.HexNumber);
_b = int.Parse(_color[4..], NumberStyles.HexNumber);
}
else
{
_r = int.Parse(_color[0..1], NumberStyles.HexNumber);
_g = int.Parse(_color[1..2], NumberStyles.HexNumber);
_b = int.Parse(_color[2..], NumberStyles.HexNumber);
}
if (_color.Length == 6)
{
_r = int.Parse(_color[..2], NumberStyles.HexNumber);
_g = int.Parse(_color[2..4], NumberStyles.HexNumber);
_b = int.Parse(_color[4..], NumberStyles.HexNumber);
}
else
{
_r = int.Parse(_color[0..1], NumberStyles.HexNumber);
_g = int.Parse(_color[1..2], NumberStyles.HexNumber);
_b = int.Parse(_color[2..], NumberStyles.HexNumber);
}
}
protected override void OnInitialized()
{
GlobalState.OnChange += UpdateNeutralColor;
}

private void UpdateNeutralColor()
{
BackgroundColor = GlobalState.NeutralColor;
StateHasChanged();
}

[JSInvokable]
Expand Down Expand Up @@ -231,7 +246,7 @@ public async Task OnCloseHandlerAsync(MouseEventArgs e)
}

private async Task OnCloseInternalHandlerAsync(MouseEventArgs e)
{
{
Visible = false;

if (VisibleChanged.HasDelegate)
Expand All @@ -257,6 +272,8 @@ public async ValueTask DisposeAsync()
{
await _jsModule.DisposeAsync();
}

GlobalState.OnChange -= UpdateNeutralColor;
}

/// <summary />
Expand All @@ -278,9 +295,6 @@ private async Task InvokeOverlayDisposeAsync()
}
}

#if NET7_0_OR_GREATER
[GeneratedRegex("^(?:#(?:[a-fA-F0-9]{6}|[a-fA-F0-9]{3}))")]
private static partial Regex CheckRGBString();
#endif

}
12 changes: 12 additions & 0 deletions src/Core/DesignTokens/Swatch.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

using System.Drawing;

namespace Microsoft.FluentUI.AspNetCore.Components.DesignTokens;
Expand Down Expand Up @@ -82,5 +86,13 @@ private static float Normalize(float value, int min, int max)
return value / (max - min);
}

public System.Drawing.Color GetColor()
{
return System.Drawing.Color.FromArgb(
(byte)Denormalize(R, 0, 255),
(byte)Denormalize(G, 0, 255),
(byte)Denormalize(B, 0, 255));
}

private static float Denormalize(float value, int min, int max) => min + (value * (max - min));
}
9 changes: 6 additions & 3 deletions src/Core/wwwroot/js/loading-theme.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// To avoid Flash of Unstyled Content, the body is hidden.
// To avoid Flash of Unstyled Content, the body is hidden.
// Here we'll find the first web component and wait for it to be upgraded.
// When it is, we'll remove this invisibility from the body.

Expand All @@ -24,9 +24,10 @@ class LoadingTheme extends HTMLElement {
}

// Attributes
const storageName = this.getAttribute("storage-name");
const storageName = this.getAttribute("storage-name");
const mode = this.getAttribute("mode");
const primaryColor = this.getAttribute("primary-color");
const neutralColor = this.getAttribute("neutral-color");

const isDark = (modeSaved, isSystemDark) => {
switch (modeSaved) {
Expand All @@ -42,6 +43,7 @@ class LoadingTheme extends HTMLElement {
// Compute the saved or the system theme (dark/light).
const modeSaved = mode ?? JSON.parse(localStorage.getItem(storageName))?.mode;
const primaryColorSaved = primaryColor ?? JSON.parse(localStorage.getItem(storageName))?.primaryColor;
const neutralColorSaved = neutralColor ?? JSON.parse(localStorage.getItem(storageName))?.neutralColor;
const isSystemDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
const bgColor = isDark(modeSaved, isSystemDark) ? this.defaultDarkColor : this.defaultLightColor;

Expand All @@ -66,6 +68,7 @@ class LoadingTheme extends HTMLElement {
const designTheme = document.createElement("fluent-design-theme");
designTheme.setAttribute("mode", modeSaved);
designTheme.setAttribute("primary-color", primaryColorSaved);
designTheme.setAttribute("neutral-color", neutralColorSaved);
this.appendChild(designTheme);

// Wait for the fluentui web components to be loaded
Expand All @@ -81,4 +84,4 @@ class LoadingTheme extends HTMLElement {
}
}

customElements.define("loading-theme", LoadingTheme);
customElements.define("loading-theme", LoadingTheme);
Loading