Help us understand the problem. What is going on with this article?

Block KitでリッチなSlackアプリを作る -乗換経路案内での実例-

More than 1 year has passed since last update.

はじめに

ナビタイムジャパンは2019年7月2日に、NAVITIMEの乗換機能がSlack上で使えるようになるSlackアプリ「NAVITIME for Slack」をリリースしました。サービスの詳細は、ランディングページをご参照ください。
scrnsht01
「NAVITIME for Slack」のリッチなUIは Block Kit を使用して作られています。本記事は、主に自分のSlackアプリのメッセージをよりリッチにしたい方やBlock Kitに興味がある方に向けて、以下のお話をします。

  • Block Kitの概説
  • 「NAVITIME for Slack」での活用例(Block Kitの実例紹介)
  • ぶつかった問題・得られた知見

前提

本記事ではSlackアプリの作成方法やメッセージ送受信方法の詳しい解説は行いません。
Slackアプリの作り方が知りたい方は、公式記事がとてもわかりやすいのでそちらをご覧ください。
Block Kit を使ってより情報的なレストラン検索コマンドを作ろう: Slackアプリの作成、Slash Commandを受け取る設定、メッセージ送受信の実装方法 の一連の流れがまとめられています。メッセージを読みやすくする手段としてBlock Kitが使われているので、Block Kitの基本的な使い方も学ぶことができます。

Block Kit

概要

Block Kitはリッチなメッセージを構築するためのフレームワークです。Block Kitはライブラリのようなものではなく、APIのインターフェース仕様なので、使用するためにインストールなどの環境構築は一切必要ありません。Block Kitが指定している形式に則ってJsonを構築して送信するだけでSlack上でリッチなメッセージを表示することが可能です。

できること

Block Kitを使用することで、ネイティブアプリのようなUIを作ったり、情報量の多いメッセージをわかりやすく整えたりすることができます。
search_top
search_result
https://github.com/slackapi/app-interaction-patterns でBlock Kitを使用したメッセージのサンプルがgifで確認できるので、一度覗いてみると面白いかと思います。

Block Kit Builderで表示を確認する

表示を確かめるためだけに毎回Jsonをコードに貼り付けて実行して......はなかなか時間がかかります。メッセージのデザインの段階では Block Kit Builder というweb上で動作するプロトタイプツールを使って試行錯誤するのがおすすめです。下図のように左側でプレビューを確認しながら右側で Json を編集することが可能です。作ったメッセージは実際に参加しているワークスペースに投稿することもできます。
Block Kit Builder

メッセージの構造

Block KitはSlackのメッセージをブロックという単位で定義します。
ブロックの内部にはボタン、セレクトメニュー、画像などのエレメントを追加することができます。ブロックには複数の種類があり、ブロックの種類によって格納できるエレメントの種類が異なります。複数のブロックを縦に積んでいくことによって、メッセージを構築していきます。
ブロック・エレメントの詳しい種類が知りたい方は、公式ドキュメントの Reference: Message layout blocksReference: Block elements をご参照ください。

具体例:Jsonとその表示結果

Block Kitの形式に則ったJsonと、その表示結果の例を示します。

sample.json
[
    {
        "type": "actions",
        "elements": [
            {
                "type": "button",
                "text": {
                    "type": "plain_text",
                    "text": "Button element 1",
                    "emoji": true
                },
                "value": "click_me_123"
            },
            {
                "type": "static_select",
                "placeholder": {
                    "type": "plain_text",
                    "text": "Select element 2"
                },
                "options": [
                    {
                        "text": {
                            "type": "plain_text",
                            "text": "Choice 1"
                        },
                        "value": "value-0"
                    },
                    {
                        "text": {
                            "type": "plain_text",
                            "text": "Choice 2"
                        },
                        "value": "value-1"
                    }
                ]
            }
        ]
    },
    {
        "type": "divider"
    },
    {
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "You can add a button alongside text in your message. "
        },
        "accessory": {
            "type": "button",
            "text": {
                "type": "plain_text",
                "text": "Button"
            },
            "value": "click_me_123"
        }
    }
]

表示結果

slack_blockkit
表示をブロックとエレメントに分解してみると、以下の画像のようになります。
1つのブロックの中に、複数のエレメントが配置されています。
slack_blockkit_partsname

Block Kit Builderでいじってみると、より構造がイメージできるかもしれません。
Block Kit Builderで表示を確認

Slackアプリから組み立てたメッセージを送信する

こうして組み立てたメッセージですが、このJsonをそのまま送信しても何も表示されません。
シンプルなtextメッセージを送信できるSlackアプリがすでにあるならば、Slackに送信するJsonのトップレベルに blocks という要素を追加して、そこにBlock Kit Builderで組み立てたJsonを入れてみてください。

例えば、Block Kit Builderで以下のようなブロックの配列を作成したとします。

example-blockkit.json
[
    {
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "これはsection blockです"
        }
    }
]

