# Button

Button elements are tappable calls-to-action. Each button carries an **action** — what happens when the visitor taps it. Six action kinds.

## Six action kinds

| Action | What it does | When to use |
|---|---|---|
| `next_slide`   | Advance to the next slide in the deck order | Standard "Next" / "Continue" |
| `prev_slide`   | Go back to the previous slide | "Back" |
| `goto_slide`   | Jump to a specific slide by ID | Branching, "Skip to summary" |
| `open_link`    | Open an external URL (configurable target) | "Visit our website", "Schedule a call" |
| `submit_form`  | Submit a form on this slide (or anywhere in the deck) | Form steps where the agent shouldn't auto-submit |
| `agent_intent` | Send a structured message to the agent so it can react in voice | "Tell me more", "Show pricing", "I'm ready" |

## Inspector

The Button element inspector exposes:

<!-- omitted: ParamsTable -->

The action field changes shape based on which kind you pick:

**next_slide / prev_slide:**

```json
{ "kind": "next_slide" }
```

No additional fields.

**goto_slide:**

```json
{ "kind": "goto_slide", "slideId": "slide_xyz" }
```

The inspector shows a slide picker (dropdown of every slide in the deck).

**open_link:**

```json
{
  "kind": "open_link",
  "url": "https://acme.com/pricing",
  "target": "_blank"
}
```

`target`: `_blank` opens in a new tab, `_self` replaces the current tab. Default: `_blank`.

**submit_form:**

```json
{ "kind": "submit_form", "formElementId": "elem_xyz" }
```

Pick the form embed element this button submits. The picker filters to embed elements with `embedKind: "form"` on the same slide (or anywhere in the deck if you allow cross-slide).

**agent_intent:**

```json
{
  "kind": "agent_intent",
  "intent": "show_pricing",
  "data": { "tier": "pro" }
}
```

The agent receives `{ type: "user_intent", intent: "show_pricing", data: { tier: "pro" } }` over its data channel. Useful for "Tell me about plan X" hot-buttons that bypass the visitor having to speak.

## Variants

The three visual variants pull from your deck theme:

- **`primary`** — filled with `theme.colors.accent`, white text.
- **`secondary`** — outline in `theme.colors.accent`, accent text. Best for non-primary CTAs.
- **`ghost`** — no border, no fill. Just text in `theme.colors.text`. Best for footer actions ("Maybe later").

## Schema reference

`Button` element:

<!-- omitted: ParamsTable -->

`ButtonAction` discriminated union:

```ts title="button-action.ts"
type ButtonAction =
  | { kind: "next_slide" }
  | { kind: "prev_slide" }
  | { kind: "goto_slide"; slideId: string }
  | { kind: "open_link"; url: string; target?: "_self" | "_blank" }
  | { kind: "submit_form"; formElementId: string }
  | { kind: "agent_intent"; intent: string; data?: Record<string, unknown> };
```

## Read next

- [Embed](/docs/build/slides/elements/embed) — pair with `submit_form` action
- [Quiz](/docs/build/slides/quiz) — alternative for capturing structured visitor input
- [Script and instructions](/docs/build/slides/script-and-instructions) — agent behavior on `agent_intent`
