mcpField
S
slack-block-kit

slack-block-kit

github.com/freightcognitionデザイン・UI449 回インストール2 週間前に更新
リポジトリ

slack-block-kit について

slack-block-kit は、Slack のインターフェースを開発する人向けの Block Kit リファレンススキルです。メッセージ、モーダル、Home タブの JSON 構造を、レイアウトブロックから入力要素まで解説します。

主な機能

  1. 01Block Kit ブロックのリファレンス
  2. 02インタラクティブ要素とメニュー
  3. 03コンポジションオブジェクトとテキスト
  4. 04メッセージ、モーダル、Home タブの各サーフェス

活用シーン

  1. 01Slack メッセージレイアウトの作成
  2. 02モーダルフォームとワークフローの作成
  3. 03Home タブへのインタラクティブコントロールの追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/freightcognition/linehaulai-claude-marketplace --skill slack-block-kit

インストール後、Claude Code で/slack-block-kitを入力して読み込まれたか確認します。

詳細

Slack Block Kit

Block Kit を使用して Slack UI を構築するための専門ガイドです。

概要

Block Kit は、リッチでインタラクティブなメッセージ、モーダル、ホームタブを作成するための Slack の UI フレームワークです。JSON ベースの構造を使用し、次の 3 つの主要コンポーネントで構成されています。

  • ブロック:レイアウト用のコンテナー(Section、Actions、Input、Header など)
  • エレメント:インタラクティブなコンポーネント(ボタン、セレクト、日付ピッカー)
  • コンポジションオブジェクト:テキスト、オプション、確認

サーフェス

Block Kit は次の 3 つのサーフェスで動作します。

サーフェスブロックの最大数用途
メッセージ50通知、ボットの応答、チャンネルへの投稿
モーダル100フォーム、確認、複数ステップのワークフロー
ホームタブ100アプリのダッシュボード、ユーザーごとのコンテンツ

クイックスタート

シンプルなメッセージ
{
  "blocks": [
    {
      "type": "header",
      "text": {
        "type": "plain_text",
        "text": "New Order Received"
      }
    },
    {
      "type": "section",
      "fields": [
        {
          "type": "mrkdwn",
          "text": "*Order ID:*\n#12345"
        },
        {
          "type": "mrkdwn",
          "text": "*Customer:*\nJohn Doe"
        }
      ]
    },
    {
      "type": "actions",
      "elements": [
        {
          "type": "button",
          "text": {
            "type": "plain_text",
            "text": "View Order"
          },
          "style": "primary",
          "action_id": "view_order",
          "value": "12345"
        }
      ]
    }
  ]
}
slack-block-builder を使用する場合(JavaScript)
import { Message, Blocks, Elements } from 'slack-block-builder';

const orderNotification = ({ orderId, customer, channel }) => {
  return Message({ channel, text: 'New Order Received' })
    .blocks(
      Blocks.Header({ text: 'New Order Received' }),
      Blocks.Section()
        .fields([
          `*Order ID:*\n#${orderId}`,
          `*Customer:*\n${customer}`
        ]),
      Blocks.Actions()
        .elements(
          Elements.Button({ text: 'View Order', actionId: 'view_order' })
            .primary()
            .value(orderId)
        )
    )
    .buildToObject();
};

ブロックリファレンス

Header ブロック

タイトル用の大きなテキストを表示します。

{
  "type": "header",
  "text": {
    "type": "plain_text",
    "text": "Budget Performance",
    "emoji": true
  }
}

フィールド:

  • type(必須):常に "header"
  • text(必須):plain_text オブジェクト。最大 150 文字
  • block_id(任意):一意の識別子。最大 255 文字

**サーフェス:**メッセージ、モーダル、ホームタブ

Section ブロック

テキストやアクセサリーに使用できる、最も汎用性の高いブロックです。

{
  "type": "section",
  "text": {
    "type": "mrkdwn",
    "text": "*Project Update*\nThe deployment is complete."
  },
  "accessory": {
    "type": "button",
    "text": {
      "type": "plain_text",
      "text": "View Details"
    },
    "action_id": "view_details"
  }
}

フィールド付き(2 列レイアウト):

