> ## Documentation Index
> Fetch the complete documentation index at: https://www.chapterjs.org/llms.txt
> Use this file to discover all available pages before exploring further.

# modal()

> Everything a form file declares, every kind of field, and what the run function receives for each

`modal()` declares a form, from any file of `src/`; the name of its export is its id. It takes one object, `ModalConfig`, and types `fields` in `run` from it.

```ts src/components/feedback.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { modal } from 'chapterjs';

export default modal({
  title: 'Feedback',
  fields: {
    text: { type: 'text', label: 'What do you think?', style: 'paragraph' },
  },
  async run({ interaction, fields }) {
    await interaction.reply({ content: `Thanks! You wrote: ${fields.text}`, ephemeral: true });
  },
});
```

> [!NOTE]
>
> How to write a form, open it and read what was filled in is in the [guide](https://www.chapterjs.org/components/modals.md). This page lists what exists. The place (`where`, `PlaceOf`...) is on the [button() page](https://www.chapterjs.org/reference/button.md#the-place).

## modal()

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
modal<Fields extends ModalFields, Data extends DataShape = {}, Where extends ComponentWhere = 'guild'>(config: ModalConfig<Fields, Data, Where>): ModalDeclaration<Fields, Data>
```

Declares a form. Export the result from any file of `src/`: the name of the export is what tells the form apart, so you never write an id.

### ModalDeclaration

What `modal()` returns: a declaration the framework finds in the exports of a file. Import it where someone uses a command or a component, and open it: `interaction.showModal(report({ userId }))`, or `interaction.showModal(feedback)` for a form without data.

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
type ModalDeclaration<Fields extends ModalFields = ModalFields, Data extends DataShape = {}> = { readonly config: unknown } &
  ({} extends Data
    ? ((options?: ModalInstanceOptions<Fields>) => ModalComponent) & ModalComponent
    : {} extends DataInputOf<Data>
      ? ((data?: DataInputOf<Data>, options?: ModalInstanceOptions<Fields>) => ModalComponent) & ModalComponent
      : (data: DataInputOf<Data>, options?: ModalInstanceOptions<Fields>) => ModalComponent)
```

**config** `unknown`

What the file gave to `modal()`, not checked yet.

### ModalInstanceOptions

What a form is opened with: its data, and what some fields hold.

**values** `ModalPrefill\<Fields\>`

What some fields hold when the form opens.

### ModalPrefill

What a form can hold when it opens: a value for some of its fields. A `string` for a `text`, a list of values for a `select` or `checkboxes`, one value for a `radio`, a `boolean` for a `checkbox`. The other kinds of fields can't be filled in advance.

## ModalConfig

What a modal file gives to `modal()`.

**title** `DynamicText` *required*

The title of the form (45 characters at most): written as is, or a function of `t` and the data, run when the form opens. See [DynamicText](https://www.chapterjs.org/reference/messages.md#dynamictext).

**fields** `ModalFields` *required*

The fields, by name (1 to 5). `run` receives them under the same names.

**run** `(context: ModalContext\<Fields, Data, Where\>) =\> unknown` *required*

What to do when someone sends the form.

**data** `DataShape`

What the form carries from the code that opens it to the code that runs when it is sent: a name and a kind for each value. Given when the form is opened, received typed in `run`.

**where** `ComponentWhere`

Where the form can be sent from: `'guild'` (servers, the default), `'dm'` (private messages with the bot) or `'both'`. What `run` receives follows it.

**ephemeral** `boolean`

Make the answers of the form only visible to who sent it. When a component of a message only the person sees opened it, they already are.

[Discord documentation](https://docs.discord.com/developers/interactions/receiving-and-responding#interaction-response-object-modal)

## Fields

### ModalFields

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
type ModalFields = Readonly<Record<string, ModalField>>
```

The fields of a form, by name (5 at most). A name is how your code reads the field (`fields.reason`): letters, digits and `_`.

### ModalField

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
type ModalField = TextField | SelectField | EntityField | FilesField | RadioField | CheckboxesField | CheckboxField | NoteField
```

One field of a form. Every field but a note has:

**label** `DynamicText` *required*

The name of the field, above it (45 characters at most): written as is, or a function of `t` and the data, run when the form opens.

**description** `DynamicText`

A help text under the label (100 characters at most): a text, or a function of `t` and the data.

[Discord documentation](https://docs.discord.com/developers/components/reference#label)

### TextField

A text the person types.

**type** `'text'` *required*

The kind of field: a text.

**style** `'short' | 'paragraph'`

One line (`'short'`, the default) or several (`'paragraph'`).

**placeholder** `DynamicText`

The text shown while the field is empty (100 characters at most): a text, or a function of `t` and the data.

**required** `boolean`

Whether the person must fill it in. `true` by default.

**minLength** `number`

The shortest text accepted, in characters (0 to 4000).

**maxLength** `number`

The longest text accepted, in characters (1 to 4000).

**value** `string`

What the field holds when the form opens (4000 characters at most).

[Discord documentation](https://docs.discord.com/developers/components/reference#text-input)

### SelectField

A menu of texts you declare.

**type** `'select'` *required*

The kind of field: a menu of texts.

**options** `SelectOptions` *required*

The options (25 at most), written like the options of a [select menu](https://www.chapterjs.org/reference/select.md#selectoptions).

**placeholder** `DynamicText`

The text shown when nothing is picked (150 characters at most): a text, or a function of `t` and the data.

**min** `number`

How many options must be picked at least (0 to 25). 1 by default.

**max** `number`

How many options can be picked at most (1 to 25). 1 by default.

**required** `boolean`

Whether something must be picked. `true` by default.

### EntityField

A menu of users, roles, users and roles, or channels of the server.

**type** `'user' | 'role' | 'mentionable' | 'channel'` *required*

The kind of field: what Discord lists.

**placeholder** `DynamicText`

The text shown when nothing is picked (150 characters at most): a text, or a function of `t` and the data.

**min** `number`

How many things must be picked at least (0 to 25). 1 by default.

**max** `number`

How many things can be picked at most (1 to 25). 1 by default.

**required** `boolean`

Whether something must be picked. `true` by default.

**channelTypes** `readonly ChannelType[]`

For a menu of channels: the kinds of channels listed. All by default.

### FilesField

Files the person uploads.

**type** `'files'` *required*

The kind of field: files to upload.

**min** `number`

How many files must be uploaded at least (0 to 10). 1 by default.

**max** `number`

How many files can be uploaded at most (1 to 10). 1 by default.

**required** `boolean`

Whether files must be uploaded. `true` by default.

**fileTypes** `readonly string[]`

The kinds of files accepted: `'image'`, `'video'`, `'audio'`, or extensions like `'.pdf'` (10 at most).

[Discord documentation](https://docs.discord.com/developers/components/reference#file-upload)

### RadioField

One choice among a few, shown as radio buttons.

**type** `'radio'` *required*

The kind of field: one choice among 2 to 10.

**options** `SelectOptions` *required*

The choices (2 to 10), written like the options of a select menu.

**required** `boolean`

Whether a choice must be made. `true` by default.

[Discord documentation](https://docs.discord.com/developers/components/reference#radio-group)

### CheckboxesField

Several choices among a few, shown as checkboxes.

**type** `'checkboxes'` *required*

The kind of field: several choices among 1 to 10.

**options** `SelectOptions` *required*

The choices (1 to 10), written like the options of a select menu.

**min** `number`

How many must be checked at least (0 to 10). 1 by default.

**max** `number`

How many can be checked at most (1 to 10). All by default.

**required** `boolean`

Whether something must be checked. `true` by default.

[Discord documentation](https://docs.discord.com/developers/components/reference#checkbox-group)

### CheckboxField

One checkbox: yes or no.

**type** `'checkbox'` *required*

The kind of field: one checkbox.

**default** `boolean`

Whether it is checked when the form opens.

[Discord documentation](https://docs.discord.com/developers/components/reference#checkbox)

### NoteField

A text shown in the form, which nobody fills in.

**type** `'note'` *required*

The kind of field: a text to read.

**content** `DynamicText` *required*

The text, with Markdown: written as is, or a function of `t` and the data.

[Discord documentation](https://docs.discord.com/developers/components/reference#text-display)

## What run receives

### ModalContext

What `run` receives when the form is sent: the place as [PlaceOf](https://www.chapterjs.org/reference/button.md#placeof) gives it with a [ModalInteraction](https://www.chapterjs.org/reference/interaction.md#modalinteraction), and:

**user** `User` *required*

Who sent the form.

**fields** `FieldValuesOf\<Fields\>` *required*

What the person filled in.

**data** `DataValuesOf\<Data\>` *required*

What the form carries, as declared in `data`.

**message** `Message | null` *required*

The message whose button or menu opened the form; `null` when a command did.

### FieldValuesOf

```ts theme={"theme":{"light":"github-light","dark":"vesper"}}
type FieldValuesOf<Fields extends ModalFields> = { [Name in keyof Fields]: FieldValue<Fields[Name]> }
```

What the person filled in, typed field by field. Notes are not there.

### FieldValue

What `run` receives for a field, from its declaration:

| Field | `FieldValue` |
| - | - |
| `TextField` | `string`, or `string \| undefined` with `required: false` |
| `SelectField` | `OptionValue<Options>[]` |
| `EntityField` | `User[]`, `Role[]`, `(User \| Role)[]` or `Channel[]` |
| `FilesField` | [`Attachment`](https://www.chapterjs.org/reference/data#attachment)`[]` |
| `RadioField` | `OptionValue<Options>`, or `\| undefined` with `required: false` |
| `CheckboxesField` | `OptionValue<Options>[]` |
| `CheckboxField` | `boolean` |

[Discord documentation](https://docs.discord.com/developers/interactions/receiving-and-responding#interaction-object-modal-submit-data-structure)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.