jsx-slack
Version:
Build JSON object for Slack Block Kit surfaces from JSX
438 lines (322 loc) • 16.4 kB
Markdown
<h1 align="center">
<a href="https://npm.im/jsx-slack">
<img src="https://raw.githubusercontent.com/yhatt/jsx-slack/HEAD/demo/public/logo.svg?sanitize=true" width="100" /><br />
jsx-slack
</a>
</h1>
[][circleci]
[](https://codecov.io/gh/yhatt/jsx-slack)
[][npm]
[][license]
[circleci]: https://circleci.com/gh/yhatt/jsx-slack/
[npm]: https://npm.im/jsx-slack
[license]: ./LICENSE
Build JSON object for [Slack][slack] [block kit] surfaces from [JSX].
[slack]: https://slack.com
[jsx]: https://reactjs.org/docs/introducing-jsx.html
[react]: https://reactjs.org/
[block kit]: https://api.slack.com/block-kit
[block kit builder]: https://api.slack.com/tools/block-kit-builder
<p align="center">
<a href="https://jsx-slack.netlify.app/">
<img src="https://raw.githubusercontent.com/yhatt/jsx-slack/HEAD/docs/jsx.png" width="550" />
</a>
<br />
<a href="https://jsx-slack.netlify.app/#bkb:message">
<img src="https://raw.githubusercontent.com/yhatt/jsx-slack/HEAD/docs/slack-notification.png" width="532" />
</a>
</p>
:point_right: **[Try our REPL demo](https://jsx-slack.netlify.app/)** in https://jsx-slack.netlify.app/.
### Features
- **[Block Kit as components](docs/jsx-components-for-block-kit.md)** - Build contents for any surfaces by composing components for Block Kit with JSX.
- **[HTML-like formatting](docs/html-like-formatting.md)** - Keep a readability by using well-known elements.
See **[references](#references)** to dive into jsx-slack deeply.
## Motivation
When developing Slack-integrated app, continuous maintenance of the rich contents is a difficult task. A team member must read and write JSON with deep knowledge about specifications of payload for Slack API.
We believe JSX-based template well-known in front-end development would enhance a developer experience of Slack app.
## Project goal
A project goal is creating an interface to compose contents for Slack with keeping code maintainability by using [JSX].
jsx-slack would allow composing contents with simple and predictable HTML-like markup. It helps in understanding the structure of complex contents and interactions.
## Install
### [Node.js](https://nodejs.org/)
We require Node.js >= 14. If you are using TypeScript, we also require TS >= 3.7.
```bash
# npm
npm install --save jsx-slack
```
```bash
# yarn
yarn add jsx-slack
```
Now you can begin to write the code with [`jsxslack` template literal tag](#quick-start-template-literal). Furthermore, [setting up JSX transpiler](docs/how-to-setup-jsx-transpiler.md) would make the best development experience.
### [Deno](https://deno.land/) ([Slack CLI](https://api.slack.com/future/tools/cli))
We also have Deno support. If you are using Deno v1.28 and later, [you can import jsx-slack through npm directly](https://deno.land/manual/node/npm_specifiers).
```typescript
// `jsxslack` template literal tag
import { jsxslack } from 'npm:jsx-slack@6'
```
```typescript
// JSX transpilation
/** @jsxImportSource npm:jsx-slack@6 */
import { Blocks, Section } from 'npm:jsx-slack@6'
```
> **Note**
> Alternatively [you also can import jsx-slack through esm.sh CDN](https://deno.land/manual@v1.28.1/node/cdns#esmsh): [`https://esm.sh/jsx-slack@6`](https://esm.sh/jsx-slack@6)
## Usage
### Quick start: Template literal
Do you hate troublesome setting up for JSX? All right. We provide **`jsxslack`** tagged template literal to build blocks _right out of the box_.
It allows the template syntax almost same as JSX, powered by [HTM (Hyperscript Tagged Markup)](https://github.com/developit/htm). Setting for transpiler and importing built-in components are not required.
This is a simple example of the template function just to say hello to someone.
```javascript
import { jsxslack } from 'jsx-slack'
export const exampleBlock = ({ name }) => jsxslack`
<Blocks>
<Section>
Hello, <b>${name}</b>!
</Section>
</Blocks>
`
```
### [JSX Transpiler](docs/how-to-setup-jsx-transpiler.md)
When you want to use jsx-slack with JSX transpiler, you have to set up to use our runtime for JSX.
**[▶︎ How to setup JSX transpiler](docs/how-to-setup-jsx-transpiler.md)** (Babel / TypeScript / Deno)
```jsx
/** @jsxImportSource jsx-slack */
import { Blocks, Section } from 'jsx-slack'
export const exampleBlock = ({ name }) => (
<Blocks>
<Section>
Hello, <b>{name}</b>!
</Section>
</Blocks>
)
```
### Use template in Slack API
After than, just use created template in Slack API. We are using the official Node SDK [`@slack/web-api`](https://github.com/slackapi/node-slack-sdk) in this example. [See also Slack guide.](https://slackapi.github.io/node-slack-sdk/web_api)
```javascript
import { WebClient } from '@slack/web-api'
import { exampleBlock } from './example.jsx'
const web = new WebClient(process.env.SLACK_TOKEN)
web.chat
.postMessage({
channel: 'C1234567890',
blocks: exampleBlock({ name: 'Yuki Hattori' }),
})
.then((res) => console.log('Message sent: ', res.ts))
.catch(console.error)
```
It would post a simple Slack message like this:
[<img src="./docs/slack-example.png" width="193" />][block-kit-builder-example]
[<img src="./docs/preview-btn.svg" width="240" />][block-kit-builder-example]
[block-kit-builder-example]: https://jsx-slack.netlify.app/#bkb:jsx:eJyzccrJT84utuNSULAJTk0uyczPA7EVFDxSc3LydRRskuwiS7MzFTwSS0ryizJt9JPsFEFq9eGKbfShRgAAVeQWug==
## Block Kit as components
Slack has recommended to use **[Block Kit]** for building tempting messages and modals.
By using jsx-slack, you can build a template with piling up Block Kit blocks by JSX. It is feeling like using components in React or Vue.
### [For messaging](https://jsx-slack.netlify.app/)
```jsx
<Blocks>
<Section>
<p>Enjoy building blocks!</p>
<blockquote>
<b>
<a href="https://github.com/yhatt/jsx-slack">jsx-slack</a>
</b>
<br />
<i>Build JSON for Slack Block Kit from JSX</i>
</blockquote>
<img src="https://github.com/yhatt.png" alt="yhatt" />
</Section>
<Context>
Maintained by <a href="https://github.com/yhatt">Yuki Hattori</a>
<img src="https://github.com/yhatt.png" alt="yhatt" />
</Context>
<Divider />
<Actions>
<Button url="https://github.com/yhatt/jsx-slack">GitHub</Button>
<Button url="https://npm.im/jsx-slack">npm</Button>
</Actions>
</Blocks>
```
### [For modal](https://jsx-slack.netlify.app/#modal)
```jsx
<Modal title="My first modal" close="Cancel">
<Section>
<p>
<strong>It's my first modal!</strong> :sunglasses:
</p>
<p>jsx-slack also has supported Slack Modals.</p>
</Section>
<Divider />
<Input type="text" name="subject" label="Subject" required />
<Textarea name="message" label="Message" maxLength={500} />
<ConversationsSelect
name="shareWith"
label="Share with..."
required
include={['public', 'im']}
excludeBotUsers
responseUrlEnabled
/>
<Input type="hidden" name="postId" value="xxxx" />
<Input type="submit" value="Send" />
</Modal>
```
### [For home tab](https://jsx-slack.netlify.app/#home)
```jsx
<Home>
<Image src="https://source.unsplash.com/random/960x240?home" alt="home" />
<Header>Welcome back to my home! :house_with_garden:</Header>
<Divider />
<Section>What's next?</Section>
<Actions>
<RadioButtonGroup actionId="next">
<RadioButton value="tickets" checked>
<b>See assigned tickets</b> :ticket:
<small>
<i>Check your tickets to start your work.</i>
</small>
</RadioButton>
<RadioButton value="reminder">
<b>Remind a task later</b> :memo:
<small>
<i>I'll remember a task for you.</i>
</small>
</RadioButton>
<RadioButton value="pomodoro">
<b>Start pomodoro timer</b> :tomato:
<small>
<i>Get focused on your time, with tomato!</i>
</small>
</RadioButton>
</RadioButtonGroup>
<Button actionId="start" style="primary">
Start working
</Button>
</Actions>
</Home>
```
### References
- **[How to setup JSX transpiler](docs/how-to-setup-jsx-transpiler.md)**
- **[JSX components for Block Kit](docs/jsx-components-for-block-kit.md)**
- [Block containers](docs/block-containers.md)
- [Layout blocks](docs/layout-blocks.md)
- [Block elements](docs/block-elements.md)
- [Interactive components](docs/block-elements.md#user-content-interactive-components)
- [Composition objects](docs/block-elements.md#user-content-composition-objects)
- [Input components](docs/block-elements.md#user-content-input-components)
* **[HTML-like formatting](docs/html-like-formatting.md)**
* **[About escape and exact mode](docs/about-escape-and-exact-mode.md)**
- **[Highlight of v2](docs/highlight/v2.md)**
### Examples by use cases
Ported from templates for [Block Kit Builder].
#### [Message](https://api.slack.com/tools/block-kit-builder?mode=message&template=1)
- [Approval (New device request)](https://jsx-slack.netlify.app/#messagingApprovalNewDevice)
- [Approval (Time Off request)](https://jsx-slack.netlify.app/#messagingApprovalTimeOff)
- [Notification](https://jsx-slack.netlify.app/#messagingNotification)
- [Onboarding (Taskbot)](https://jsx-slack.netlify.app/#messagingOnboardingTaskbot)
- [Onboarding (Onboarding App)](https://jsx-slack.netlify.app/#messagingOnboardingApp)
- [Poll](https://jsx-slack.netlify.app/#messagingPoll)
- [Search Results (TripAgent)](https://jsx-slack.netlify.app/#messagingSearchResultsTripAgent)
- [Search Results (FileCard Agent)](https://jsx-slack.netlify.app/#messagingSearchResultsFileCard)
- [Newsletter](https://jsx-slack.netlify.app/#messagingNewsletter)
#### [Modal](https://api.slack.com/tools/block-kit-builder?mode=modal&template=1)
- [Poll](https://jsx-slack.netlify.app/#modalPoll)
- [Search Results](https://jsx-slack.netlify.app/#modalSearchResults)
- [Settings (App menu)](https://jsx-slack.netlify.app/#modalSettingsAppMenu)
- [Settings (Notification settings)](https://jsx-slack.netlify.app/#modalSettingsNotification)
- [List of information (Your itinerary)](https://jsx-slack.netlify.app/#modalListOfInformationYourItinerary)
- [List of information (Ticket app)](https://jsx-slack.netlify.app/#modalListOfInformationTicketApp)
#### [App Home](https://api.slack.com/tools/block-kit-builder?mode=appHome&template=1)
- [Project Tracker](https://jsx-slack.netlify.app/#appHomeProjectTracker)
- [Calendar](https://jsx-slack.netlify.app/#appHomeCalendar)
- [Expense App](https://jsx-slack.netlify.app/#appHomeExpenseApp)
- [Todo App](https://jsx-slack.netlify.app/#appHomeTodoApp)
## Fragments
[As like as React](https://reactjs.org/docs/fragments.html), jsx-slack provides `<Fragment>` (`<JSXSlack.Fragment>`) component for higher-order component (HOC) consited of multiple blocks or elements.
For example, you can define the custom block by grouping some blocks with `<Fragment>` if you were using JSX transpiler.
Let's say about defining `<Heading>` custom block that is consisted by `<Section>` and `<Divider>`.
```javascript
import { Fragment, Section, Divider } from 'jsx-slack'
const Heading = ({ children }) => (
<Fragment>
<Section>
<b>{children}</b>
</Section>
<Divider />
</Fragment>
)
```
Now the defined block can use in `<Blocks>` as like as the other blocks:
```jsx
<Blocks>
<Heading>
<i>jsx-slack custom block</i> :sunglasses:
</Heading>
<Section>Let's build your block.</Section>
</Blocks>
```
[<img src="./docs/custom-header-block.png" width="600" />][custom-header-block]
[<img src="./docs/preview-btn.svg" width="240" />][custom-header-block]
[custom-header-block]: https://jsx-slack.netlify.app/#bkb:jsx:eJxVjrEOgzAQQ3e-4jYmejs6Zag6duMLSIjQlZRIOEHt3xcaBphsD8-23EN0E0xFJJ13SeO8-y3ZoptT88KnQejdRC4jxTfZnRJWQy3yPIYe8GgLyH9S-FQnD1118AvxZejpUw2yWcNA35iXUns7ocLHvx9tITN_
### Short syntax for fragments
Babel transpiler and TypeScript 4 can use [the short syntax `<></>` for fragments](https://reactjs.org/docs/fragments.html#short-syntax). See [how to setup JSX transpiler](docs/how-to-setup-jsx-transpiler.md).
```javascript
import { Section, Divider } from 'jsx-slack'
const Heading = ({ children }) => (
<>
<Section>
<b>{children}</b>
</Section>
<Divider />
</>
)
```
### In the case of template literal tag
`jsxslack` template literal tag has [built-in fragments support](https://github.com/developit/htm#improvements-over-jsx) so `<Fragment>` does not have to use.
```javascript
// Heading.js
import { jsxslack } from 'jsx-slack'
export const Heading = ({ children }) => jsxslack`
<Section>
<b>${children}</b>
</Section>
<Divider />
`
```
A defined component may use in `jsxslack` tag as below:
```javascript
import { jsxslack } from 'jsx-slack'
import { Heading } from './Heading'
console.log(jsxslack`
<Blocks>
<${Heading}>
<i>jsx-slack custom block</i> :sunglasses:
<//>
<Section>Let's build your block.</Section>
</Blocks>
`)
```
Please notice to a usage of component that has a bit different syntax from JSX.
## Frequently questions
### Is jsx-slack the state of production-ready?
Of course! In our workspace, we are developing Slack custom app for internal with providing great UX powered by jsx-slack. And some apps published in Slack app directory are also using jsx-slack in production.
Do you have an app with jsx-slack in public? Please let us know your great app!
### Can I develop Slack app _only using jsx-slack_?
No. jsx-slack just generates JSON for Slack API. You have to send generated message and control interaction with Slack by yourself.
Don't worry; you can use jsx-slack together with helpful libraries: [Bolt framework for JavaScript](https://slack.dev/bolt) (recommended), [Slack Node SDK](https://slack.dev/node-slack-sdk/), and third-party library (e.g. [BotKit](https://botkit.ai/), [Bottender](https://bottender.js.org/)).
### Is this working based on [React]?
No, jsx-slack has very similar API to React but is not based on React, because our library doesn't need to use some features provided by React: incremental updates, event handling, reference to the rendered JSON, and component class.
Nevertheless, jsx-slack can use React's methodology (composition of components) through JSX and the basic JavaScript function. In addition, we can follow up rapidly-evolving Slack Block Kit by keeping the smallest requirements without depending on React.
FYI there are some projects based on React ([react-reconciler](https://github.com/facebook/react/tree/master/packages/react-reconciler)) to generate or manage Slack interactions: [phelia](https://github.com/maxchehab/phelia) framework, [react-chat-renderer](https://github.com/asynchronous-dev/react-chat-renderer) (< v0.1.0), and [rebot](https://github.com/bradennapier/rebot). You should use them if you want to use React ecosystem.
<!-- NOTE: The latest react-chat-renderer is no longer based on react-reconciler. It implements custom JSX renderer as same as jsx-slack. -->
### How do you spell this library?
"jsx-slack" with all in lowercase. It is neither of "JSX-Slack" nor "JSX Slack".
## Similar projects
<!-- This section is listing only libraries that generates Block Kit JSON from JSX. -->
- [phelia](https://github.com/maxchehab/phelia) - :zap: A reactive Slack application framework. <!-- React-based Slack app framework with familiar event handling by hooks -->
- [react-chat-renderer](https://github.com/asynchronous-dev/react-chat-renderer) - React renderer implementation for building rich Slack messages using JSX <!-- Custom JSX renderer for Slack + async component support -->
- [slack-blockx](https://github.com/kevin940726/slack-blockx) - jsx for Slack block-kit <!-- Block Kit JSON builder whose exactly same concept as jsx-slack -->
## Author
- <img src="https://github.com/yhatt.png" alt="@yhatt" width="24" height="24" valign="bottom" /> Yuki Hattori ([@yhatt](https://github.com/yhatt)) - Maintainer
## License
[MIT License](LICENSE)