実際にSlackに送信するのは、メッセージのJsonペイロードに blocks を作り、そこにブロックの配列を格納したJsonです。(メッセージのペイロードの形式は使用するSlack APIによっても異なるかもしれません。)

example-send.json
{
    "channel": "Cxxxxxx",
    "text": "blocks が存在するときはこの内容は無視されるはずです",
    "blocks": // ここにBlock Kit Builderで作成したJsonを入れる
    [
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "これはsection blockです"
            }
        }
    ]
}

作成したJsonをSlackに送信すればBlock Kit Builderで組み立てたメッセージがSlack上で表示されるはずです。blocks が存在するときは text フィールドは通知に使用するフォールバックの文字列として使われ、メッセージの表示上は無視されるようです。(参考: Reference: Message payloads)

なお、現状Block Kitのメッセージに対応しているのは Incoming webhooks, chat.postMessage, chat.postEphemeral, slash command, message actions, URL unfurls です。それ以外の方法でメッセージを送信している場合は表示されないかもしれません。 (参考: Creating rich message layouts)

「NAVITIME for Slack」での活用例

「NAVITIME for Slack」では、Block Kitを活用しています。実例として、本アプリのメッセージの一部をブロックとエレメントに分解してみようと思います。一見複雑な画面でも、分解してみるとブロックとエレメントの組み合わせで構成されていることがわかります。なお、メッセージを構成しているJsonはここに載せると長くなってしまうので、Block Kit Builderのリンク先でご確認ください。

検索ウィンドウ

出発地、到着地、日付、時刻などの情報を入力する部分は、セレクトメニューやボタンを使用することで多くのユーザーが慣れているであろうネイティブアプリの見た目・操作感に近づけています。
search_top_partsname

Block Kit Builderで検索ウィンドウのJsonを確認

乗換経路

乗換経路の案内は概して複雑な情報になりがちなので、マークダウンやアイコン画像を多用して要素を整理しています。
search_result_partsname

Block Kit Builderで乗換経路のJsonを確認
※アイコン画像のURLは Block Kit Builder に用意されているサンプル画像のURLに差し替えています

ぶつかった問題・得られた知見

画像を多用すると表示が遅くなってしまう問題

1つのメッセージ内に、7~10個のimage elementを含むcontext blockを複数個含めて送信したとき、表示に7, 8秒かかってしまうことがありました。レスポンス速度を重視する場合は、画像を多用するのは避けた方がよいかもしれません。
対応策のひとつとして、emojiで代用できるものはemojiを使うことでかなりの速度改善が図れます。

ボタンやセレクトメニューを多用するとスマホの画面が埋まる問題

スマホではボタンやセレクトメニューなどのエレメントが横いっぱいに表示されるので、例えば1つのメッセージ内でボタンを多用すると画面がボタンで埋まってしまいます。実際にSlackアプリを作る時には、スマホでの表示を確かめながら進めていくのをおすすめします。
なお、NAVITIME for SlackではPCでの表示を優先しています。スマホユーザーが乗換検索したいときにはSlackを閉じてネイティブアプリを起動するだろうと判断したためです。
sp_layout

ダイアログ内でBlock Kitのエレメントは使えない

初期はダイアログ内で出発地・到着地・日時を入力するようなUIを考えていたのですが、ダイアログとBlock Kitは別物なので、Block Kitの便利なエレメントはダイアログ内で使用することはできませんでした。
そこでダイアログ内はセレクトメニューの使用のみにとどめ、Block Kitのパーツはダイアログの外に出すようにデザインを変更しました。
dialog

あると思っていたエレメント・オプションが用意されていないこともある

現状エレメントは5種類のようなので、htmlやネイティブアプリでもよく使うパーツがないことがあります。開発時に使いたかったパーツとその代用方法を記載します。

  • ラジオボタン
    • セレクトメニューの static_select タイプで代用
  • 日時用のPicker
    • セレクトメニューの static_select タイプで代用
    • 時と分はひとつのエレメントで指定が理想でした
  • セレクトメニュー の channels_select のオプション指定
    • 「自分がjoinしてるチャンネルのみ表示」などのオプションが指定できるようになると、よりUXが向上しそうです

まとめ

  • Block Kitを使うとJsonを組み立てるだけでリッチな表現が可能になる
  • 画像を多用する場合はレスポンス遅延に注意
  • 実装時にはPCだけではなく、スマホでの表示・使い勝手も確かめるべき

【ご案内】
7/25(木)にナビタイムジャパン(表参道)にてSlack APIのミートアップが開催されます。Slackアプリの開発にご興味のある方はぜひご参加ください!
Slack Dev Meetup Tokyo #1 〜App ディレクトリにアプリを公開しよう〜

navitime_tech
株式会社ナビタイムジャパンの技術に関する情報を発信します。 ※ご意見、お問い合わせは公式サイト (https://www.navitime.co.jp/) からお願いします。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした