Skip to content
Draft
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
@@ -0,0 +1,43 @@
<FluentStack Wrap="true" VerticalAlignment="VerticalAlignment.Center">
<FluentSwitch @bind-Value="@FullScreen" Label="FullScreen" Margin="@Margin.Right4" />
<FluentSwitch @bind-Value="@Interactive" Label="Interactive" Margin="@Margin.Right4" />
<FluentSwitch @bind-Value="@Visible" Label="Visible" Margin="@Margin.Right4" />
<FluentSpacer />
<FluentSelect @bind-Value="@CloseMode"
Items="@(Enum.GetValues(typeof(OverlayCloseMode)).Cast<OverlayCloseMode>())"
Label="Close Mode"
LabelPosition="LabelPosition.Before" />
</FluentStack>

<div style="@CommonStyles.NeutralBorder1 @CommonStyles.NeutralBackground"
class="@Margin.All4 @Padding.All4">

<!-- Container with a interactive (clickable) button -->
<h3>Container</h3>
<button onclick="alert('clicked')">Click Me</button>

<!-- Overlay -->
<FluentOverlay @ref="OverlayRef" Style="background: transparent;"
Class="my-class"
FullScreen="@FullScreen"
Interactive="@Interactive"
@bind-Visible="@Visible"
CloseMode="@CloseMode">
<FluentSpinner />
</FluentOverlay>

</div>

<FluentStack Wrap="true" HorizontalGap="12px">
<FluentButton OnClick="@(e => OverlayRef.ShowAsync())">Show Overlay</FluentButton>
<FluentButton OnClick="@(e => OverlayRef.CloseAsync())">Close Overlay</FluentButton>
</FluentStack>

@code
{
FluentOverlay OverlayRef = default!;
bool FullScreen = false;
bool Interactive = false;
bool Visible = false;
OverlayCloseMode CloseMode = OverlayCloseMode.All;
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ title: Overlay
route: /Overlay
---

# Overlay HTMLElement
# Overlay Default

{{ OverlayHtmlElement }}
{{ OverlayDefault }}

## API FluentOverlay

{{ API Type=FluentOverlay }}
69 changes: 68 additions & 1 deletion src/Core.Scripts/src/Components/Overlay/FluentOverlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,42 @@ export namespace Microsoft.FluentUI.Blazor.Components.Overlay {
shadow.appendChild(this.dialog);
}

/***************
Attributes
****************/

static get observedAttributes() { return ['dialogStyle', 'dialogClass', 'visible']; }

// Handles attribute changes to update references and listeners.
attributeChangedCallback(name: string, oldValue: string, newValue: string) {
if (oldValue !== newValue) {

if (name === 'background') {
if (this.hasAttribute('background')) {
this.background = this.getAttribute('background')!;
}
}

if (name === 'dialogStyle') {
if (this.hasAttribute('dialogStyle')) {
this.dialogStyle = this.getAttribute('dialogStyle')!;
}
}

if (name === 'dialogClass') {
if (this.hasAttribute('dialogClass')) {
this.dialogClass = this.getAttribute('dialogClass')!;
}
}

if (name === 'visible') {
const isVisible = this.hasAttribute('visible')
&& (this.getAttribute('visible') === 'true' || this.getAttribute('visible') === '');
this.visible = isVisible;
}
}
}

/************************
Public Properties
************************/
Expand Down Expand Up @@ -152,6 +188,19 @@ export namespace Microsoft.FluentUI.Blazor.Components.Overlay {
}
}

// Property getter/setter for visible
public get visible(): boolean {
return this.dialog?.open ?? false;
}

public set visible(value: boolean) {
if (value) {
this.show();
} else {
this.close();
}
}

/************************
Public methods
************************/
Expand Down Expand Up @@ -285,7 +334,7 @@ export namespace Microsoft.FluentUI.Blazor.Components.Overlay {
}
}

// Subscribe to container size changes
// Subscribe to container size changes
private createResizeObserver(): void {
if (!this.resizeObserver && this.container) {
this.resizeObserver = new ResizeObserver(() => {
Expand Down Expand Up @@ -331,6 +380,24 @@ export namespace Microsoft.FluentUI.Blazor.Components.Overlay {

}

/**
* Display the fluent-overlay with the given id
* @param id The id of the fluent-overlay to display
*/
export function Show(id: string): void {
const element = document.getElementById(id) as any;
element?.show();
}

/**
* Close the fluent-overlay with the given id
* @param id The id of the fluent-overlay to close
*/
export function Close(id: string): void {
const element = document.getElementById(id) as any;
element?.close();
}

/**
* Register the FluentOverlay component
* @param blazor
Expand Down
2 changes: 2 additions & 0 deletions src/Core.Scripts/src/ExportedMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Microsoft as FluentTabsFile } from './Components/Tabs/FluentTabs';
import { Microsoft as FluentMultiSplitterFile } from './Components/Splitter/FluentMultiSplitter';
import { Microsoft as FluentLayoutFile } from './Components/Layout/FluentLayout';
import { Microsoft as FluentTextMaskedFile } from './Components/TextInput/TextMasked';
import { Microsoft as FluentOverlayFile } from './Components/Overlay/FluentOverlay';

export namespace Microsoft.FluentUI.Blazor.ExportedMethods {

Expand All @@ -32,6 +33,7 @@ export namespace Microsoft.FluentUI.Blazor.ExportedMethods {
(window as any).Microsoft.FluentUI.Blazor.Components.MultiSplitter = FluentMultiSplitterFile.FluentUI.Blazor.Components.MultiSplitter;
(window as any).Microsoft.FluentUI.Blazor.Components.Layout = FluentLayoutFile.FluentUI.Blazor.Components.Layout;
(window as any).Microsoft.FluentUI.Blazor.Components.TextMasked = FluentTextMaskedFile.FluentUI.Blazor.Components.TextMasked;
(window as any).Microsoft.FluentUI.Blazor.Components.Overlay = FluentOverlayFile.FluentUI.Blazor.Components.Overlay;

// [^^^ Add your other exported methods before this line ^^^]
}
Expand Down
23 changes: 23 additions & 0 deletions src/Core/Components/Overlay/FluentOverlay.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@namespace Microsoft.FluentUI.AspNetCore.Components
@using Microsoft.FluentUI.AspNetCore.Components.Extensions
@inherits FluentComponentBase

<fluent-overlay id="@Id"
dialog-style="@StyleValue"
dialog-class="@ClassValue"
background="@GetBackground()"
fullscreen="@FullScreen"
interactive="@Interactive"
close-mode="@CloseMode.ToAttributeValue()"
visible="@Visible"
@attributes="@AdditionalAttributes"
@ondialogtoggle="@OnToggleAsync">
@if (ChildContent is null)
{
<FluentSpinner />
}
else
{
@ChildContent
}
</fluent-overlay>
128 changes: 128 additions & 0 deletions src/Core/Components/Overlay/FluentOverlay.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// ------------------------------------------------------------------------
// This file is licensed to you under the MIT License.
// ------------------------------------------------------------------------

using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components;
using Microsoft.FluentUI.AspNetCore.Components.Utilities;
using Microsoft.JSInterop;

namespace Microsoft.FluentUI.AspNetCore.Components;

/// <summary>
/// Represents an overlay component that provides visual layering and interaction blocking in Fluent UI applications.
/// </summary>
public partial class FluentOverlay : FluentComponentBase, IFluentComponentElementBase
{
/// <summary />
public FluentOverlay(LibraryConfiguration configuration) : base(configuration)
{
Id = Identifier.NewId();
}

/// <summary />
protected string? ClassValue => DefaultClassBuilder
.Build();

/// <summary />
protected string? StyleValue => DefaultStyleBuilder
.Build();

/// <inheritdoc cref="IFluentComponentElementBase.Element" />
[Parameter]
public ElementReference Element { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the component is displayed in full screen mode.
/// </summary>
[Parameter]
public bool FullScreen { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the overlay allows interaction with underlying content.
/// </summary>
[Parameter]
public bool Interactive { get; set; }

/// <summary>
/// Gets or sets the background color of the overlay.
/// Default is `var(--colorBackgroundOverlay)`.
/// </summary>
[Parameter]
public string BackgroundColor { get; set; } = "var(--colorBackgroundOverlay)";

/// <summary>
/// Gets or sets the opacity level of the overlay background.
/// Default is `0.2` (20%).
/// </summary>
[Parameter]
public double Opacity { get; set; } = 0.4;

/// <summary>
/// Gets or sets the mode that determines how the overlay can be closed.
/// Default is <see cref="OverlayCloseMode.All"/>.
/// </summary>
[Parameter]
public OverlayCloseMode CloseMode { get; set; } = OverlayCloseMode.All;

/// <summary>
/// Gets or sets a value indicating whether the overlay is visible.
/// </summary>
[Parameter]
public bool Visible { get; set; }

/// <summary>
/// Gets or sets the callback that is invoked when the visibility state changes.
/// </summary>
[Parameter]
public EventCallback<bool> VisibleChanged { get; set; }

/// <summary>
/// Gets or sets the content to be rendered inside the component.
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }

/// <summary>
/// Displays the overlay.
/// </summary>
[ExcludeFromCodeCoverage]
public async Task ShowAsync()
{
await JSRuntime.InvokeVoidAsync("Microsoft.FluentUI.Blazor.Components.Overlay.Show", Id);
}

/// <summary>
/// Hides the overlay.
/// </summary>
[ExcludeFromCodeCoverage]
public async Task CloseAsync()
{
await JSRuntime.InvokeVoidAsync("Microsoft.FluentUI.Blazor.Components.Overlay.Close", Id);
}

/// <summary />
internal async Task OnToggleAsync(DialogToggleEventArgs args)
{
if (string.CompareOrdinal(args.Id, Id) != 0)
{
return;
}

var isVisible = string.Equals(args.NewState, "open", StringComparison.OrdinalIgnoreCase);
if (Visible != isVisible)
{
Visible = isVisible;

if (VisibleChanged.HasDelegate)
{
await VisibleChanged.InvokeAsync(Visible);
}
}
}

private string GetBackground()
{
return $"color-mix(in srgb, {BackgroundColor} {Opacity * 100}%, transparent)";
}
}
3 changes: 2 additions & 1 deletion src/Core/Components/Switch/FluentSwitch.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

<FluentField InputComponent="@this" ForId="@Id" Class="@ClassValue" Style="@StyleValue" Label="@GetLabel"
tabindex="@AdditionalAttributes.GetValueIfNoAdditionalAttribute("tabindex", "-1", when: () => ReadOnly)">
<fluent-switch aria-label="@AriaLabel"
<fluent-switch @ref="@Element"
aria-label="@AriaLabel"
autofocus="@Autofocus"
checked="@CurrentValue"
disabled="@Disabled"
Expand Down
Loading
Loading