Block Kit is a very powerful UI framework that provides you to flexibly construct messages, modals and HomeTabs sent or created from Slack Apps.
However, since the UI is defined by JSON, it is a little difficult to handle in a program.
block-kit-handler lets you programmatically handle Block Kit with less code and in an easier way.
npm install block-kit-handler
I have Github project that shows how to use block-kit-handler.
For details, please refer to the project.
import { Block } from '@slack/types';
import { actions, section, button, divider, mrkdwnText, plainText } from 'block-kit-handler';
app.command("/message", async ({ ack, payload, context }) => {
await ack();
// declare blocks for message
const blocks: Block[] = [
section({ text: mrkdwnText('*Where should we order lunch from?* Poll by <fakeLink.toUser.com|Mark>')}),
divider(),
section({
text: mrkdwnText(':sushi: *Ace Wasabi Rock-n-Roll Sushi Bar*\nThe best landlocked sushi restaurant.'),
accessory: button(plainText('Vote'), 'vote-a', { value: 'click_me_123'})
}),
section({
text: mrkdwnText(':hamburger: *Super Hungryman Hamburgers*\nOnly for the hungriest of the hungry.'),
accessory: button(plainText('Vote'), 'vote-b', { value: 'click_me_123'})
}),
section({
text: mrkdwnText(':ramen: *Kagawa-Ya Udon Noodle Shop*\nDo you like to shop for noodles? We have noodles.'),
accessory: button(plainText('Vote'), 'vote-c', { value: 'click_me_123'})
}),
divider(),
actions([ button(plainText('Add a suggestion'), 'add-suggestion', { value: 'click_me_123' })])
];
// post message
await app.client.chat.postMessage({
token: context.botToken,
channel: payload.channel_id,
text: 'message sample',
blocks: blocks
});
});
If you use the raw JSON to create the same message, you'll have to write many more lines.
See this.
import { Block } from '@slack/types';
import { Modal, actions, section, button, divider, staticSelect, option, mrkdwnText, plainText } from 'block-kit-handler';
app.command("/modal", async ({ ack, payload, context }) => {
await ack();
// declare blocks for modal
const blocks: Block[] = [
section({ text: mrkdwnText('*Hi <fakelink.toUser.com|@David>!* Here\'s how I can help you:')}),
divider(),
section({
text: mrkdwnText(':calendar: *Create event*\nCreate a new event'),
accessory: button(plainText('Create event'), 'create', { value: 'click_me_123', style: 'primary' })
}),
section({
text: mrkdwnText(':clipboard: *List of events*\nChoose from different event lists'),
accessory: staticSelect('chose-list', plainText('Choose list'), [
option(plainText('My events'), 'value-0'),
option(plainText('All events'), 'value-1'),
option(plainText('Event invites'), 'value-2')
])
}),
section({
text: mrkdwnText(':gear: *Settings*\nManage your notifications and team settings'),
accessory: staticSelect('edit-settings', plainText('Edit settings'), [
option(plainText('Notifications'), 'value-0'),
option(plainText('Team settings'), 'value-1')
])
}),
actions([
button(plainText('Send feedback'), 'send-feedback', { value: 'click_me_123' }),
button(plainText('FAQs'), 'faqs', { value: 'click_me_123' })
])
];
// build modal
const modal = new Modal(plainText('App menu'), blocks, { close: plainText('Cancel'), submit: plainText('Submit')});
// open modal
await app.client.views.open({
token: context.botToken,
trigger_id: payload.trigger_id,
view: modal.getView()
});
});
JSON for the same modal is Here.
import { Block } from '@slack/types';
import { HomeTab, actions, section, button, divider, staticSelect, option, mrkdwnText, plainText } from 'block-kit-handler';
app.event('app_home_opened', async({ context, body }) => {
// declare blocks for home tab
const blocks: Block[] = [
section({ text: mrkdwnText('*Here\'s what you can do with Project Tracker:*')}),
actions([
button(plainText('Create New Task'), 'create-new-task', { value: 'click_me_123', style: 'primary' }),
button(plainText('Create New Project'), 'create-new-project', { value: 'click_me_123' }),
button(plainText('Help'), 'help', { value: 'click_me_123' })
]),
section({ text: mrkdwnText('*Your Configurations*')}),
divider(),
section({
text: mrkdwnText('*#public-relations*\n<fakelink.toUrl.com|PR Strategy 2019> posts new tasks, comments, and project updates to <fakelink.toChannel.com|#public-relations>'),
accessory: button(plainText('Edit'), 'edit-1', { value: 'public-relations' })
}),
divider(),
section({
text: mrkdwnText('*#team-updates*\n<fakelink.toUrl.com|Q4 Team Projects> posts project updates to <fakelink.toChannel.com|#team-updates>'),
accessory: button(plainText('Edit'), 'edit-2', { value: 'public-relations' })
}),
divider(),
actions([
button(plainText('New Configuration'), 'new-configuration', { value: 'new_configuration' })
])
];
// build home tab
const homeTab = new HomeTab(blocks);
// publish home tab
await app.client.views.publish({
token: context.botToken,
user_id: body.user_id,
view: homeTab.getView()
});
});
JSON for the same home tab is here.
Components | Supported | Link |
---|---|---|
Messages | yes | Link |
Modals | yes | Link |
Home Tab | yes | Link |
Components | Supported | Link |
---|---|---|
Actions | yes | Link |
Context | yes | Link |
Divider | yes | Link |
File | not yet | Link |
Header | not yet | Link |
Image | not yet | Link |
Input | yes | Link |
Section | yes | Link |
Components | Supported | Link |
---|---|---|
Button | yes | Link |
Checkboxes | yes | Link |
Date Picker | yes | Link |
Image | not yet | Link |
Multi-select menu with static options | yes | Link |
Multi-select menu with external data source | yes | Link |
Multi-select menu with user list | yes | Link |
Multi-select menu with conversations list | yes | Link |
Multi-select menu with channels list | yes | Link |
Overflow menu | yes | Link |
Plain-text input | yes | Link |
Radio button group | not yet | Link |
Select menu with static options | yes | Link |
Select menu with external data source | yes | Link |
Select menu with user list | yes | Link |
Select menu with conversations list | yes | Link |
Select menu with channels list | yes | Link |
Time Picker | not yet | Link |
Components | Supported | Link |
---|---|---|
Text | yes | Link |
Confirmation dialog | not yet | Link |
Option | yes | Link |
Option group | not yet | Link |
Dispatch action configuration | not yet | Link |
Filter object for conversation lists | not yet | Link |