Skip to main content
On this pageFunctions

Ui/Dialog

Functions

close

functionsource
/** Programmatically closes the dialog. */
(model: Dialog.Model): UpdateReturn

descriptionId

functionsource
/** Returns the ID used for `aria-describedby` on the dialog. Apply this to your description element. */
(model: Dialog.Model): string

init

functionsource
/** Creates an initial dialog model from a config. Defaults to closed and non-animated. */
(config: InitConfig): Dialog.Model

open

functionsource
/** Programmatically opens the dialog. */
(model: Dialog.Model): UpdateReturn

titleId

functionsource
/** Returns the ID used for `aria-labelledby` on the dialog. Apply this to your title element. */
(model: Dialog.Model): string

update

functionsource
/** Processes a dialog message and returns the next model and commands. */
(
  model: Dialog.Model,
  message: {
    _tag: "RequestedOpen"
  } | {
    _tag: "RequestedClose"
  } | {
    _tag: "CompletedShowDialog"
  } | {
    _tag: "CompletedCloseDialog"
  } | {
    _tag: "GotAnimationMessage"
    message: {
      _tag: "Showed"
    } | {
      _tag: "Hid"
    } | {
      _tag: "AdvancedAnimationFrame"
    } | {
      _tag: "EndedAnimation"
    }
  }
): UpdateReturn

Types

InitConfig

typesource
/** Configuration for creating a dialog model with `init`. */
type InitConfig = Readonly<{
  focusSelector: string
  id: string
  isAnimated: boolean
  isOpen: boolean
}>

RenderInfo

typesource
/**
 * Render-time payload published to the consumer's `toView`.
 * 
 *  - `dialog`: attributes for the native `<dialog>` element. Carries
 *    the id, ARIA labelling, `open` prop, positioning style, and the
 *    `OnCancel` handler that wires Escape to `RequestedClose`. The
 *    consumer MUST render an `h.dialog(...)` element so the framework's
 *    `showModal`/`close()` commands can target it.
 *  - `backdrop`: attributes for the backdrop element. Includes the
 *    Animation data attributes and the `OnClick` handler that closes
 *    the dialog on outside-click (suppressed while a leave animation
 *    is in progress).
 *  - `panel`: attributes for the panel element. Includes the panel id
 *    (`${model.id}-panel`) and the Animation data attributes.
 *  - `isVisible`: derived from `isOpen` and the Animation
 *    `transitionState`. The consumer renders backdrop + panel only
 *    while this is true.
 */
type RenderInfo = Readonly<{
  backdrop: ReadonlyArray<ChildAttribute>
  dialog: ReadonlyArray<ChildAttribute>
  isVisible: boolean
  panel: ReadonlyArray<ChildAttribute>
}>

ViewInputs

typesource
/** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs` field. */
type ViewInputs = Readonly<{
  toView: (render: RenderInfo) => Html
}>

Constants

CloseDialog

constsource
/** Calls `close()` on the native dialog element and unlocks page scroll. */
const CloseDialog: CommandDefinitionWithArgs<"CloseDialog", {
  id: String
}, Effect<{
  _tag: "CompletedCloseDialog"
}, never, never>>

Closed

constsource
/**
 * Sent once the dialog has transitioned to closed. Programmatic
 *  `Dialog.close` on an already-closed model is a no-op that does not
 *  re-emit; calling close while a leave animation is in progress is
 *  also a no-op.
 */
const Closed: CallableTaggedStruct<"Closed", {}>

CompletedCloseDialog

constsource
/** Sent when the close-dialog command completes. */
const CompletedCloseDialog: CallableTaggedStruct<"CompletedCloseDialog", {}>

CompletedShowDialog

constsource
/** Sent when the show-dialog command completes. */
const CompletedShowDialog: CallableTaggedStruct<"CompletedShowDialog", {}>

GotAnimationMessage

constsource
/** Wraps an Animation submodel message for delegation. */
const GotAnimationMessage: CallableTaggedStruct<"GotAnimationMessage", {
  message: Union<[CallableTaggedStruct<"Showed", {}>, CallableTaggedStruct<"Hid", {}>, CallableTaggedStruct<"AdvancedAnimationFrame", {}>, CallableTaggedStruct<"EndedAnimation", {}>]>
}>

Message

constsource
/** Union of all messages the dialog component can produce. */
const Message: S.Union<[typeof RequestedOpen, typeof RequestedClose, typeof CompletedShowDialog, typeof CompletedCloseDialog, typeof GotAnimationMessage]>

Model

constsource
/** Schema for the dialog component's state, tracking its unique ID, open/closed status, animation support, and animation lifecycle phase. */
const Model: Struct<{
  animation: Struct<{
    id: String
    isShowing: Boolean
    transitionState: Literals<readonly ["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>
  }>
  id: String
  isAnimated: Boolean
  isOpen: Boolean
  maybeFocusSelector: Option<String>
}>

Opened

constsource
/**
 * Sent once the dialog has transitioned to open. Fires after `update`
 *  has processed `RequestedOpen` and `isOpen` reflects the new state.
 *  Programmatic `Dialog.open` on an already-open model is a no-op that
 *  does not re-emit.
 */
const Opened: CallableTaggedStruct<"Opened", {}>

OutMessage

constsource
/** Union of out-messages the dialog component can produce. */
const OutMessage: Union<readonly [CallableTaggedStruct<"Opened", {}>, CallableTaggedStruct<"Closed", {}>]>

RequestedClose

constsource
/** Sent when the dialog should close (Escape key, backdrop click, or programmatic). */
const RequestedClose: CallableTaggedStruct<"RequestedClose", {}>

RequestedOpen

constsource
/** Sent when the dialog should open. Triggers the showModal command. */
const RequestedOpen: CallableTaggedStruct<"RequestedOpen", {}>

ShowDialog

constsource
/** Locks page scroll and calls `showModal()` on the native dialog element. */
const ShowDialog: CommandDefinitionWithArgs<"ShowDialog", {
  id: String
  maybeFocusSelector: Option<String>
}, Effect<{
  _tag: "CompletedShowDialog"
}, never, never>>

view

constsource
/**
 * Renders a headless dialog component backed by the native `<dialog>`
 *  element with `showModal()`.
 */
const view: SubmodelView<Dialog.Model, {
  _tag: "RequestedOpen"
} | {
  _tag: "RequestedClose"
} | {
  _tag: "CompletedShowDialog"
} | {
  _tag: "CompletedCloseDialog"
} | {
  _tag: "GotAnimationMessage"
  message: {
    _tag: "Showed"
  } | {
    _tag: "Hid"
  } | {
    _tag: "AdvancedAnimationFrame"
  } | {
    _tag: "EndedAnimation"
  }
}, Readonly<{
  toView: (render: RenderInfo) => Html
}>>

Stay in the update loop.

New releases, patterns, and the occasional deep dive.


Built with Foldkit.

© 2026 Devin Jameson