---
title: Workflow button
description: A button that runs a Slack workflow's link trigger.
---

`workflow_button` looks like a regular button with a small lightning-bolt glyph, and carries a
`workflow` object describing the [link trigger](https://docs.slack.dev/tools/deno-slack-sdk/guides/creating-link-triggers/#workflow_buttons)
it runs when clicked.

<Preview
  payload={{
    blocks: [
      {
        type: "actions",
        block_id: "workflow",
        elements: [
          {
            type: "workflow_button",
            action_id: "run_workflow",
            text: { type: "plain_text", text: "Run workflow" },
            workflow: {
              trigger: {
                url: "https://slack.com/shortcuts/Ft0123ABC456/321cba",
                customizable_input_parameters: [
                  { name: "input_parameter_a", value: "Value for input param A" },
                ],
              },
            },
          },
        ],
      },
    ],
  }}
  actions
/>

## Fields

| Prop | Type | Default | Description |
| - | - | - | - |
| `type` | `string` | - | Always `workflow_button`. |
| `text` | `PlainTextElement` | - | The button's label. Truncates around 30 characters. Maximum length is 75 characters. |
| `workflow` | `{ trigger: { url: string; customizable_input_parameters?: { name: string; value: string }[] } }` | - | The link trigger this button runs, and any input values to pass to it. |
| `style?` | `"primary" \| "danger"` | - | `primary` renders green, `danger` renders red. Omit for the default gray style. |
| `accessibility_label?` | `string` | - | Read by screen readers instead of `text`. Maximum length is 75 characters. |
| `confirm?` | `ConfirmationDialog` | - | Shows a confirmation dialog before the click is dispatched. See Confirmation dialogs. |

:::note
Slack's real `block_actions` payload includes `action_id` on a `workflow_button` action, even
though `@slack/types` omits it from the element's own type. Set `action_id` on the element and this
library forwards it in the payload; without one it falls back to `""`.
:::

## Examples

### Primary style

<Preview
  payload={{
    blocks: [
      {
        type: "actions",
        elements: [
          {
            type: "workflow_button",
            action_id: "run_workflow",
            text: { type: "plain_text", text: "Start onboarding" },
            style: "primary",
            workflow: { trigger: { url: "https://slack.com/shortcuts/Ft0123ABC456/321cba" } },
          },
        ],
      },
    ],
  }}
  actions
/>

## Interactivity

:::warning
This is a preview environment, not a real Slack workspace: clicking the button never calls the
trigger URL or runs a real workflow. It only dispatches the `block_actions` payload below, exactly
like a real Slack client would send to your app before the platform runs the workflow.
:::

Clicking the button (after any confirm dialog is accepted) calls `onAction` with a
`workflow_button` action carrying the `workflow` object and text back verbatim:

```json
{
  "type": "workflow_button",
  "action_id": "run_workflow",
  "block_id": "workflow",
  "action_ts": "1706000000.000100",
  "text": { "type": "plain_text", "text": "Run workflow", "emoji": true },
  "workflow": {
    "trigger": {
      "url": "https://slack.com/shortcuts/Ft0123ABC456/321cba",
      "customizable_input_parameters": [
        { "name": "input_parameter_a", "value": "Value for input param A" }
      ]
    }
  },
  "style": "primary"
}
```

`style` is only included when the element sets it. A workflow button doesn't write to
`state.values`: it's a one-shot action.

## Related

**[Button](/elements/button)**

The plain button this element visually extends.

**[Confirmation dialogs](/elements/confirmation-dialogs)**

Add a confirm step to any element with the `confirm` object.

**[Elements overview](/elements/index)**

Where each element can live, and how `action_id` and `block_id` fit together.
