Surfaces
Render blocks as a Slack message, a modal or a Home tab.
Slack shows blocks on three surfaces: messages, modals and the App Home tab. Each has its own component, and each lays the same blocks out the way Slack does on that surface.
| Component | Slack surface | Takes |
|---|---|---|
<Message> |
A message in a channel | blocks, or a whole message object |
<Modal> |
A modal opened with views.open |
A modal view |
<HomeTab> |
The App Home tab, published with views.publish |
A home view |
<View> |
Either of the two above | Any view; picks <Modal> or <HomeTab> from its type |
Message
<Message> draws the message chrome (app avatar, name, APP badge and time) around its blocks.
import { Message } from "@nkootstra/block-kit";
<Message
app={{ name: "Deploy Bot", iconUrl: "/deploy-bot.png" }}
blocks={[{ type: "section", text: { type: "mrkdwn", text: "Deployed *api@4.2.0* :rocket:" } }]}
/>;
blocks?AnyBlock[]
The blocks to render.
AnyBlock[]text?string
Fallback text. Slack shows it only when the message has no blocks, and so does this.
stringapp?{ name: string; iconUrl?: string }
The app the message is from. Without `iconUrl`, the avatar shows the name's first letter.
{ name: string; iconUrl?: string }{ name: "Block Kit Preview" }ts?string | number
The message timestamp in seconds, as in Slack's `ts`.
string | numberThe time the component mountedtimeZone?string
IANA zone for the displayed time.
stringThe viewer's zonemessage?SlackMessageLike
A whole Slack message object. See below.
SlackMessageLikechannelId?string
The channel the message is in, sent in the `container` of `block_actions` payloads.
stringisEphemeral?boolean
Show Slack's “Only visible to you” marker.
booleanfalseMessage objects
When you already have a message from Slack’s API, say from conversations.history, pass it as message. It supplies the blocks, text, timestamp and sender (username, icon_url, icon_emoji or bot_profile), and renders what surrounds them: legacy attachments, reactions, the thread summary and the (edited) marker.
const { messages } = await slack.conversations.history({ channel: "C0RELEASES", limit: 1 });
<Message message={messages[0]} channelId="C0RELEASES" />;
Attachments
Legacy attachments render with their colour bar, author, title, fields, image and footer. An attachment can also hold blocks.
Ephemeral messages
Ephemeral messages, posted with chat.postEphemeral, carry Slack’s “Only visible to you” marker:
<Message isEphemeral blocks={blocks} />
Modal
<Modal> renders a modal view the way views.open shows it: the title bar with the app icon and close button, a scrolling body, and the close and submit buttons.
import { Modal } from "@nkootstra/block-kit";
<Modal
icon="/deploy-bot.png"
view={{
type: "modal",
callback_id: "deploy",
title: { type: "plain_text", text: "Deploy" },
submit: { type: "plain_text", text: "Deploy" },
close: { type: "plain_text", text: "Cancel" },
blocks: [
{
type: "input",
block_id: "version",
label: { type: "plain_text", text: "Version" },
element: {
type: "plain_text_input",
action_id: "value",
placeholder: { type: "plain_text", text: "api@4.2.0" },
},
},
],
}}
/>;
Deploy
Press Deploy with the field empty: the modal validates it the way Slack does before it sends anything. When it’s valid, the provider’s onSubmit gets the view_submission payload. To open, push and update modals from actions, and answer a submission with errors, see Modals.
viewModalView
The view, as you'd pass it to `views.open`. Slack allows up to 100 blocks.
ModalViewicon?string
URL of the app icon shown before the title.
stringHome tab
<HomeTab> renders a home view full width, under the App Home tab bar.
import { HomeTab } from "@nkootstra/block-kit";
<HomeTab view={{ type: "home", blocks }} />;
Your deploys
An action handler can swap the content with views.publish, just as your app republishes the Home tab.
Any view
<View> takes any view object, for example one you’ve loaded from your database, and renders <Modal> or <HomeTab> depending on its type:
import { View } from "@nkootstra/block-kit";
<View view={savedView} icon="/deploy-bot.png" />;
Choosing the surface for loose blocks
<Blocks> renders an array of blocks with no surface around them. Some elements look different per surface: selects and text inputs are taller in modals and the Home tab, and only there does an optional input block get its “(optional)” label. Set the provider’s surface to the one you’re imitating:
import { BlockKitProvider, Blocks } from "@nkootstra/block-kit";
<BlockKitProvider surface="modal">
<div className="sbk-root">
<Blocks blocks={blocks} />
</div>
</BlockKitProvider>;
The sbk-root class applies the base font, colours and resets; <Message>, <Modal> and <HomeTab> add it for you.
