# Components

> Buttons and menus that keep working after the command ends. Build them with ComponentBuilder.

`ComponentBuilder` makes rows of buttons and menus. Unlike a [View](https://ccbot.app/docs/reference/views), its buttons keep working after the command has finished. Use it for panels that people click for days, like a ticket panel or a role menu.

A click goes to one of two places:

| You set | The click runs |
|---|---|
| nothing | A **Button Click / Select Menu Change** event on the dashboard whose custom IDs include this button's `custom_id`. |
| `on_click` or `on_select` | Your own function, in this script. |

Read [Buttons and menus](https://ccbot.app/docs/concepts/buttons-and-menus) to choose between a View and a component.

## ComponentBuilder

Makes an empty builder.

```python
c = ComponentBuilder(interaction=None)
```

Pass `interaction` when you use `private=True`. Then send the builder with `set_components(c)`, or `send_message(channel, ..., components=c)`.

```python
c = ComponentBuilder()
c.add_button("Open a ticket", style="primary", custom_id="ticket-open")
c.add_link_button("Rules", "https://example.com/rules")
send_message("support", "Need help? Press the button.", components=c)
```

Then make an event on the dashboard: **Create → Event**, type **Button Click / Select Menu Change**, custom ID `ticket-open`. Its code runs on every click.

## add_button

Adds a button.

```python
c.add_button(
    label,
    style="primary",
    emoji=...,
    is_disabled=False,
    custom_id=None,
    on_click=None,
    row=None,
    private=False,
)
```

| Argument | What it does |
|---|---|
| `label` | The button text. |
| `style` | `primary`, `secondary`, `success` or `danger`. |
| `emoji` | An emoji on the button. Leave it out for none. |
| `custom_id` | The name the click carries. Needed for every button that is not a link. |
| `on_click` | A `ComponentAction` to run on click. |
| `row` | Which row to put it in. Default is the current row. |
| `private` | `True`: only the member who ran the command can click. |

## add_link_button

Adds a button that opens a website. Link buttons never run code.

```python
c.add_link_button(label, url, emoji=..., is_disabled=False, row=None)
```

## add_text_menu

Adds a menu with your own options.

```python
c.add_text_menu(
    options,
    custom_id=None,
    placeholder=...,
    min_values=0,
    max_values=1,
    is_disabled=False,
    on_select=None,
    row=None,
    private=False,
)
```

`options` is a list of `TextOption(label, value, description=..., emoji=..., default=False)`.

## add_role_menu

Adds a menu that lists the server's roles.

```python
c.add_role_menu(custom_id=None, placeholder=..., min_values=0, max_values=1,
                is_disabled=False, on_select=None, row=None, private=False)
```

## add_user_menu

Adds a menu that lists members. Same arguments as `add_role_menu`.

## add_channel_menu

Adds a menu that lists channels. The first argument is a list of channel types: `text`, `voice`, `category`, `news`, `news-thread`, `public-thread`, `private-thread`, `forum`, `stage`.

```python
c.add_channel_menu(["text", "voice"], custom_id="pick-channel")
```

## add_row

Starts a new row. Later buttons go into it.

```python
c.add_row(row)
c.remove_row(row)
```

Rules: at most 5 rows, at most 5 buttons in a row, and a menu takes a whole row.

## ComponentAction

Runs your own function when the button or menu is used.

```python
ComponentAction(
    type,
    ephemeral,
    callback,
    clickable=0,
    clicked=0,
    auto_defer=True,
    args=[],
)
```

| Argument | What it does |
|---|---|
| `type` | `"create"`: the answer is a new message. `"update"`: the answer changes the message with the button. |
| `ephemeral` | `True`: the new message is visible to the clicker only. |
| `callback` | Your function. |
| `clickable` | How many clicks in total are allowed. `0` means no limit. |
| `auto_defer` | `True`: the bot answers the click for you before the callback runs. |
| `args` | Extra values passed to your function. |

A button's callback gets `(interaction, *args)`. A menu's callback gets `(interaction, values, *args)`.

```python
async def claim(interaction):
    add_roles(interaction.member, "Early Bird")
    await respond_interaction(interaction, "You got the Early Bird role!")

c = ComponentBuilder()
c.add_button("Claim", custom_id="claim-early",
             on_click=ComponentAction("create", True, claim, clickable=10))
set_components(c)
```

> **on_click lives in memory:** An `on_click` function is kept in the bot's memory. After the bot restarts, the button no longer runs it. For panels that must work for weeks, use a dashboard event instead.

## Button

Makes one button on its own, outside a builder.

```python
Button(label, style="primary", emoji=..., is_disabled=False, custom_id=None)
```

## LinkButton

Makes one link button on its own.

```python
LinkButton(label, url, emoji=..., is_disabled=False)
```

## Newer layout parts

Discord's newer message layout uses these parts: `TextDisplay`, `Section`, `Thumbnail`, `MediaGallery`, `Container`, `Separator`, `File`, `Spacing` and `Color`. They are passed straight to Discord, so they follow Discord's own rules.

For most messages, it is easier to design the layout on the dashboard under **Components**, then load it with [`load_components`](https://ccbot.app/docs/reference/response).
