Wow, what a beautifully constructed message! Wouldn’t it be great to create a bot to keep your new hires informed of what they should be doing in their first days with the company, in a clear, organized message sent directly to them? Yes, the answer is yes, it would be great.
In this tutorial, we’ll walk through how to structure the Block Kit blocks to achieve this message, while explaining the ins and outs of rich text. To learn how to incorporate these blocks in messages and modals, read up on Building with Block Kit.
If you’d like to follow along with the code already constructed, you can check it out here in Block Kit Builder.
Building with Block Kit is layering one block on after another, all independent pieces with their own details within their structure. The main blocks of this message are:
Block Type | Description of block in image |
---|---|
header |
Onboarding Week 1 |
context |
Line of text in smaller, lighter font providing context for the message |
section |
Text and accessory image |
divider |
Horizontal line |
rich_text |
Company business header, bulleted and ordered lists |
divider |
Horizontal line |
rich_text |
Read about our culture header and bullet list |
divider |
Horizontal line |
rich_text |
Inspirational quote of the day section |
input |
Component for text data collection |
actions |
Button |
Now let's step through these individually.
To give the user context of the overall content of the message, we provide a header, a context sentence, and an introductory blurb.
The header block is straightforward. The only option for the text
object's type
field is plain_text
, so if you wanted to add emoji here, it would need to be in a separate component. We'll explore adding emoji later.
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Onboarding Week 1"
}
},
The context block is a bit of text that gives the user context for the rest of the message. It is shown in smaller text that is grey instead of black. A context block's elements
property is an array of objects, either image
or text
. Here we are using text
. It's important to know that text
in a context block cannot be rich text, only mrkdwn
or plain_text
.
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "Hello there! This is a weekly reminder of what you should be doing during onboarding."
}
]
},
The section block provides an introductory blurb with a fun gif welcoming the user to the team. While we strongly encourage rich text to markdown formatting, we've used a section
block here (which offers only markdown formatting, not rich text) for use the of the accessory image. The same content could be achieved by creating a rich_text
block followed by an image
block, but they would be stacked, as opposed to side by side as shown in this example. Also note that we use a link to a gif, and while it is not animated in this screenshot, it will be in a message (and even in the Block Kit Builder preview). After this section, we'll use rich text for formatting text.
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Welcome aboard!*\n :eye: :lips: :eye:\n\nHere are some things you should do in week 1.\n Of course, reach out to your manager with any questions."
},
"accessory": {
"type": "image",
"image_url": "https://media.giphy.com/media/Ae7SI3LoPYj8Q/giphy.gif",
"alt_text": "One of us"
}
}
The divider block is simply a horizontal line to provide a visual break in content.
The main content of this message is comprised of a few visual sections: "Company business", "Read about our culture", and "Inspirational quote of the day".
The entirety of the "Company business" section of this message is contained within a single rich_text
block. The flexibility of formatting is possible through many element types we'll dive into deeper here.
Within the top-level rich_text
block, we have a rich_text_section
, a rich_text_list
, and another rich_text_list
. Think of each rich_text_section
as a single line of text. This may be deceiving, given that it holds an array of elements. However, structuring it as an array of elements provides maximum flexibility with styling each element (which can be as tiny as a single character), as well as ease in parsing. For instance, looking at the rich_text_section
, we see two elements: an emoji
and a text
element. While these are different elements in the array, they appear on the same line.
The rich_text_section
block allows for elements of the following types, providing many possibilities for styling: text
, link
, emoji
, user
, user_group
, and channel
.
Our text object has a style
field, in which we specify bold
. Other style options include italic
, strike
, and code
. You apply them in the same manner as bold
is shown here.
Moving on to the lists, you'll see in the code that we have two lists. One is the bulleted list, containing the first three bullets, and the second is an ordered list containing the last two elements. Notice how the rich_text_list
is comprised of another elements
array. This again allows for flexibility in the types of text you want to show, whether that be links, quotes, code snippets, or simply formatted text. To achieve the style of linking one word in a line of plain text, we use a rich_text_section
, remembering that each rich_text_section
is read as a single line of text.
To achieve the nested list that is part of the third bullet point, we simply create another rich_text_list
below the prior one and set the indent
property to 1. To indent a list further, you keep increasing the number by one to create deeply nested lists.
This section ends with another divider block.
{
"type": "rich_text",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "emoji",
"name": "office"
},
{
"type": "text",
"text": " Company business",
"style": {
"bold": true
}
}
]
},
{
"type": "rich_text_list",
"style": "bullet",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "text",
"text": "Fill out your W-2"
}
]
},
{
"type": "rich_text_section",
"elements": [
{
"type": "text",
"text": "Enroll in "
},
{
"type": "link",
"text": "benefits",
"url": "https://salesforcebenefits.com"
}
]
},
{
"type": "rich_text_section",
"elements": [
{
"type": "text",
"text": "Fill out your Slack profile, including:"
}
]
}
]
},
{
"type": "rich_text_list",
"style": "ordered",
"indent": 1,
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "text",
"text": "Time zone"
}
]
},
{
"type": "rich_text_section",
"elements": [
{
"type": "text",
"text": "Pronouns"
}
]
}
]
}
]
},
The entirety of the "Read about our culture" section is also contained within a single rich_text
block. Let's look at how to format links in a list like the ones shown in this example.
Again within this block we see it is constructed using a rich_text_section
and a rich_text_list
. Unlike the prior section, we have decided to link the entire text line of the bullet, which can be done using the text
property of the link
element, instead of breaking it into multiple link
and text
elements.
This section ends with another divider block.
{
"type": "rich_text",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "emoji",
"name": "green_book"
},
{
"type": "text",
"text": " Read about our culture",
"style": {
"bold": true
}
}
]
},
{
"type": "rich_text_list",
"style": "bullet",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "link",
"text": "Four tips for building a digital first culture",
"url": "https://slack.com/blog/collaboration/four-tips-build-digital-first-culture"
}
]
},
{
"type": "rich_text_section",
"elements": [
{
"type": "link",
"text": "6 simple ways to foster a positive hybrid work environment",
"url": "https://slack.com/blog/collaboration/ways-foster-positive-work-environment"
}
]
}
]
}
]
},
While the header and emoji of the last section of content also use the rich_text
block, the following rich text element is different: the rich_text_quote
. Using this element creates the vertical bar to the left of the text that indicates it is a quote, similar to how it is shown in messages in the Slack client or app.
The next piece is an input
block, which allows collection of data, in this case, a quote, from the user that can be stored and recalled again at a later date.
The final block is the actions
block, which is the call to action after the user submits their favorite quote — they push the button, letting the app know the action has been completed and the data is submitted. Read more about button function on the Block elements & interactive components reference page. We've added a block_id
for both the input
and actions
block in order to reference them later. When a block_id
is not explicitly added for a block, one will be automatically generated.
{
"type": "rich_text",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "emoji",
"name": "speech_balloon"
},
{
"type": "text",
"text": " Inspirational quote of the day",
"style": {
"bold": true
}
}
]
},
{
"type": "rich_text_quote",
"elements": [
{
"type": "text",
"text": "Having no destination I am never lost. - Ikkyū."
}
]
}
]
},
{
"type": "input",
"block_id": "quote_input_block",
"element": {
"type": "plain_text_input"
},
"label": {
"type": "plain_text",
"text": ":envelope: Enter your favorite quote, to be shared with future hires like you:",
"emoji": true
}
},
{
"type": "actions",
"block_id": "submit_button_action_block",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Submit"
},
"value": "submit",
"action_id": "button_1"
}
]
}
This concludes our guide on how to construct a beautiful message with Block Kit! We hope you will continue to explore all that blocks have to offer in Block Kit Builder and by reviewing the material below.
Check out these articles to expand your knowledge and skills of Block Kit:
Another tool to help you in your rich text journey is the Slack Developer Tools Inspect tool. Once installed, you can click the kebab (or three dots) menu on the upper-right of any message in Slack, then click "more message shortcuts." Search for the Inspect tool and click on it. This tool shows you the json
behind any given message in Slack, which helps you understand how blocks are used to construct them. Magic. ✨