{
  "type": "section",
  "fields": [
    {
      "type": "mrkdwn",
      "text": "*Status:*\nApproved"
    },
    {
      "type": "mrkdwn",
      "text": "*Created:*\nDec 15, 2025"
    },
    {
      "type": "mrkdwn",
      "text": "*Priority:*\nHigh"
    },
    {
      "type": "mrkdwn",
      "text": "*Assignee:*\n<@U123ABC>"
    }
  ]
}

フィールド:

  • type(必須):常に "section"
  • text(任意):テキストオブジェクト(mrkdwn または plain_text)。最大 3000 文字
  • fields(任意):テキストオブジェクトの配列(最大 10 個)。各要素は最大 2000 文字
  • accessory(任意):インタラクティブなエレメント 1 個
  • block_id(任意):一意の識別子
  • expand(任意):ブール値。デフォルトでテキストを展開するかどうか

**サーフェス:**メッセージ、モーダル、ホームタブ

Actions ブロック

複数のインタラクティブなエレメントを含みます。

{
  "type": "actions",
  "block_id": "approval_actions",
  "elements": [
    {
      "type": "button",
      "text": {
        "type": "plain_text",
        "text": "Approve"
      },
      "style": "primary",
      "action_id": "approve_request",
      "value": "approved"
    },
    {
      "type": "button",
      "text": {
        "type": "plain_text",
        "text": "Reject"
      },
      "style": "danger",
      "action_id": "reject_request",
      "value": "rejected"
    }
  ]
}

フィールド:

  • type(必須):常に "actions"
  • elements(必須):インタラクティブなエレメントの配列(最大 25 個)
  • block_id(任意):一意の識別子

**サーフェス:**メッセージ、モーダル、ホームタブ

Input ブロック

ユーザー入力を収集します(主にモーダルとホームタブで使用します)。

{
  "type": "input",
  "block_id": "description_input",
  "label": {
    "type": "plain_text",
    "text": "Description"
  },
  "element": {
    "type": "plain_text_input",
    "action_id": "description_value",
    "multiline": true,
    "placeholder": {
      "type": "plain_text",
      "text": "Enter a description..."
    }
  },
  "optional": true,
  "hint": {
    "type": "plain_text",
    "text": "Provide additional context"
  }
}

フィールド:

  • type(必須):常に "input"
  • element(必須):入力エレメント(テキスト入力、セレクト、日付ピッカーなど)
  • label(必須):plain_text オブジェクト。最大 2000 文字
  • block_id(任意):一意の識別子
  • hint(任意):plain_text オブジェクト。最大 2000 文字
  • optional(任意):ブール値。デフォルトは false
  • dispatch_action(任意):ブール値。変更時に block_actions をディスパッチするかどうか

**サーフェス:**モーダル、メッセージ、ホームタブ

Context ブロック

補足的なコンテキスト情報を表示します。

{
  "type": "context",
  "elements": [
    {
      "type": "image",
      "image_url": "https://example.com/avatar.png",
      "alt_text": "User avatar"
    },
    {
      "type": "mrkdwn",
      "text": "Posted by <@U123ABC> on Dec 15, 2025"
    }
  ]
}

フィールド:

  • type(必須):常に "context"
  • elements(必須):画像/テキストエレメントの配列(最大 10 個)
  • block_id(任意):一意の識別子

**サーフェス:**メッセージ、モーダル、ホームタブ

Divider ブロック

ブロック間の視覚的な区切りです。

{
  "type": "divider"
}

**サーフェス:**メッセージ、モーダル、ホームタブ

Image ブロック

画像を表示します。

{
  "type": "image",
  "image_url": "https://example.com/chart.png",
  "alt_text": "Sales chart",
  "title": {
    "type": "plain_text",
    "text": "Q4 Sales Performance"
  }
}

フィールド:

  • type(必須):常に "image"
  • image_url(必須*):公開 URL。最大 3000 文字
  • slack_file(必須*):image_url の代替
  • alt_text(必須):説明。最大 2000 文字
  • title(任意):plain_text オブジェクト。最大 2000 文字
  • block_id(任意):一意の識別子

*image_url または slack_file のいずれかが必須です

**サーフェス:**メッセージ、モーダル、ホームタブ

Markdown ブロック

書式設定された Markdown を表示します(メッセージのみ)。

{
  "type": "markdown",
  "text": "**Important:** This is *formatted* text with `code`."
}

**サーフェス:**メッセージのみ

