Gathering detailed insights and metrics for slack-block-builder
Gathering detailed insights and metrics for slack-block-builder
Gathering detailed insights and metrics for slack-block-builder
Gathering detailed insights and metrics for slack-block-builder
npm install slack-block-builder
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
567 Stars
409 Commits
47 Forks
6 Watching
2 Branches
18 Contributors
Updated on 23 Nov 2024
Minified
Minified + Gzipped
TypeScript (100%)
Cumulative downloads
Total Downloads
Last day
-21.9%
14,056
Compared to previous day
Last week
-9.4%
80,624
Compared to previous week
Last month
12.2%
355,586
Compared to previous month
Last year
129.4%
3,571,344
Compared to previous year
23
:information_source: Block Builder was built in Kyiv, Ukraine :ukraine: If it has saved you time as a developer and brought value to your projects and products, we would like to ask you to consider donating to Come Back Alive to help Ukraine in its fight against Russian aggression. Every cent helps. :pray:
Lightweight, zero-dependency library for declaratively building Slack Block Kit UI.
View the Docs »
Quick Start Guide
·
Request Feature
·
Report Bug
Block Builder helps you keep your Slack app code for UI maintainable, testable, and reusable. It has a declarative, chainable syntax inspired by SwiftUI and is built for better UI architecture.
Paginator
and Accordion
.printPreviewURL()
method that outputs a link to preview your UI on Slack's Block Kit Builder website for easier prototyping.Feedback – love it! Aside from GitHub Issues, there's a Slack channel available in the Slack Community workspace to discuss Block Builder – we'll see you there! :raised_hands:
Block Builder requires Node.js 12 or higher, and, when using TypeScript, TypeScript 3.8 or higher.
1npm install --save slack-block-builder
1yarn add slack-block-builder
For full documentation, make sure you head over to https://blockbuilder.dev.
The functions for creating objects can be both imported directly or through an object that groups them by category.
1// Importing exposed groups of objects 2 3import { Surfaces, Blocks, Elements, Bits, Utilities } from 'slack-block-builder'; 4 5// Importing objects top-level 6 7import { Modal, Section, Actions, Button } from 'slack-block-builder';
The same goes for importing Slack markdown helper functions:
1// Importing the Md object 2 3import { Surfaces, Blocks, Md } from 'slack-block-builder'; 4 5// Importing the functions top-level 6 7import { Modal, Section, bold, link } from 'slack-block-builder';
Surfaces
– Contains functions for creating modals, messages, home tabs, and workflow steps.
Blocks
– Layout blocks used to organize the UI.
Elements
– UI elements that are used to capture user interaction.
Bits
– These are composition objects and other bits and pieces from Slack's docs. Included are Attachment
, Options
, OptionGroup
, and ConfirmationDialog
. They felt like they were deserving of their own category.
Utilities
– A group of utility functions. See Utility Functions.
Md
– Helper functions for formatting text with Slack's markdown. See Markdown Helpers.
Below is a list of supported objects and how to access them in Block Builder:
Name | Type | Support | Accessed Via |
---|---|---|---|
Home Tab | Surface | :white_check_mark: | Surfaces.HomeTab() |
Message | Surface | :white_check_mark: | Surfaces.Message() |
Modal | Surface | :white_check_mark: | Surfaces.Modal() |
Workflow Step | Surface | :white_check_mark: | Surfaces.WorkflowStep() |
Actions | Block | :white_check_mark: | Blocks.Actions() |
Context | Block | :white_check_mark: | Blocks.Context() |
Divider | Block | :white_check_mark: | Blocks.Divider() |
File | Block | :white_check_mark: | Blocks.File() |
Header | Block | :white_check_mark: | Blocks.Header() |
Image | Block | :white_check_mark: | Blocks.Image() |
Input | Block | :white_check_mark: | Blocks.Input() |
Section | Block | :white_check_mark: | Blocks.Section() |
Video | Block | :white_check_mark: | Blocks.Video() |
Button | Element | :white_check_mark:️ | Elements.Button() |
Checkboxes | Element | :white_check_mark: | Elements.Checkboxes() |
Date Picker | Element | :white_check_mark: | Elements.DatePicker() |
Date Time Picker | Element | :white_check_mark: | Elements.DateTimePicker() |
Email Input | Element | :white_check_mark: | Elements.EmailInput() |
File Input | Element | :white_check_mark: | Elements.FileInput() |
Time Picker | Element | :white_check_mark: | Elements.TimePicker() |
Image | Element | :white_check_mark: | Elements.Img() |
Number Input | Element | :white_check_mark: | Elements.NumberInput() |
Overflow Menu | Element | :white_check_mark: | Elements.OverflowMenu() |
Radio Buttons | Element | :white_check_mark: | Elements.RadioButtons() |
Plain-Text Input | Element | :white_check_mark: | Elements.TextInput() |
Select Menus | Element | :white_check_mark: | Elements.[Type]Select() |
Multi-Select Menus | Element | :white_check_mark: | Elements.[Type]MultiSelect() |
URL Input | Element | :white_check_mark: | Elements.NumberInput() |
Option | Composition Object | :white_check_mark: | Bits.Option() |
Confirm Dialog | Composition Object | :white_check_mark: | Bits.ConfirmationDialog() |
Option Group | Composition Object | :white_check_mark: | Bits.OptionGroup() |
Attachment | Legacy Feature | :white_check_mark: | Bits.Attachment() |
Let's take a look at how to compose an interactive message. Even though Slack now has modals, these have always been the basis for Slack apps.
Functions that return Block Kit objects have setter methods for all of the properties, but also support parameters that are passed into the constructor for properties with primitive types.
1import { Message, Blocks, Elements } from 'slack-block-builder'; 2 3export default ({ channel, dangerLevel }) => 4 Message() 5 .channel(channel) 6 .text('Alas, my friend.') 7 .blocks( 8 Blocks.Section() 9 .text('One does not simply walk into Slack and click a button.'), 10 Blocks.Section() 11 .text('At least that\'s what my friend Slackomir said :crossed_swords:'), 12 Blocks.Divider(), 13 Blocks.Actions() 14 .elements( 15 Elements.Button() 16 .text('Sure One Does') 17 .actionId('gotClicked') 18 .danger(dangerLevel > 42), // Optional argument, defaults to 'true' 19 Elements.Button() 20 .text('One Does Not') 21 .actionId('scaredyCat') 22 .primary())) 23 .asUser() 24 .buildToJSON();
And now an example with using both the setter methods and passing parameters into the functions at initiation:
1import { Message, Blocks, Elements } from 'slack-block-builder'; 2 3export default ({ channel, dangerLevel }) => 4 Message({ channel, text: 'Alas, my friend.' }) 5 .blocks( 6 Blocks.Section({ text: 'One does not simply walk into Slack and click a button.' }), 7 Blocks.Section({ text: 'At least that\'s what my friend Slackomir said :crossed_swords:' }), 8 Blocks.Divider(), 9 Blocks.Actions() 10 .elements( 11 Elements.Button({ text: 'Sure One Does', actionId: 'gotClicked' }) 12 .danger(dangerLevel > 42), // Optional argument, defaults to 'true' 13 Elements.Button({ text: 'One Does Not', actionId: 'scaredyCat' }) 14 .primary())) 15 .asUser() 16 .buildToJSON();
Both of these examples render the message below. And the best part? It only took 15 lines of code, as opposed to the 44 lines of JSON generated as a result.
View Example on Slack Block Kit Builder Website
Let's take a look at how modals are created. Here we'll also take a look at working with Bits and with loops, by adding options with the Array.map()
method.
1import { Modal, Blocks, Elements, Bits, setIfTruthy } from 'slack-block-builder'; 2 3export default ({ menuOptions, selected }) => 4 Modal({ title: 'PizzaMate', submit: 'Get Fed' }) 5 .blocks( 6 Blocks.Section({ text: 'Hey there, colleague!' }), 7 Blocks.Section({ text: 'Hurray for corporate pizza! Let\'s get you fed and happy :pizza:' }), 8 Blocks.Input({ label: 'What can we call you?' }) 9 .element( 10 Elements.TextInput({ placeholder: 'Hi, my name is... (What?!) (Who?!)' }) 11 .actionId('name')), 12 Blocks.Input({ label: 'Which floor are you on?' }) 13 .element( 14 Elements.TextInput({ placeholder: 'HQ – Fifth Floor' }) 15 .actionId('floor')), 16 Blocks.Input({ label: 'What\'ll you have?' }) 17 .element( 18 Elements.StaticSelect({ placeholder: 'Choose your favorite...' }) 19 .actionId('item') 20 .options(menuOptions 21 .map((item) => Bits.Option({ text: item.name, value: item.id }))) 22 .initialOption(setIfTruthy(selected, Bits.Option({ text: selected.name, value: selected.id }))))) 23 .buildToJSON();
Both of these examples render the modal below.
View Example on Slack Block Kit Builder Website
Block Builder provides a Paginator
component that assists in producing paginated UI. It allows you to dictate the UI to build for each items passed in and provides to the actionId
all of the data (page
, perPage
, totalPages
, offset
, totalItems
) you need to produce the right page when a user clicks the Next or Previous buttons.
Note that there is a demo app available that demonstrates how to use components.
The Paginator
component supports optional customizations, such as:
nextButtonText
– Used to pass in custom text for the Next button, but has a default.
previousButtonText
– Used to pass in custom text for the Next button, but has a default.
pageCountText
– Used to pass in custom text for the page count, accepts a function and passes the function an object with page
and totalPages
properties.
1import { Modal, Blocks, Elements, Paginator } from 'slack-block-builder'; 2 3export default ({ tasks, totalTasks, page, perPage }) => Modal({ title: 'Open Tasks' }) 4 .blocks( 5 Blocks.Section({ text: 'Hi! :wave: And welcome to the FAQ section! Take a look around and if you don\'t find what you need, feel free to open an issue on GitHub.' }), 6 Blocks.Section({ text: `You currently have *${totalTasks} open task(s)*:` }), 7 Paginator({ 8 perPage, 9 items: tasks, 10 totalItems: totalTasks, 11 page: page || 1, 12 actionId: ({ page, offset }) => JSON.stringify({ action: 'render-tasks', page, offset }), 13 blocksForEach: ({ item }) => [ 14 Blocks.Divider(), 15 Blocks.Section({ text: `*${item.title}*` }) 16 .accessory( 17 Elements.Button({ text: 'View Details' }) 18 .actionId('view-details') 19 .value(item.id.toString())), 20 Blocks.Section({ text: `*Due Date:* ${getDate(item.dueDate)}` }), 21 ], 22 }).getBlocks()) 23 .close('Done') 24 .buildToJSON();
The code above renders the modal below. And be sure to check out the full documentation on the Block Builder doc site for more information.
View Example on Slack Block Kit Builder Website
Using the Accordion
component, you can easily create a customizable accordion for your Slack app. It not only assists in building a suitable UI, but also calculates the next state and gives you access to it in the actionId
of the buttons in the accordion, so that you can pass that back to your app's backend and use it to render the next state.
Note that there is a demo app available that demonstrates how to use components.
The Accordion
component supports optional customizations, such as:
collapseOnExpand
– Dictates whether or not multiple items can be expanded at once. When set to true, only one item will be expanded at any given time.
expandButtonText
– Used to pass in custom text for the button that expands an item, but has a default.
collapseButtonText
– Used to pass in custom text for the button that collapses an expanded item, but has a default.
isExpandable
– Used to display or not the expand/collapse button for a given item.
1import { Modal, Blocks, Accordion } from 'slack-block-builder'; 2 3export default ({ faqs, expandedItems }) => Modal({ title: 'FAQ' }) 4 .blocks( 5 Blocks.Section({ text: 'Hi! :wave: And welcome to the FAQ section! Take a look around and if you don\'t find what you need, feel free to open an issue on GitHub.'}), 6 Blocks.Divider(), 7 Accordion({ 8 items: faqs, 9 expandedItems: expandedItems || [], // In this case, the value is [1] 10 collapseOnExpand: true, 11 titleText: ({ item }) => `*${item.question}*`, 12 actionId: ({ expandedItems }) => JSON.stringify({ action: 'render-faqs', expandedItems }), 13 blocksForExpanded: ({ item }) => [ 14 Blocks.Section({ text: `${item.answer}` }), 15 ], 16 }).getBlocks()) 17 .close('Done') 18 .buildToJSON();
The code above renders the modal below. And be sure to check out the full documentation on the Block Builder doc site for more information.
View Example on Slack Block Kit Builder Website
The Utilities
object contains various utility functions for creating UI. Currently, there are two:
BlockCollection()
– Accepts multiple arguments or an array of blocks and returns them in an array, in their built state.
AttachmentCollection()
– Accepts multiple arguments or an array of attachments and returns them in an array, in their built state.
OptionCollection()
– Accepts multiple arguments or an array of options and returns them in an array, in their built state.
OptionGroupCollection()
– Accepts multiple arguments or an array of option groups and returns them in an array, in their built state.
Both BlockCollection()
and AttachmentCollection()
are useful when you wish to keep surface or view configuration separate from UI representation.
An example using Slack's WebClient
from their SDK for Node.js:
1import { BlockCollection, AttachmentCollection, Blocks } from 'slack-block-builder'; 2import { WebClient } from '@slack/web-api'; 3 4const client = new WebClient(process.env.SLACK_TOKEN); 5 6client.chat.postMessage({ 7 channel: 'ABCDEFG', 8 text: 'Hello, my dear, sweet world!', 9 blocks: BlockCollection( /* Pass in blocks */ ), 10 attachments: AttachmentCollection( /* Pass in attachments */ ), 11}) 12.then((response) => console.log(response)) 13.catch((error) => console.log(error));
Another example where you might find BlockCollection()
helpful is when unfurling links in messages:
1import { BlockCollection, Blocks } from 'slack-block-builder'; 2import { WebClient } from '@slack/web-api'; 3 4const client = new WebClient(process.env.SLACK_TOKEN); 5 6const unfurl = ({ channel, ts, url }) => client.chat.unfurl({ 7 channel, 8 ts, 9 unfurls: { [url]: BlockCollection( /* Pass in blocks */ ) }, 10}) 11.then((response) => console.log(response)) 12.catch((error) => console.log(error));
Both OptionCollection()
and OptionGroupCollection()
come in handy when returning an array of options or option groups for select menus with external data sources, as seen in Slack's API docs:
1return { options: OptionCollection( /* Pass in options */ ) }; 2 3// Or: 4 5return { options: OptionGroupCollection( /* Pass in option groups */ ) };
There are a few helper functions available to make it easy to work with inline conditionals within your UI source code.
They can be imported separately:
1import { setIfTruthy, omitIfTruthy, setIfFalsy, omitIfFalsy } from 'slack-block-builder';
Or as a part of the conditionals
object:
1import { conditionals } from 'slack-block-builder';
Each function accepts two arguments – the first being a value that is evaluated whether it is either null
, undefined
, or false
, and the second being the value to set or omit:
1import { Modal, Blocks, Elements, Bits, setIfTruthy } from 'slack-block-builder'; 2 3export default ({ groups, selectedGroup, selectedGroupMembers }) => Modal() 4 .title('Edit Groups') 5 .callbackId('submit-edit-groups') 6 .blocks( 7 Blocks.Section({ text: 'Hello! Need to edit some groups?'}), 8 Blocks.Input({ label: 'Select a group to get started' }) 9 .dispatchAction() 10 .element( 11 Elements.StaticSelect({ placeholder: 'Select a group...' }) 12 .actionId('selectedGroup') 13 .options(groups 14 .map(({ name, id }) => Bits.Option({ text: name, value: id })))), 15 setIfTruthy(selectedGroup, [ 16 Blocks.Input({ label: 'Current group members' }) 17 .element( 18 Elements.UserMultiSelect({ placeholder: 'Select members...' }) 19 .actionId('groupMembers') 20 .initialUsers(selectedGroupMembers)) 21 ])) 22 .submit(setIfTruthy(selectedGroup, 'Save Changes')) 23 .buildToJSON();
These functions essentially return either the value passed into as the second argument or undefined
, depending on the condition. Please note that falsy is defined as null
, undefined
, or false
. To avoid side effects, values such as 0
or ''
are not considered to be falsy.
Often you'll find that you need to format text in your messages and modals. Block Builder has helper functions available to simply that process. They are available both as members of the Md
object and as top-level imports. You can find the full list of functions on the Block Builder doc site:
1import { Message, Blocks, Md } from 'slack-block-builder'; 2 3export default ({ channel, user }) => { 4 const slashCommands = ['/schedule', '/cancel', '/remind', '/help']; 5 6 return Message({ channel, text: 'Alas, my friend.' }) 7 .blocks( 8 Blocks.Section({ text: `:wave: Hi there, ${Md.user(user)}!` }), 9 Blocks.Section({ text: `${Md.italic('Sorry')}, I didn't get that. Why don't you try out some of my slash commands?` }), 10 Blocks.Section({ text: `Here are some of the things that I can do:` }), 11 Blocks.Section() 12 .text(Md.listBullet(slashCommands 13 .map((item) => Md.codeInline(item))))) 14 .asUser() 15 .buildToObject(); 16};
View Example on Slack Block Kit Builder Website
Bolt for JavaScript – A simple framework for building Slack apps, developed by Slack themselves.
Node Slack SDK – A great and powerful SDK for building Slack Apps from the ground up.
Taras Neporozhniy (@korywka) - For help and ideas along the way!
Alexey Chernyshov (@ft502 on Dribbble) - For such a beautiful logo!
SlackHQ (@slackhq) - For such a wonderful product and API!
Ray East (@raycharius) - Huge Fan of Slack and Block Builder Maintainer
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
0 existing vulnerabilities detected
Reason
Found 7/11 approved changesets -- score normalized to 6
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More