Looking for the chatbot template? It's now here.

Actions

Handle button clicks and interactive card events across platforms.

Actions let you handle button clicks, dropdown selections, and other interactive events from cards. Register handlers with onAction to respond when users interact with your cards.

Handle a specific action

lib/bot.ts
bot.onAction("approve", async (event) => {
  await event.thread.post(`Order approved by ${event.user.fullName}!`);
});

Handle multiple actions

lib/bot.ts
bot.onAction(["approve", "reject"], async (event) => {
  const action = event.actionId === "approve" ? "approved" : "rejected";
  await event.thread.post(`Order ${action} by ${event.user.fullName}`);
});

Catch-all handler

Register a handler without an action ID to catch all actions:

lib/bot.ts
bot.onAction(async (event) => {
  console.log(`Action: ${event.actionId}, Value: ${event.value}`);
});

ActionEvent

The event object passed to action handlers:

PropertyTypeDescription
actionIdstringThe id from the Button or Select component
valuestring (optional)The value from the Button or selected option
userAuthorThe user who clicked
threadThreadThe thread containing the card
messageIdstringThe message containing the card
threadIdstringThread ID
adapterAdapterThe platform adapter
triggerIdstring (optional)Platform trigger ID (used for opening modals)
openModal(modal) => Promise<void>Open a modal dialog
rawunknownPlatform-specific event payload

Pass data with buttons

Use the value prop on buttons to pass extra context to your handler:

lib/bot.tsx
<Button id="report" value="bug">Report Bug</Button>
<Button id="report" value="feature">Request Feature</Button>
lib/bot.ts
bot.onAction("report", async (event) => {
  if (event.value === "bug") {
    // Open bug report flow
  } else if (event.value === "feature") {
    // Open feature request flow
  }
});

Open a modal from an action

Use event.openModal() to open a modal in response to a button click:

lib/bot.tsx
import { Modal, TextInput, Select, SelectOption } from "chat";

bot.onAction("feedback", async (event) => {
  await event.openModal(
    <Modal callbackId="feedback_form" title="Send Feedback" submitLabel="Send">
      <TextInput id="message" label="Your Feedback" multiline />
      <Select id="category" label="Category">
        <SelectOption label="Bug" value="bug" />
        <SelectOption label="Feature" value="feature" />
      </Select>
    </Modal>
  );
});

Modals are currently supported on Slack. Other platforms will receive a no-op or fallback behavior.