Rich Text ブロック

構造化されたテキスト表現です。

{
  "type": "rich_text",
  "elements": [
    {
      "type": "rich_text_section",
      "elements": [
        {
          "type": "text",
          "text": "Hello ",
          "style": {
            "bold": true
          }
        },
        {
          "type": "user",
          "user_id": "U123ABC"
        }
      ]
    }
  ]
}

**サーフェス:**メッセージ、モーダル、ホームタブ

Video ブロック

動画プレーヤーを埋め込みます。

{
  "type": "video",
  "title": {
    "type": "plain_text",
    "text": "Product Demo"
  },
  "video_url": "https://example.com/video.mp4",
  "thumbnail_url": "https://example.com/thumb.png",
  "alt_text": "Product demonstration video"
}

**サーフェス:**メッセージ、モーダル、ホームタブ

エレメントリファレンス

Button Element

アクションを実行するためのインタラクティブなボタンです。

{
  "type": "button",
  "text": {
    "type": "plain_text",
    "text": "Click Me",
    "emoji": true
  },
  "action_id": "button_click",
  "value": "button_value",
  "style": "primary"
}

フィールド:

  • type(必須):常に"button"
  • text(必須):plain_textオブジェクト。最大75文字
  • action_id(任意):インタラクションの識別子。最大255文字
  • value(任意):ペイロードの値。最大2000文字
  • style(任意):"primary"(緑)または"danger"(赤)
  • url(任意):開くURL。最大3000文字
  • confirm(任意):確認ダイアログ
  • accessibility_label(任意):スクリーンリーダー用のテキスト。最大75文字

使用先: Section(アクセサリー)、Actions

Static Select Menu

あらかじめ定義されたオプションを表示するドロップダウンです。

{
  "type": "static_select",
  "action_id": "priority_select",
  "placeholder": {
    "type": "plain_text",
    "text": "Select priority"
  },
  "options": [
    {
      "text": {
        "type": "plain_text",
        "text": "High"
      },
      "value": "high"
    },
    {
      "text": {
        "type": "plain_text",
        "text": "Medium"
      },
      "value": "medium"
    },
    {
      "text": {
        "type": "plain_text",
        "text": "Low"
      },
      "value": "low"
    }
  ],
  "initial_option": {
    "text": {
      "type": "plain_text",
      "text": "Medium"
    },
    "value": "medium"
  }
}

フィールド:

  • type(必須):"static_select"
  • action_id(任意):インタラクションの識別子
  • options(必須*):オプションオブジェクトの配列(最大100個)
  • option_groups(必須*):グループ化されたオプション(最大100グループ)
  • initial_option(任意):事前に選択するオプション
  • placeholder(任意):プレースホルダーテキスト。最大150文字
  • confirm(任意):確認ダイアログ
  • focus_on_load(任意):モーダルで自動的にフォーカス

*optionsまたはoption_groupsのいずれかが必須です

External Select Menu

動的に読み込まれるオプションを表示するドロップダウンです。

{
  "type": "external_select",
  "action_id": "customer_select",
  "placeholder": {
    "type": "plain_text",
    "text": "Search customers..."
  },
  "min_query_length": 2
}

フィールド:

  • type(必須):"external_select"
  • action_id(任意):インタラクションの識別子
  • min_query_length(任意):クエリを送信するまでの最小文字数(デフォルトは3)
  • initial_option(任意):事前に選択するオプション
  • placeholder(任意):プレースホルダーテキスト
Users Select Menu

ワークスペースのユーザーを選択します。

{
  "type": "users_select",
  "action_id": "assignee_select",
  "placeholder": {
    "type": "plain_text",
    "text": "Select assignee"
  },
  "initial_user": "U123ABC"
}
Channels Select Menu

パブリックチャンネルを選択します。

{
  "type": "channels_select",
  "action_id": "channel_select",
  "placeholder": {
    "type": "plain_text",
    "text": "Select channel"
  },
  "initial_channel": "C123ABC"
}
Conversations Select Menu

任意の会話(チャンネル、DM、グループ)を選択します。

{
  "type": "conversations_select",
  "action_id": "conversation_select",
  "placeholder": {
    "type": "plain_text",
    "text": "Select conversation"
  },
  "default_to_current_conversation": true
}
Multi-Select Menus

