lotusui
A Go design system for desktop and mobile — one codebase, native apps. Web when you want it.
GitHub

Dialog

The one overlay primitive: dimmed scrim, width-capped card, caller-owned visibility.

A dimmed scrim over the entire window with a width-capped SurfaceCard centered on it. It wraps arbitrary content and knows nothing about what's inside; visibility stays with the caller — the isOpen/onClose contract. Don't call Layout when closed.

Installation

Use the module import (the default), or own the source: lotusui add vendors the component into your app and lotusui update keeps the copy mergeable — see Registry.

Go
go get github.com/ikaito-com/lotusui

# or vendor the source into your app:
go run github.com/ikaito-com/lotusui/cmd/lotusui add dialog

Usage

onClose controls backdrop dismissal: pass your close func to let a backdrop click dismiss, or nil to absorb outside clicks — for typed confirmations, anywhere an accidental dismissal costs more than it saves. Lay the dialog out at window constraints (your shell's top layer / portal): inside a content column it inherits that column's constraints — the "scrim only covers part of the window" bug this type exists to end.

Escape dismisses exactly like a backdrop click (both go through onClose, so absorb-only dialogs ignore it too). The first open animates on the shared clock — the scrim fades in while the card settles upward; call Appear() when your isOpen transitions closed→open to play the entrance again.

open demo ↗

Sizes

Width presets on the shared Size scale — 2XS 280dp through 2XL 840dp; Width stays as the free-form override. Each button below opens the dialog at that size.

open demo ↗

Close button

Dismissable dialogs (non-nil onClose) render the corner ✕ automatically; HideClose suppresses it when the footer carries the only exits — the demo opens without the ✕, and Save is the way out. A CUSTOM close control is any button calling your close func.

open demo ↗

Scrollable content

A tall dialog stops short of the window edges; longer content scrolls INSIDE — a height-capped list in the body, title fixed above.

open demo ↗

Responsive width

Stepped width against Theme breakpoints: Sizes overrides Size; Widths (dp) overrides both when set. Priority: Widths → Width → Sizes → Size. Resize with the dialog open.

open demo ↗

API

OptionTypeDescription
Appear()methodRestart the entrance animation — call on the closed→open transition.
HideCloseboolSuppress the corner ✕ on dismissable dialogs.
SizeSizeWidth preset: Size2XS 280dp … Size2XL 840dp (SizeMD, the default, is 480dp).
SizesResponsiveSizeStepped Size; when Set(), overrides Size.
Widthunit.DpFree-form width override; zero defers to Size/Sizes.
WidthsResponsiveDpStepped dp width; when Set(), wins over Width/Sizes/Size.
onClosefunc()Layout parameter — backdrop-click and Escape dismissal; nil absorbs without dismissing.
contentlayout.WidgetLayout parameter — arbitrary content; the dialog knows nothing about what's inside.

lotusui is a Go design system for native desktop and mobile — and the web when you want it. Docs demos are the real components (WebAssembly) — one gallery app, each Preview an iframe addressed by URL hash.