From 4c0f26e66c62c9119e72d0842c024bda78858172 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 29 Jun 2026 15:53:33 -0600 Subject: [PATCH 1/2] update documentation for stacked dialogs --- .../plugins/interactive-dialogs/_index.md | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/site/content/integrate/plugins/interactive-dialogs/_index.md b/site/content/integrate/plugins/interactive-dialogs/_index.md index 1245129977..9863f7bb82 100644 --- a/site/content/integrate/plugins/interactive-dialogs/_index.md +++ b/site/content/integrate/plugins/interactive-dialogs/_index.md @@ -12,6 +12,8 @@ Integrations open dialogs by sending an `HTTP POST`, containing some data in the Moreover, [plugins]({{< ref "/integrate/plugins/using-and-managing-plugins" >}}) can trigger a dialog based on user actions. For instance, if a plugin adds a button in the channel header, clicking that button may open a dialog. +From Mattermost v11.10, dialogs can be stacked: an [`action_button`](#action-button-elements) element inside a dialog lets a user open a child dialog on top of the current one. Up to three dialogs may be open at once; any request to open a dialog beyond this limit is silently ignored by the client. + Here is an example of what a dialog looks like for creating a Jira issue within the Mattermost user interface: ![image](interactive-dialog-example.png) @@ -68,6 +70,7 @@ Each dialog supports elements for users to enter information. - `radio`: Radio button option. Use this to quickly select an option from pre-selected choices. - `date`: Date picker field. Use this for selecting dates without time information. - `datetime`: Date and time picker field. Use this for selecting both date and time with timezone support. +- `action_button`: Clickable button that opens a child (stacked) dialog. Use this to branch into a follow-up dialog without submitting the current one. (Minimum server version 11.10.) Each element is required by default, otherwise the client will return an error as shown below. Note that the error message will appear below the help text, if one is specified. To make an element optional, set the field `"optional": "true"`. @@ -621,6 +624,69 @@ The `datetime_config` object groups date/datetime configuration into a single ne - `"time_interval": 60` creates options: 00:00, 01:00, 02:00, 03:00, etc. - Invalid: `"time_interval": 7` (7 is not a divisor of 1440) +### Action button elements +##### Minimum Server Version: 11.10 + +Action button elements render a clickable button inside a dialog. Instead of submitting the current dialog, clicking the button asks your integration to open a *child* dialog that is stacked on top of the current one. Use this to branch into a follow-up workflow (for example, "Add another item" or "Configure advanced options") while preserving the dialog the user is already working in. + +```json +{ + "display_name": "Add attachment", + "name": "add_attachment", + "type": "action_button", + "action_button": { + "url": "https://your-mattermost-server.com/plugins/your-plugin-id/api/attach", + "context": { + "action": "open_attachment_dialog" + } + } +} +``` + +The full list of supported fields is included below: + +| Field | Type | Description | +|-----------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------| +| `display_name` | String | Display name shown on the button. Maximum 24 characters. | +| `name` | String | Name of the field element used by the integration. Maximum 300 characters. You should use unique `name` fields in the same dialog. | +| `type` | String | Set this value to `action_button` for an action button element. | +| `action_button` | Object | Action button configuration. Required for this element type. See the fields below. | + +The `action_button` object supports: + +| Field | Type | Description | +|-----------|--------|---------------------------------------------------------------------------------------------------------------------------------------| +| `url` | String | The URL the action is sent to when the button is clicked. Required. Must be a valid lookup URL — an HTTPS URL or a `/plugins/` path. | +| `context` | Object | (Optional) String map of arbitrary key/value pairs forwarded to your integration when the button is clicked. Use this to identify which button was pressed or to carry state. | + +Action button elements are not input fields: their values are never included in the dialog submission payload, and they are not subject to the required/optional validation applied to other elements. + +#### Action button flow + +When a user clicks an action button, the Mattermost client sends an `HTTP POST` to the `/api/v4/actions/dialogs/execute` endpoint. The server validates the request, generates a new trigger ID, and forwards the button's `context` to the `url` configured on the button. The payload your integration receives is a `PostActionIntegrationRequest`: + +```json +{ + "type": "dialog_action", + "trigger_id": "", + "user_id": "", + "user_name": "", + "channel_id": "", + "channel_name": "", + "team_id": "", + "team_name": "", + "context": { + "action": "open_attachment_dialog" + } +} +``` + +Use the `trigger_id` from this payload to [open a child dialog](#open-a-dialog) — send an `HTTP POST` to `/api/v4/actions/dialogs/open` exactly as you would for a top-level dialog. The child dialog is displayed stacked on top of the dialog the user clicked the button in. + +{{}} +Up to three dialogs may be open at once. If three dialogs are already open, the request to open a further child dialog is silently ignored by the client, so design your workflows to stay within this limit. +{{}} + ## Dialog submission When a user submits a dialog, Mattermost will perform client-side input validation to make sure: @@ -637,7 +703,7 @@ The submission payload sent to the integration is: "state": "", "user_id": "", "channel_id": "", - "team_id": "", + "team_id": "", "submission": { "some_element_name": "", "some_other_element": "" @@ -646,6 +712,10 @@ The submission payload sent to the integration is: } ``` +{{}} +For the `/api/v4/actions/dialogs/submit`, `/api/v4/actions/dialogs/lookup`, and `/api/v4/actions/dialogs/execute` endpoints, the `team_id` forwarded to your integration is now always derived by the server from the channel the dialog was opened in, rather than from the value supplied by the client. Any client-supplied `team_id` is ignored. For direct (DM) and group (GM) message channels — which do not belong to a team — `team_id` is sent as an empty string. If your integration previously relied on a client-supplied `team_id` for team-specific logic, update it to use this channel-derived value (and to handle the empty case for DM/GM channels). +{{}} + Optionally, the dialog can send an event back to the integration if `notify_on_cancel` parameter is set to `true`. If this happens, `cancelled` will be set to `true` on the above payload, and `submission` will be empty. Moreover, Mattermost also allows the integration itself to perform input validation. This can be done by responding to the dialog submission request with a JSON body containing an `errors` field. The `errors` field can contain a JSON object, mapping input field names to string error messages you would like to display to the user. For example, if you have a field named `num_between_0_and_10`, you can enforce the user to enter a number between 0 and 10 by returning the following response body if the condition isn't satisfied: From d647d75f5db39e650846a9622821ebcbce3f0618 Mon Sep 17 00:00:00 2001 From: Scott Bishel Date: Mon, 29 Jun 2026 16:05:18 -0600 Subject: [PATCH 2/2] Fix markdown heading hierarchy in action button elements section --- site/content/integrate/plugins/interactive-dialogs/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/integrate/plugins/interactive-dialogs/_index.md b/site/content/integrate/plugins/interactive-dialogs/_index.md index 9863f7bb82..dbf7cc7001 100644 --- a/site/content/integrate/plugins/interactive-dialogs/_index.md +++ b/site/content/integrate/plugins/interactive-dialogs/_index.md @@ -625,7 +625,7 @@ The `datetime_config` object groups date/datetime configuration into a single ne - Invalid: `"time_interval": 7` (7 is not a divisor of 1440) ### Action button elements -##### Minimum Server Version: 11.10 +#### Minimum Server Version: 11.10 Action button elements render a clickable button inside a dialog. Instead of submitting the current dialog, clicking the button asks your integration to open a *child* dialog that is stacked on top of the current one. Use this to branch into a follow-up workflow (for example, "Add another item" or "Configure advanced options") while preserving the dialog the user is already working in.