すべての選択メニューには、複数選択できるバリエーションがあります。

  • multi_static_select
  • multi_external_select
  • multi_users_select
  • multi_channels_select
  • multi_conversations_select
{
  "type": "multi_users_select",
  "action_id": "team_select",
  "placeholder": {
    "type": "plain_text",
    "text": "Select team members"
  },
  "max_selected_items": 5
}
Date Picker

日付を選択します。

{
  "type": "datepicker",
  "action_id": "due_date",
  "placeholder": {
    "type": "plain_text",
    "text": "Select due date"
  },
  "initial_date": "2025-12-31"
}
Time Picker

時刻を選択します。

{
  "type": "timepicker",
  "action_id": "meeting_time",
  "placeholder": {
    "type": "plain_text",
    "text": "Select time"
  },
  "initial_time": "14:30"
}
Datetime Picker

日付と時刻をまとめて選択します。

{
  "type": "datetimepicker",
  "action_id": "event_datetime",
  "initial_date_time": 1734307200
}
Checkboxes

オプションから複数選択します。

{
  "type": "checkboxes",
  "action_id": "features_select",
  "options": [
    {
      "text": {
        "type": "plain_text",
        "text": "Email notifications"
      },
      "value": "email",
      "description": {
        "type": "mrkdwn",
        "text": "*Receive daily summary*"
      }
    },
    {
      "text": {
        "type": "plain_text",
        "text": "Slack notifications"
      },
      "value": "slack"
    }
  ],
  "initial_options": [
    {
      "text": {
        "type": "plain_text",
        "text": "Email notifications"
      },
      "value": "email"
    }
  ]
}
Radio Buttons

オプションから1つ選択します。

{
  "type": "radio_buttons",
  "action_id": "urgency_select",
  "options": [
    {
      "text": {
        "type": "plain_text",
        "text": "Urgent"
      },
      "value": "urgent"
    },
    {
      "text": {
        "type": "plain_text",
        "text": "Standard"
      },
      "value": "standard"
    }
  ],
  "initial_option": {
    "text": {
      "type": "plain_text",
      "text": "Standard"
    },
    "value": "standard"
  }
}
Plain Text Input

1行または複数行のテキスト入力です。

{
  "type": "plain_text_input",
  "action_id": "comment_input",
  "placeholder": {
    "type": "plain_text",
    "text": "Enter your comment..."
  },
  "multiline": true,
  "min_length": 10,
  "max_length": 500
}
Number Input

入力値を検証する数値入力です。

{
  "type": "number_input",
  "action_id": "quantity_input",
  "is_decimal_allowed": false,
  "min_value": "1",
  "max_value": "100",
  "placeholder": {
    "type": "plain_text",
    "text": "Enter quantity"
  }
}
URL Input

入力値を検証するURL入力です。

{
  "type": "url_text_input",
  "action_id": "website_input",
  "placeholder": {
    "type": "plain_text",
    "text": "https://example.com"
  }
}
Email Input

入力値を検証するメールアドレス入力です。

{
  "type": "email_text_input",
  "action_id": "email_input",
  "placeholder": {
    "type": "plain_text",
    "text": "[email protected]"
  }
}
Rich Text Input

書式付きテキスト入力です。

{
  "type": "rich_text_input",
  "action_id": "content_input",
  "placeholder": {
    "type": "plain_text",
    "text": "Write your content..."
  }
}
File Input

ファイルをアップロードします(モーダルのみ)。

{
  "type": "file_input",
  "action_id": "attachment_input",
  "filetypes": ["pdf", "png", "jpg"],
  "max_files": 3
}
Overflow Menu

補助的なアクション用のコンパクトなメニューです。

{
  "type": "overflow",
  "action_id": "more_actions",
  "options": [
    {
      "text": {
        "type": "plain_text",
        "text": "Edit"
      },
      "value": "edit"
    },
    {
      "text": {
        "type": "plain_text",
        "text": "Delete"
      },
      "value": "delete"
    }
  ]
}

Composition Objects

Text Object

Block Kit全体でテキストコンテンツに使用します。

プレーンテキスト:

{
  "type": "plain_text",
  "text": "Hello, world!",
  "emoji": true
}

Markdown(mrkdwn):

{
  "type": "mrkdwn",
  "text": "*Bold* _italic_ ~strike~ `code` <https://example.com|link>"
}
Confirmation Dialog

