# Modals

> Open a pop-up form, then read what the member typed.

A **modal** is a pop-up form in Discord. It has a title and up to 5 text boxes. You open it in answer to a command or a click. When the member presses **Submit**, a **Modal Submit** event runs with what they typed.

For a walk-through, read [Forms](https://ccbot.app/docs/concepts/forms).

## ModalBuilder

Makes an empty form.

```python
form = ModalBuilder(title, custom_id)
```

| Argument | What it does |
|---|---|
| `title` | The text at the top of the form. |
| `custom_id` | The name the submit carries. Your Modal Submit event listens for it. |

## add_text_input

Adds a text box. Each box gets its own row.

```python
form.add_text_input(
    name,
    label,
    style="short",
    placeholder=...,
    value=...,
    required=True,
    min_length=0,
    max_length=4000,
)
```

| Argument | What it does |
|---|---|
| `name` | The key for this box in `values`. |
| `label` | The text above the box. |
| `style` | `"short"`: one line. `"long"`: a big box for many lines. |
| `placeholder` | Grey hint text in the empty box. |
| `value` | Text already filled in. |
| `required` | `False` lets the member leave it empty. |
| `min_length`, `max_length` | The shortest and longest answer allowed. |

## send_modal

Opens the form. Needs `await`.

```python
await send_modal(form)               # from a command or a component handler
await send_modal(form, interaction)  # from a View button or menu
```

Opening the form **is** the answer to the command or click. Do not defer before it.

> **Slash commands: turn off Show thinking:** A slash command answers Discord at once when **Show "thinking…"** is on. Then a form can no longer open. Turn it off under **Behavior** on the command.

> **Inside a View:** Pass the click as the second argument: `send_modal(form, interaction)`. With one argument the form answers the command, which is already answered, and Discord refuses it.

**Example: a feedback command**

```python
# pre-hook of /feedback, with Show "thinking…" turned off
form = ModalBuilder(title="Send feedback", custom_id="feedback-form")
form.add_text_input("topic", "Topic", placeholder="Bug, idea, other…")
form.add_text_input("details", "Tell us more", style="long", max_length=1000)
await send_modal(form)
```

## values

In a **Modal Submit** event, `values` is a dictionary. Each key is a box `name`. Each value is what the member typed.

```python
# Modal Submit event, custom ID: feedback-form
await defer_response(ephemeral=True)
send_message("feedback", f"**{values['topic']}** from {user.mention}\n{values['details']}")
await respond_interaction(interaction, "Thanks! We got your feedback.")
```

An empty optional box gives `""`.

## get_modal_values

Reads the answers from a submit, as the same dictionary as `values`.

```python
get_modal_values(interaction)
```

You only need it when you have a submit outside a Modal Submit event, for example one you got from `wait_for("modal_submit")`.
