# Button

> A flexible action button that triggers widget actions.

**URL:** https://inference.sh/docs/agents/widgets/button
**Last updated:** 2026-09-18

---

A flexible action button that triggers widget actions.

## Preview

```
[Submit] [Cancel]
```

## Usage

```go
node := models.WidgetNode{
    Type:    models.WidgetNodeTypeButton,
    Label:   "Click Me",
    Variant: "default",
    OnClickAction: &models.WidgetAction{
        Type:    "button_click",
        Payload: map[string]interface{}{"source": "inline"},
    },
}
```

## Props

| Name | Type | Description | Default |
|------|------|-------------|---------|
| `type` | `"button"` | Node type | required |
| `label` | `string` | Button text | required |
| `variant` | `string` | Visual style variant | `"default"` |
| `disabled` | `bool` | Disable the button | `false` |
| `onClickAction` | `WidgetAction` | Action to trigger on click | - |

### WidgetAction Properties

| Name | Type | Description |
|------|------|-------------|
| `type` | `string` | Action identifier (e.g., "submit", "cancel") |
| `payload` | `map[string]any` | Optional data to include |
| `loadingBehavior` | `string` | Loading state: "auto", "self", "container", "none" |
| `handler` | `string` | Handler location: "server" (default), "client" |

### Variants

| Variant | Description | Use Case |
|---------|-------------|----------|
| `default` | Primary action style | Main actions, submit |
| `secondary` | Secondary action style | Alternative actions |
| `outline` | Border only | Cancel, back, dismiss |
| `ghost` | Minimal style | Subtle actions |
| `destructive` | Danger/error style | Delete, remove |
| `link` | Link style | Navigation-like actions |

## Examples

### Primary Button

```go
{Type: models.WidgetNodeTypeButton, Label: "Submit", Variant: "default"}
```

### Secondary Button

```go
{Type: models.WidgetNodeTypeButton, Label: "Save Draft", Variant: "secondary"}
```

### Button with Action

```go
{
    Type:    models.WidgetNodeTypeButton,
    Label:   "Approve",
    Variant: "default",
    OnClickAction: &models.WidgetAction{
        Type:    "approve",
        Payload: map[string]interface{}{
            "request_id": "123",
        },
        LoadingBehavior: "self",
    },
}
```

### Button Row

```go
{
    Type: models.WidgetNodeTypeRow,
    Gap:  2,
    Justify: "end",
    Children: []models.WidgetNode{
        {
            Type:    models.WidgetNodeTypeButton,
            Label:   "Cancel",
            Variant: "outline",
            OnClickAction: &models.WidgetAction{Type: "cancel"},
        },
        {
            Type:    models.WidgetNodeTypeButton,
            Label:   "Confirm",
            Variant: "default",
            OnClickAction: &models.WidgetAction{
                Type:            "confirm",
                LoadingBehavior: "self",
            },
        },
    },
}
```

### Destructive Button

```go
{
    Type:    models.WidgetNodeTypeButton,
    Label:   "Delete",
    Variant: "destructive",
    OnClickAction: &models.WidgetAction{
        Type:            "delete",
        Payload:         map[string]interface{}{"item_id": "456"},
        LoadingBehavior: "self",
    },
}
```

## TypeScript

```typescript
const node: WidgetNode = {
  type: "button",
  label: "Click Me",
  variant: "default",
  onClickAction: {
    type: "click",
    payload: { id: 123 },
    loadingBehavior: "self",
  },
}
```

## Best Practices

1. **Use inline buttons with onClickAction** - Attach actions directly to buttons
2. **Use loadingBehavior: "self"** - Shows spinner on button during async operations
3. **Semantic variants** - Match variant to action meaning (destructive for delete)
4. **Short labels** - 1-3 words (e.g., "Submit", "Save Changes", "Delete Item")
5. **Include payload context** - Add IDs or relevant data in the action payload