破壊的なアクションを実行する前の確認です。

{
  "title": {
    "type": "plain_text",
    "text": "Confirm Delete"
  },
  "text": {
    "type": "mrkdwn",
    "text": "Are you sure you want to delete this item? This cannot be undone."
  },
  "confirm": {
    "type": "plain_text",
    "text": "Delete"
  },
  "deny": {
    "type": "plain_text",
    "text": "Cancel"
  },
  "style": "danger"
}
Option Object

選択メニュー、チェックボックス、ラジオボタンに使用します。

{
  "text": {
    "type": "plain_text",
    "text": "Option Label"
  },
  "value": "option_value",
  "description": {
    "type": "plain_text",
    "text": "Optional description"
  },
  "url": "https://example.com"
}
Option Group

選択メニュー用のグループ化されたオプションです。

{
  "label": {
    "type": "plain_text",
    "text": "Group Label"
  },
  "options": [
    {
      "text": {
        "type": "plain_text",
        "text": "Option 1"
      },
      "value": "option_1"
    }
  ]
}

Modal Reference

モーダルを開く
{
  "type": "modal",
  "callback_id": "feedback_modal",
  "title": {
    "type": "plain_text",
    "text": "Submit Feedback"
  },
  "submit": {
    "type": "plain_text",
    "text": "Submit"
  },
  "close": {
    "type": "plain_text",
    "text": "Cancel"
  },
  "blocks": [
    {
      "type": "input",
      "block_id": "feedback_type",
      "label": {
        "type": "plain_text",
        "text": "Feedback Type"
      },
      "element": {
        "type": "static_select",
        "action_id": "type_select",
        "options": [
          {
            "text": {
              "type": "plain_text",
              "text": "Bug Report"
            },
            "value": "bug"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "Feature Request"
            },
            "value": "feature"
          }
        ]
      }
    },
    {
      "type": "input",
      "block_id": "feedback_content",
      "label": {
        "type": "plain_text",
        "text": "Description"
      },
      "element": {
        "type": "plain_text_input",
        "action_id": "content_input",
        "multiline": true
      }
    }
  ]
}
モーダルのフィールド
  • type(必須):常に"modal"
  • title(必須):plain_text。最大24文字
  • blocks(必須):ブロックの配列(最大100個)
  • callback_id(任意):view_submissionの識別子
  • submit(任意):送信ボタンのテキスト。最大24文字
  • close(任意):閉じるボタンのテキスト。最大24文字
  • private_metadata(任意):送信時に渡される文字列。最大3000文字
  • clear_on_close(任意):閉じるときにすべてのビューをクリア
  • notify_on_close(任意):view_closedイベントを送信
  • external_id(任意):カスタム識別子
  • submit_disabled(任意):初期状態で送信ボタンを無効化

slack-block-builder Library

インストール
npm install slack-block-builder
インポート
import {
  Message,
  Modal,
  HomeTab,
  Blocks,
  Elements,
  Bits,
  Md
} from 'slack-block-builder';
メッセージの構築
const message = Message({ channel: 'C123ABC', text: 'Fallback text' })
  .blocks(
    Blocks.Header({ text: 'Welcome!' }),
    Blocks.Section({ text: 'Hello, *world*!' }),
    Blocks.Divider(),
    Blocks.Actions()
      .elements(
        Elements.Button({ text: 'Click Me', actionId: 'click' })
          .primary()
      )
  )
  .buildToObject();
モーダルの構築
const modal = Modal({ title: 'My Form', callbackId: 'form_submit' })
  .submit('Save')
  .close('Cancel')
  .blocks(
    Blocks.Input({ label: 'Name', blockId: 'name_block' })
      .element(
        Elements.TextInput({ actionId: 'name_input' })
          .placeholder('Enter your name')
      ),
    Blocks.Input({ label: 'Priority', blockId: 'priority_block' })
      .element(
        Elements.StaticSelect({ actionId: 'priority_select' })
          .options(
            Bits.Option({ text: 'High', value: 'high' }),
            Bits.Option({ text: 'Medium', value: 'medium' }),
            Bits.Option({ text: 'Low', value: 'low' })
          )
      )
  )
  .buildToObject();
Markdownヘルパー
import { Md } from 'slack-block-builder';

