# Overlay Service

Source: https://lumeo.nativ.sh/components/overlay-service

# Overlay Service

A programmatic service for opening dialogs, sheets, drawers, and alert dialogs imperatively from code.

## Installation

.NET CLI PackageReference Lumeo CLI

dotnet add package Lumeo

One-time app setup (`AddLumeo()`, CSS & JS) is covered in the [installation guide](docs/introduction).

Preview Code

Dialog

Open Dialog

Open a dialog containing a dynamic component and await its result.

**Authoring components for the service.** When a component is opened via `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.

Preview Code

Sheet

Right Left Bottom

Open a sheet panel from any side with a dynamic component.

Preview Code

Drawer

Open Drawer

Open a bottom drawer with a dynamic component.

Preview Code

Alert Dialog

Confirm Action Delete Item

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.
