Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 400,000 packages pre-installed, including @speee-js/jsx-slack with all npm packages installed. Try it out:

var jsxSlack = require("@speee-js/jsx-slack")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

@speee-js/jsx-slack v0.9.1

Build JSON object for Slack Block Kit and dialog from readable JSX

jsx-slack

CircleCI Codecov npm LICENSE

Build JSON object for Slack Block Kit and dialog from readable JSX.


:point_right: Try our REPL demo in https://speee-jsx-slack.netlify.com/.

Features

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 a specification of Slack messaging.

Slack has shipped Block Kit and Block Kit Builder, and efforts to develop app easily. We believe JSX-based template would enhance a developer experience of Slack app to the next stage.

Project goal

A project goal is creating an interface to build a maintainable Slack message and interactive contents with confidence via readable JSX.

jsx-slack would allow building message blocks and dialogs with predictable HTML-like markup. It helps in understanding the structure of complex messages and interactions.

Install

We require Node.js >= 8. If you are using TypeScript, we also require TS >= 3.0.

# npm
npm install --save @speee-js/jsx-slack
# yarn
yarn add @speee-js/jsx-slack

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). 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.

import { jsxslack } from '@speee-js/jsx-slack'

export default function exampleBlock({ name }) {
  return jsxslack`
    <Blocks>
      <Section>
        Hello, <b>${name}</b>!
      </Section>
    </Blocks>
  `
}

JSX Transpiler

When you want to use jsx-slack with JSX transpiler (Babel / TypeScript), you have to set up to use imported our parser JSXSlack.h. Typically, we recommend to use pragma comment /** @jsx JSXSlack.h */.

To create JSON from JSX, please wrap JSX by JSXSlack() function.

/** @jsx JSXSlack.h */
import JSXSlack, { Blocks, Section } from '@speee-js/jsx-slack'

export default function exampleBlock({ name }) {
  return JSXSlack(
    <Blocks>
      <Section>
        Hello, <b>{name}</b>!
      </Section>
    </Blocks>
  )
}

A prgama would work in Babel (@babel/plugin-transform-react-jsx) and TypeScript with --jsx react. You can use jsx-slack in either one.

Use template in Slack API

After than, just use created template in Slack API. We are using the official Node SDK @slack/client in this example. See also Slack guide.

import { WebClient } from '@slack/client'
import exampleBlock from './example'

const web = new WebClient(process.env.SLACK_TOKEN)

web.chat
  .postMessage({
    channel: 'C1232456',
    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:

Block Kit as components

Slack has recommended to use Block Kit for building tempting message. 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.

<Blocks>
  <Section>
    <p>Enjoy building blocks!</p>
    <blockquote>
      <b>
        <a href="https://github.com/speee/jsx-slack">@speee-js/jsx-slack</a>
      </b>
      <br />
      <i>Build JSON for Slack Block Kit from JSX</i>
    </blockquote>
    <Image src="https://github.com/speee.png" alt="Speee, Inc." />
  </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/speee/jsx-slack">GitHub</Button>
    <Button url="https://www.npmjs.com/package/@speee-js/jsx-slack">npm</Button>
  </Actions>
</Blocks>

References

Dialog as components

We also provide @speee-js/jsx-slack/dialog to allow building Dialog JSON with same feeling. You can create Dialog JSON for dialog argument in dialog.open Slack API, with familiar HTML form style.

/** @jsx JSXSlack.h */
import JSXSlack from '@speee-js/jsx-slack'
import { Dialog, Input, Textarea } from '@speee-js/jsx-slack/dialog'

export default function exampleDialog(data) {
  return JSXSlack(
    <Dialog callbackId="create" title="Create">
      <Input name="name" label="Name" value={data.name} required />
      <Textarea name="desc" label="Description" value={data.desc} />

      <Input type="hidden" name="userId" value={data.userId} />
      <Input type="submit" value="Create" />
    </Dialog>
  )
}

References

Fragments

As like as React, 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 defines <Header> custom block that is consisted by <Section> and <Divider>.

/** @jsx JSXSlack.h */
import JSXSlack, { Fragment } from '@speee-js/jsx-slack'

const Header = ({ children }) => (
  <Fragment>
    <Section>
      <b>{children}</b>
    </Section>
    <Divider />
  </Fragment>
)

Now the defined block can use in <Blocks> as like as the other blocks:

<Blocks>
  <Header>
    <i>jsx-slack custom block</i> :sunglasses:
  </Header>
  <Section>Let's build your block.</Section>
</Blocks>

Short syntax for Babel transpiler

If you want to use the short syntax <></> for fragments in Babel transpiler, we recommend to set an extra pragma command /** @jsxFrag JSXSlack.Fragment */.

/** @jsx JSXSlack.h */
/** @jsxFrag JSXSlack.Fragment */
import JSXSlack from '@speee-js/jsx-slack'

const Header = ({ children }) => (
  <>
    <Section>
      <b>{children}</b>
    </Section>
    <Divider />
  </>
)

:warning: TypeScript cannot customize the factory method for fragment syntax. (Microsoft/TypeScript#20469) Please use <Fragment> component as usual.

jsxslack.fragment template literal tag

You should use jsxslack.fragment template literal tag instead of jsxslack when you want to create HOC or custom block with prefering template literal to JSX transpiler.

// Header.js
import { jsxslack } from '@speee-js/jsx-slack'

const Header = ({ children }) => jsxslack.fragment`
  <Section>
    <b>${children}</b>
  </Section>
  <Divider />
`
export default Header

<Fragment> built-in component does not have to use because the parser allows multiple elements on the root.

A defined component may use in jsxslack tag as below:

import { jsxslack } from '@speee-js/jsx-slack'
import Header from './Header'

console.log(jsxslack`
  <Blocks>
    <${Header}>
      <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.

Note about dialog components

<Select> and similar components are provided by the both of Block Kit and Dialog.

These within template literal will be resolved by the container component <Blocks> and <Dialog> smartly, but the most use cases of jsxslack.fragment won't define the container so jsx-slack prefers Block Kit components.

You can use dialog components correctly by adding prefix Dialog.XXXXXX. (e.g. <Dialog.Select>)

Similar projects

  • slack-jsx - Compose Slack messages from JSX Components instead of writing JSON.
  • react-chat-renderer - React renderer implementation for building rich Slack messages using JSX.

Author

Managed by Speee, Inc. Speee, Inc. (@speee)

  • @yhatt Yuki Hattori (@yhatt) - Maintainer

Licnese

MIT License

RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free