Quickstart
Render an approval message and answer its buttons the way your Slack app would.
In this guide you render a message with two buttons, handle the click, and replace the buttons with the outcome, the same flow a Slack app runs with response_url.
This guide assumes you’ve finished Installation.
Render the message
Pass the blocks your app sends to chat.postMessage straight to <Message>:
import { Message } from "@nkootstra/block-kit";
const blocks = [
{
type: "section",
text: { type: "mrkdwn", text: "<@U0ADA> wants to deploy *api@4.2.0* to production." },
},
{
type: "actions",
block_id: "deploy",
elements: [
{
type: "button",
style: "primary",
action_id: "approve",
value: "api@4.2.0",
text: { type: "plain_text", text: "Approve" },
},
{
type: "button",
action_id: "reject",
value: "api@4.2.0",
text: { type: "plain_text", text: "Reject" },
},
],
},
];
export function Approval() {
return <Message app={{ name: "Deploy Bot" }} blocks={blocks} />;
}<@U0ADA> renders as a mention. Tell the renderer who that is with resolvers; until then it shows the raw id, as Slack does for a user it can’t find.
Handle the click
Wrap the message in a <BlockKitProvider> and pass onAction. It receives each action in the shape of one entry of a block_actions payload’s actions array:
import { BlockKitProvider, Message, type BlockAction } from "@nkootstra/block-kit";
function handleAction(action: BlockAction) {
console.log(action.action_id, action.value);
// → "approve" "api@4.2.0"
}
export function Approval() {
return (
<BlockKitProvider onAction={handleAction}>
<Message app={{ name: "Deploy Bot" }} blocks={blocks} />
</BlockKitProvider>
);
}Click a button below to see the action it sends:
Update the message
The second argument to onAction lets you answer the way an app would. message.update replaces the message the action came from, like posting to response_url with replace_original:
import {
BlockKitProvider,
Message,
type ActionContext,
type BlockAction,
} from "@nkootstra/block-kit";
function handleAction(action: BlockAction, { message }: ActionContext) {
const verdict = action.action_id === "approve" ? ":white_check_mark: Approved" : ":x: Rejected";
message?.update({
blocks: [
blocks[0],
{ type: "context", elements: [{ type: "mrkdwn", text: `${verdict} by <@U0GRACE>` }] },
],
});
}After a click, the message becomes:
The context also has views, to open a modal, and state, with the current value of every input in the message.
Already have a Slack app?
If your app already handles interactions, with Bolt or your own request URL, you don’t need to rewrite its logic in React. Relay the clicks to it instead, and apply whatever it answers: see Connecting your app.
