Skip to main content

Modals

A modal is an alert box, pop-up, or dialog box. Modals capture and maintain focus within Slack until the user submits or dismisses the modal. This makes them a powerful piece of app functionality for engaging with users. Modals are available for both Bolt apps and Deno Slack SDK apps.

You can use modals with other app surfaces such as messages and Home tabs.

For example, you could have an app present a task dashboard that resides in the app's Home tab. A user clicks a button to add a task, and is presented with a modal to input some plain text and select from a list of categories. Upon submitting, a message is sent to a triage channel in the Slack workspace, where another user can click a button to claim the task.

If you've used our outmoded dialogs in your apps, check out our guide to upgrading dialogs to modals.

Understanding the lifecycle of a modal

Each modal consists of some standardized UI elements, including a title, an x button to dismiss the modal, and a cancel button, that wrap around a focused space, known as the modal's view.

To generate a modal, an app composes an initial view. Apps can compose view layouts and add interactivity to views using Block Kit.

A modal can hold up to 3 views at a time in a view stack. There is only ever a single view visible at a given moment, but the view stack can retain previous views, returning to them with their prior state still intact. An app can push new views onto a modal's view stack or update an existing view within that stack, including the currently visible view.

But first, there is a user interaction.

Interactions happen with one of an app's entry points. As a result, the app is sent an interaction payload containing a special trigger_id. The app then composes an initial view (view A in the diagram below).

A diagram explaining the view stack through the lifecycle of a modal

The user interacts with an interactive component in view A. This sends another interaction payload to the app. The app uses the context from this new payload to update the currently visible view A with additional content.

The user interacts with another interactive component in view A, and another interaction payload is sent to the app. The app uses the context from the new payload to push a new view (view B) on to the modal's view stack, causing it to appear to the user immediately. View A remains in the view stack, but is no longer visible or active. The user enters some values into input blocks in view B, and clicks the view's submit button. This sends a different type of interaction payload to the app.

The app handles the view submission and responds by clearing the view stack.

As described, the view stack can be manipulated in a few ways over the course of a modal's lifetime:

  • Updating a view. This can happen at any time while the modal is open. Updates can change the contents and layout of the view. A view update should normally only happen in response to the use of interactive components or inputs gathered in the view.
  • Adding a new view. Apps can push a new view onto the modal's view stack. This causes the new view to immediately become visible. Three views can exist in the view stack at any one time. Again, pushing a new view should normally only happen in response to the use of interactive components or inputs gathered in one of the previous views.
  • Closing a view. When a view contains inputs, users can submit the modal when that view is visible. The app can then either close that specific view or all views in the view stack. Closing a single view removes it from the view stack and causes the next view in the stack to appear again. Closing all views will close the modal entirely.

Preparing your app

First things first: follow the Quickstart guide to create an app. Once completed, open the app settings, find the Install App tab in the sidebar, and copy the Bot User OAuth Token; we'll use that in a bit.

Composing modal views

Before opening a modal, you'll need to define a view object to structure the layout of the initial view. The view object is a JSON object that defines the content populating this initial view and some version of metadata about the modal itself.

Defining modal view objects

Modal view objects are used within the following Web API methods:

Each of these methods requires a modal view object argument, which contains the fields outlined in the Modal views reference doc.

The layout of a view is composed using Block Kit's visual and interactive components, including special input blocks to gather user input. These visual components are all contained within the blocks field of the view object. Read our comprehensive guide to composing layouts with Block Kit to see how the blocks array should be formed.

When creating a view, set a unique block_id for each block and a unique action_id for each block element. This will make it much easier to track the possible values of those block elements when they are returned in view_submission payloads.

Gathering user input

In order to capture user input, a special type of Block Kit component is available called an input block. An input block can hold a plain-text input, a select menu, or a multi-select menu. Plain-text inputs can be set to accept single or multi-line text. Input blocks require that you include the submit field when defining your view. See the full input block definition in the input block reference.

Pre-filling a modal with the approximate information will allow the user to review the information rather than needing to fill it out manually before submitting. Use the initial_value / initial_options property to prefill the modal. For example, if an app is used for gathering information for submitting an issue, the app could send a message with a button that, when clicked, opens a modal for data collection. In that modal, you can use the plain-text input for fields and pre-populate them with user-provided data using the initial_value field.

Once you've created your blocks layout, add it to your view object payload. Here's an example view that we'll use:

{
"type": "modal",
"callback_id": "modal-identifier",
"title": {
"type": "plain_text",
"text": "Just a modal"
},
"blocks": [
{
"type": "section",
"block_id": "section-identifier",
"text": {
"type": "mrkdwn",
"text": "*Welcome* to ~my~ Block Kit _modal_!"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "Just a button",
},
"action_id": "button-identifier",
}
}
],
}

View in Block Kit Builder

Opening modals

To open a new modal, your app must possess a valid, unexpired trigger_id, obtained from an interaction payload. Your app will receive one of these payloads, and therefore a trigger_id, after a user invokes one of the app's entry points. If your app doesn't have one of these entry point features enabled, the app will not be able to open a modal. The trigger_id requirement ensures that modals only appear when apps have the express permission of a user.

A trigger_id will expire 3 seconds after it's sent to your app, so you’ll want to use it quickly.

Once in possession of a trigger_id, your app can call the views.open API method with the view payload you created above and the access token you saved from the app settings:

POST https://slack.com/api/views.open
Content-type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN_HERE
{
"trigger_id": "156772938.1827394",
"view": {
"type": "modal",
"callback_id": "modal-identifier",
"title": {
"type": "plain_text",
"text": "Just a modal"
},
"blocks": [
{
"type": "section",
"block_id": "section-identifier",
"text": {
"type": "mrkdwn",
"text": "*Welcome* to ~my~ Block Kit _modal_!"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "Just a button"
},
"action_id": "button-identifier"
}
}
]
}
}