Native dialogs and actions
Use the ui capability to add host-rendered dialogs, text panels, notifications, overlays, and composer attachment-menu actions. Core owns labels, focus management, scrolling, cancellation, and theme styling.
Open a form from an action
Section titled “Open a form from an action”The following snippet registers an action and stores its disposer in the lifecycle cleanup array:
cleanup.push( await api.ui.registerAttachmentAction( { id: "greeting", label: "Show greeting" }, async () => { const values = await api.ui.openDialog( { title: "Greeting", description: "Choose the text to display.", submitLabel: "Show", sections: [ { title: "Message", controls: [ { key: "message", label: "Message", kind: "text", maxLength: 100, }, ], }, ], }, (values) => typeof values.message === "string" && values.message.trim() ? undefined : "Enter a message", ); if (values && typeof values.message === "string") { await api.ui.notify(values.message); } }, ),);The validator returns an error string to keep the dialog open, or undefined to accept. The dialog promise resolves to values or undefined on dismissal. Act after successful completion; do not send messages or save data in the validator.
Controls and presentation
Section titled “Controls and presentation”Control kinds are text, url, number, textarea, and checkbox. Keys must be unique. Sections can use repeatKey and maxRows for up to 25 repeated rows.
Use registerPanel for plain text, notify for a concise notice, and setOverlay for bounded geometry with optional action text. setOverlay(null) removes an overlay.
An attachment action can specify submenu: { id, label }. Groups are plugin-scoped and disappear when their last action is removed. Composer actions differ from posted-file actions.
Catch operation failures in your callback and use a short user-facing error. Dispose registrations in stop; do not retain callbacks from an old instance.
