Dismiss handler: scrim tap, Esc, Cancel, or the close (X) button.
onConfirm *
() => void
n/a
Default-action handler: the confirm button + Enter.
title *
string
n/a
Accessible title; carries the dialog name (aria-labelledby).
confirmLabel
string
'Confirm'
Confirm-button label.
cancelLabel
string | null
'Cancel'
Cancel-button label. null hides Cancel (a single-action alert).
tone
'primary' | 'destructive'
'primary'
Emphasis of the default action: primary cyan or destructive red.
icon
'warning' | 'fork'
n/a
Optional leading header glyph key (warning for destructive, fork for branch).
confirmDisabled
boolean
false
Disable the confirm action (e.g. an unsatisfied form).
stage *
HTMLElement | null
n/a
The contained stage element, which gates rendering so the dialog never escapes it.
children *
React.ReactNode
n/a
Body: supporting text and/or a form field.
Parameter
Type
Default
Description
onDismissRequest *
() -> Unit
n/a
Invoked on scrim tap, the system back gesture, or Esc. Wire to the same handler as the Cancel button.
confirmButton *
@Composable -> Unit
n/a
The default action slot. Fill with a NockerlButton (PRIMARY, or DESTRUCTIVE for a delete).
dismissButton
@Composable (() -> Unit)?
null
The secondary action slot, typically a GHOSTNockerlButton labelled "Cancel". Omit for a single-action alert.
title
@Composable (() -> Unit)?
null
Heading slot. A Row with an Icon + Text gives the icon-header variant.
text
@Composable (() -> Unit)?
null
Body slot: supporting Text (and a Column with an OutlinedTextField for a form dialog).
properties
DialogProperties
DialogProperties()
Platform dialog behavior, such as dismiss-on-back and dismiss-on-outside.
SwiftUI presents dialogs as view modifiers bound to a Bool, not a component
with parameters. Voice uses the stock presenters; buttons carry semantics via
role.
Style
Type
Default
Description
.alert(_:isPresented:actions:message:)
modifier
n/a
A titled message with action buttons + an optional message. May contain a TextField for a short prompt.
A choice sheet for a destructive/irreversible action. titleVisibility: .visible shows the prompt as the title.
isPresented
Binding<Bool>
n/a
Drives presentation; set false from any action to dismiss. There is no explicit scrim/elevation parameter, since the system supplies them.
Button(role:)
.destructive | .cancel
n/a
Action emphasis. .destructive tints the confirm red; .cancel is the dismiss. The platform orders the buttons.
Dialog vs. bottom sheet
Reach for a dialog when the choice is short, blocking, and platform-neutral: a
confirm, an alert, or a one-field prompt that wants the user’s full attention,
centered over a scrim. Reach for the bottom sheet when
the surface is a longer, scrollable, thumb-reachable list of actions or settings on
mobile. Same scrim + focus-trap + Esc/scrim-dismiss vocabulary; different anchor
(centered card vs. bottom edge) and posture (decision vs. browse).
Cross-platform drift (tracked for reconciliation)
Custom vs. stock: Android centers a custom-styled Material AlertDialog
filled with NockerlButtons; Voice uses the stock SwiftUI .alert /
.confirmationDialog (no bespoke card), so the macOS scrim, radius, and button
order are system-supplied, not token-driven. Web is the intended original.
Icon header: web + Compose support a leading glyph in the title; SwiftUI
alerts have no icon slot.
Button order: web + Compose place Cancel ← Confirm (confirm trailing);
SwiftUI orders role-tagged buttons itself.