In late 2019 we released a new app surface for collecting rich user input and displaying dynamic information using Block Kit — modals. Modals are the replacement for dialogs, an outmoded feature that allowed apps to collect simple, static input.
Modals have the ability to use Block Kit interactive components like datepickers and multi-select menus, as well as the standard input options available to dialogs. Modals can also be updated dynamically, and chained together to form deep workflows.
Dialogs will continue to work for the time being, but apps using them cannot avail any of these new modal features.
This guide is intended for developers of existing Slack apps that use dialogs. It will provide information on how to migrate your dialogs to modals and introduce you to new capabilities and components that modals provide.
Mapping dialogs to modals is fairly straight-forward if you plan to keep the same layout and user flow. However, it’s highly recommended you take the opportunity to explore the new Block Kit components and additional functionality available to your app within modals.
Modals are built with blocks that can be mixed and stacked to design surface areas customized to your app. Modals can use Block Kit components that map directly to dialog elements. Blocks such as
input and elements like
select menus replicate fields that could be added to dialogs.
There are also additional blocks that your app can use to improve the user experience and simplify the payload your app receives on submission:
Date pickers allow your app to collect dates through a calendar interface. This provides a better user experience than text fields, and it standardizes date formats that your app may receive.
Multi-select menus are new dropdown menus similar to select menus. You probably guessed by the name, but they allow users to make multiple selections rather than being limited to just one.
You also have access to the entire suite of blocks, like
image blocks that allow you to display static content, or
context blocks that help you organize information.
To get started with blocks read our building with blocks guide, or to see all available blocks check out our layout block reference.
dialog.open, with modals you call
views.open to open a modal and populate it with a view object.
The response will be similar to dialogs, though it will also include a view ID which you can use to update an existing modal. Read our documentation on creating modals to learn more and see an example.
Modals are containers that can hold a stack of one to three views. Each view is generated using a payload that defines a Block Kit layout, view functionality, and some state variables to track within the view.
Within an individual modal, views can be created and pushed onto the stack, or updated while in the stack. Complete our guide to using modals to learn how to manipulate views and modals.
Block Kit Builder is a prototyping tool that allows you (or a designer on your team) to quickly design surface areas for your app. There’s a dedicated mode to design modals which reveals blocks exclusive to modals, like the
The Builder also provides templates with common workflows to get started, editable JSON to plug into your app, and example interactive payloads to examine what your app will receive.
You've read about the details of new modals functionality that apps have access to. Now let's get into the specific differences to account for in your app when you replace dialogs with modals.
The content of a view is composed using a
blocks array rather than the
elements equivalent in dialogs. The
blocks array contains a collection of blocks from the Block Kit framework. Although dialogs could only contain 10 elements, modals can contain up to 100 blocks.
Each dialog element has an equivalent that you can use to define and design the views within your modals:
input blocks replace the dialog's text element and textarea. The
input block has an optional
multiline flag that determines whether it should be one line (the text element equivalent) or multiple lines (the textarea equivalent).
An important difference with
input blocks in a view is that when any
input blocks are in your
blocks array, you must pass a
submit element. When you pass a
submit element, you will receive the input's values when a user submits the view. This is discussed more in the accessing input values in modals section.
select menus and
multi-select menus replace the dialog's select element. Select menus can be within
input blocks, or as accessories in
To see all available blocks, see our layout block reference.
While view objects are still identified using a
callback_id, interactive components within a view use
action_ids. These are sent when interactive components are used in a view, or when a view is submitted (described below).
block_id is specified in blocks. It can be used to identify the parent block of the source interactive component used in a
view_submission interaction. If you don’t specify a
block_id, one will be automatically generated for the block.
action_id is specified in the interactive component. It can be used to identify the parent block of the source interactive component used in a
view_submission interaction. If you don’t specify an
action_id, one will be automatically generated for the element.
For elements within
input blocks, the values will be contained in a
view_submission payload that will be sent to your app’s Request URL when a user clicks a submit button.
view_submission payload, there will be a
state object that contains the values for all
input blocks, stored using their
To learn more about view submissions, read the section on handling
If you have
select menus or other interactive components within an
section block, the values will not be contained in the
view_submission payload. You’ll handle these events in the same way as all Block Kit interactive components.
For more information on handling non-input interactions in modals, read the modals documentation.
Within dialogs, you respond to
dialog_submission events with either a 200 OK or an array of errors. With modals, your app will receive a
view_submission event. After receiving this event, you have 3 seconds to respond with a valid
Similar to dialogs,
response_actions allow your app to close the modal or display errors. If you just want to close the modal, nothing will change — you’ll just respond with a 200 OK. For other options, you’ll respond with the
response_action corresponding to the action you want to take.
With modals, you also have the option to use a
response_action to update a view, push a new view, or close all views. To learn more about using
response_actions read the handling submission section of the documentation.
When opening or updating a view, you may optionally use the
private_metadata string to pass additional data. This is equivalent to the
state string in dialogs, and has the same 3000 character limit.
private_metadata string will never be sent to clients. It is only returned in
When a dialog is submitted, your app receives an HTTP request.
dialog_submission events contained a
response_url that allowed you to post a message tied to the channel the dialog was initiated from. However, modals don't rely on a channel context. This means that the
view_submission event will not contain a
If you want to send a message into the channel the modal was opened from, you can pass the channel ID in the
private_metadata string. This will be included in
view_submission events, and you can access this value to send a message to channel using
chat.postMessage. Another option is to DM the user verifying that the modal they filled out was successfully submitted.
Note that to call
chat.postMessage, you’ll need to add the
chat:write scope to your app if you aren’t using a bot user.
Instead of defining text as a flat field, Block Kit uses text objects. Using text objects you can define the actual text content, as well as the formatting method (mrkdwn or plain_text) in the same place. Read the reference guide for text objects to see an example and full details.
Note that in view objects, most text objects only accept
plain_text objects. Read the reference guide for view objects for more information.
When creating a view object, you can pass a
notify_on_close flag that indicates that Slack will send you a
view_closed event. This is equivalent to the
notify_on_cancel flag in dialogs.
Read the reference guide for view objects for more information and examples.
Congratulations! 🎉 If you made it to this point, hopefully you were successfully able to migrate your app’s dialogs to modals. If you want to level-up your app’s user experience, here are some next steps:
If you haven’t migrated your messages to use Block Kit, read our migration guide for messages.
Explore all of the available Blocks and elements in Block Kit. Discover new interactive components and static elements that will allow you to create cleaner and more compelling workflows.
Use the Block Kit Builder to quickly play with blocks, or use templates as a starting point for common design patterns in Slack apps.