Md.bold('text')           // *text*
Md.italic('text')         // _text_
Md.strike('text')         // ~text~
Md.code('text')           // `text`
Md.codeBlock('text')      // ```text```
Md.link('url', 'text')    // <url|text>
Md.user('U123')           // <@U123>
Md.channel('C123')        // <#C123>
Md.emoji('smile')         // :smile:
Md.listBullet(['a', 'b']) // • a\n• b
ビルドメソッド
// Returns JavaScript object
modal.buildToObject();

// Returns JSON string
modal.buildToJSON();

// Returns only blocks array
modal.getBlocks();

ベストプラクティス

命名規則
  • action_id:{verb}_{noun} - 例:submit_form、select_priority
  • block_id:{noun}_block - 例:name_block、options_block
  • callback_id:{feature}_{action} - 例:feedback_submit
パフォーマンス
  • メッセージは50ブロック未満にしてください
  • モーダルは100ブロック未満にしてください
  • 選択肢が多い場合(100項目超)は、external_selectを使用してください
  • トラフィックの多いメッセージでは画像の使用を最小限にしてください
アクセシビリティ
  • 画像には必ずalt_textを指定してください
  • アイコン付きボタンにはaccessibility_labelを使用してください
  • 十分な色のコントラストを確保してください
  • 明確でわかりやすいラベルを付けてください
モバイルでの考慮事項
  • テキストは短めにしてください(ボタンでは約30文字で切り詰められます)
  • Sectionブロック内のフィールド数を制限してください(最大2~3個)
  • モバイル版Slackクライアントでテストしてください
  • 複雑な入れ子状のレイアウトは避けてください

よくあるパターン

アクション付き通知
Message({ channel, text: 'New request' })
  .blocks(
    Blocks.Header({ text: 'New Request' }),
    Blocks.Section()
      .fields([
        `*From:*\n${requester}`,
        `*Priority:*\n${priority}`
      ]),
    Blocks.Context()
      .elements([`Submitted ${timestamp}`]),
    Blocks.Divider(),
    Blocks.Actions()
      .elements(
        Elements.Button({ text: 'Approve', actionId: 'approve' }).primary(),
        Elements.Button({ text: 'Reject', actionId: 'reject' }).danger()
      )
  )
  .buildToObject();
バリデーション付きフォームモーダル
Modal({ title: 'Create Task', callbackId: 'task_create' })
  .submit('Create')
  .close('Cancel')
  .blocks(
    Blocks.Input({ label: 'Task Name', blockId: 'name' })
      .element(Elements.TextInput({ actionId: 'name_input' })),
    Blocks.Input({ label: 'Assignee', blockId: 'assignee' })
      .element(Elements.UsersSelect({ actionId: 'assignee_select' })),
    Blocks.Input({ label: 'Due Date', blockId: 'due_date' })
      .element(Elements.DatePicker({ actionId: 'date_select' }))
      .optional(true)
  )
  .buildToObject();
ホームタブのダッシュボード
HomeTab()
  .blocks(
    Blocks.Header({ text: `Welcome, ${userName}!` }),
    Blocks.Section({ text: 'Here are your pending tasks:' }),
    Blocks.Divider(),
    ...tasks.map(task =>
      Blocks.Section({ text: `• ${task.title}` })
        .accessory(
          Elements.Button({ text: 'Complete', actionId: `complete_${task.id}` })
        )
    ),
    Blocks.Divider(),
    Blocks.Actions()
      .elements(
        Elements.Button({ text: 'New Task', actionId: 'new_task' }).primary()
      )
  )
  .buildToObject();

トラブルシューティング

よくあるエラー
エラー原因解決方法
invalid_blocks不正なJSONBlock Kit Builderで検証する
too_many_blocks上限超過50(メッセージ)または100(モーダル)に減らす
invalid_elementブロック内の要素が不適切要素とブロックの互換性を確認する
missing_text必須のテキストがないSectionにテキストまたはフィールドを追加する
検証のヒント
  1. Block Kit BuilderでJSONをテストする
  2. 要素とブロックの互換性を確認する
  3. 必須フィールドが存在することを確認する
  4. 表示上の問題がないか、モバイルでテストする

リソース

リファレンスドキュメント

詳しいガイドについては、references/ディレクトリを参照してください。

外部リソース

コメント