Overlay Service
A programmatic service for opening dialogs, sheets, drawers, and alert dialogs imperatively from code.
Installation
dotnet add package Lumeo
One-time app setup (AddLumeo(), CSS & JS) is covered in the
installation guide.
Open a dialog containing a dynamic component and await its result.
OverlayService.Show*Async<T>,
the provider already wraps it in <Dialog><DialogContent>
(or the Sheet / Drawer equivalent). Your component renders as the children of that shell — put
<DialogHeader>,
<DialogFooter>
(or the Sheet / Drawer equivalents) and your body content directly at the root.
Inline-declarative usage (<Sheet><SheetContent>...</SheetContent></Sheet>)
inside a service-opened component is detected and passes through — but the cleaner pattern is
to skip the outer wrappers entirely.
Open a sheet panel from any side with a dynamic component.
Open a bottom drawer with a dynamic component.
Show a confirmation dialog and await the user's choice.
API Reference
OverlayService
| Method | Signature | Description |
|---|---|---|
| ShowDialogAsync | ShowDialogAsync<TComponent>(title?, parameters?, options?) | Opens a Dialog containing the given component. Returns a Task<OverlayResult>. |
| ShowSheetAsync | ShowSheetAsync<TComponent>(title?, side, size, parameters?, options?) | Opens a Sheet panel. Side defaults to Right. Returns a Task<OverlayResult>. |
| ShowDrawerAsync | ShowDrawerAsync<TComponent>(title?, parameters?, options?) | Opens a Drawer from the bottom. Returns a Task<OverlayResult>. |
| ShowAlertDialogAsync | ShowAlertDialogAsync(alertOptions) | Shows a confirmation alert dialog. Returns a Task<OverlayResult>. |
| Close | Close(overlayId, result?) | Closes an overlay and resolves its task with the given result data. |
| Cancel | Cancel(overlayId) | Cancels an overlay, resolving its task with a cancelled result. |
OverlayResult
| Member | Type | Description |
|---|---|---|
| Cancelled | bool | True when the user dismissed the overlay without confirming. |
| Data | object? | The result value passed to Close(). |
| GetData<T>() | T? | Casts and returns the result data as T. |
OverlayReference
| Member | Type | Description |
|---|---|---|
| Id | string | Unique identifier for this overlay instance. |
| Parameters | OverlayParameters? | The parameters passed when the overlay was opened. |
| Close(result?) | void | Closes the overlay and resolves with optional result data. |
| Cancel() | void | Cancels the overlay, setting Cancelled = true on the result. |
OverlayParameters
| Method | Signature | Description |
|---|---|---|
| Add | Add(name, value) → OverlayParameters | Adds a named parameter. Returns itself for chaining. |
| Get<T> | Get<T>(name) → T? | Retrieves a parameter by name cast to type T. |
| ToDictionary | ToDictionary() → Dictionary<string, object> | Returns all parameters as a dictionary for DynamicComponent use. |
OverlayOptions
| Property | Type | Default | Description |
|---|---|---|---|
| Class | string? | null | Additional CSS class for the overlay container. |
| PreventClose | bool | false | When true, the close button and backdrop click are disabled. |
| SheetSide | SheetSide | Right | Which side the sheet slides in from. |
| Size | OverlaySize | Default | Dialog & Sheet (3.6.0). Unified size knob. For a Dialog it maps to a max-w-* preset (Sm→max-w-sm, Default→max-w-lg, Lg→max-w-2xl, Xl→max-w-4xl, Full→near-viewport) — so you can enlarge a service Dialog without a Class override. For a Sheet it controls width on Left/Right or height on Top/Bottom; Full on Bottom + SwipeToClose=true gives the mobile-fullscreen sheet. |
| SheetSize deprecated | SheetSize | Default | Legacy Sheet-only alias for Size (1:1 mapping). Kept for source compatibility — prefer Size in new code. |
| SwipeToClose | bool | false | Sheet-only (2.1.1). Pipes the SwipeToClose flag through to the rendered SheetContent so programmatically-opened sheets can be dismissed by swiping in the direction matching SheetSide. Default false to keep existing programmatic-open behaviour. Drawers already swipe-close by default. |
| MobileBreakpoint | int? | 768 | Sheet-only (2.1.3). Viewport width threshold (CSS px) below which the Mobile* overrides activate. Default 768 = Tailwind md. Set to null to disable responsive switching entirely. |
| MobileSheetSide | SheetSide? | null | Sheet-only (2.1.3). Side override used when the viewport is below MobileBreakpoint. Typical pattern: Lumeo.Side.Right on desktop, Lumeo.Side.Bottom on mobile. null keeps SheetSide at every size. |
| MobileSize | OverlaySize? | null | Dialog & Sheet (3.6.0). Size override used below MobileBreakpoint. Pair with MobileSheetSide=Bottom + MobileSize=Full for the mobile-fullscreen bottom-sheet pattern. null keeps Size at every viewport. |
| MobileSheetSize deprecated | SheetSize? | null | Legacy alias for MobileSize (1:1 mapping, null round-trips). Prefer MobileSize. |
| MobileSwipeToClose | bool? | null | Sheet-only (2.1.3). SwipeToClose override below MobileBreakpoint. Typical: false on desktop side panel, true on mobile bottom sheet so the pull-down dismiss is available. |
Sizing overlays (3.6.0)
OverlayOptions.Size is a single, unified knob that sizes both Dialogs and Sheets — no Class override needed. To make a service-opened Dialog larger, just pass a Size:
// A wide dialog — Lg → max-w-2xl, Xl → max-w-4xl, Full → near-viewport
await Overlay.ShowDialogAsync<MyForm>(
title: "Edit user",
options: new OverlayOptions { Size = OverlaySize.Lg });
The same Size drives Sheets (width on Left/Right, height on Top/Bottom). The old Sheet-only SheetSize property still works as a 1:1 alias but is deprecated — prefer Size.
Responsive sheets (2.1.3)
A single ShowSheetAsync call can switch between a side panel on desktop and a fullscreen bottom sheet on mobile, including SwipeToClose behaviour. OverlayProvider subscribes to IResponsiveService.ViewportChanged and re-renders the effective Side/Size/SwipeToClose when the viewport crosses MobileBreakpoint — works mid-flight (user rotates a tablet, sheet flips correctly).
// In any component:
@inject OverlayService Overlay
private async Task ShowResponsive()
{
await Overlay.ShowSheetAsync<MyForm>(
title: "Edit user",
side: Lumeo.Side.Right, // desktop default
size: SheetSize.Default,
options: new OverlayOptions
{
// Below 768px, switch to a fullscreen bottom sheet with swipe-down dismiss
MobileSheetSide = Lumeo.Side.Bottom,
MobileSize = OverlaySize.Full, // unified Size — drives Dialog & Sheet
MobileSwipeToClose = true,
// MobileBreakpoint defaults to 768 (md) — set to null to disable
});
}
If you need finer-grained mobile detection (e.g. to change the rendered content, not just overlay sizing), inject IResponsiveService directly. See the IResponsiveService API below.
IResponsiveService (2.1.3)
Reactive viewport/breakpoint service. One JS resize listener per circuit (debounced 100ms), Tailwind-v4-aligned Breakpoint enum, plus IsMobile/IsTablet/IsDesktop convenience flags and a ViewportChanged event for components that need to react to the live viewport.
| Member | Type | Description |
|---|---|---|
| Width | double | Current viewport width in CSS pixels (window.innerWidth). 0 until the first interop sync — call EnsureInitialisedAsync from OnAfterRenderAsync(firstRender: true) or subscribe to ViewportChanged. |
| Height | double | Current viewport height in CSS pixels. |
| Current | Breakpoint | Tailwind-aligned breakpoint. Values: Xs (<640), Sm ([640,768)), Md ([768,1024)), Lg ([1024,1280)), Xl ([1280,1536)), Xxl (>=1536). |
| IsMobile | bool | True when Current is Xs or Sm. Same boundary the default MobileBreakpoint=768 on OverlayOptions checks. |
| IsTablet | bool | True when Current is Md. |
| IsDesktop | bool | True when Current is Lg, Xl, or Xxl. |
| ViewportChanged | event Action<ViewportInfo> | Fires on every (debounced) resize. ViewportInfo carries Width, Height, Current. Unsubscribe in DisposeAsync. |
| EnsureInitialisedAsync() | ValueTask | Lazily attaches the JS resize listener + pulls the initial viewport. Call eagerly from OnAfterRenderAsync(firstRender: true) to avoid the first-render zero-value read. |
@inject IResponsiveService Responsive
@implements IAsyncDisposable
@if (Responsive.IsMobile)
{
<BottomNav />
}
else
{
<Sidebar />
}
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await Responsive.EnsureInitialisedAsync();
Responsive.ViewportChanged += OnVp;
}
}
private void OnVp(ViewportInfo vp) => InvokeAsync(StateHasChanged);
public ValueTask DisposeAsync()
{
Responsive.ViewportChanged -= OnVp;
return ValueTask.CompletedTask;
}
}AlertDialogOptions
| Property | Type | Default | Description |
|---|---|---|---|
| Title | string | "Are you sure?" | The dialog heading text. |
| Description | string? | null | Optional body text below the title. |
| ConfirmText | string | "Continue" | Label for the confirm button. |
| CancelText | string | "Cancel" | Label for the cancel button. |
| IsDestructive | bool | false | When true, the confirm button uses destructive styling. |