Modals
A modal is a pop-up form. You describe it with Modal, render it, and show it:
import { Modal, renderModal } from "@hyperion-js/jsx";
const form = renderModal(
<Modal customId="todo.create" title="Create todo">
<Modal.TextDisplay>Tell us what needs doing.</Modal.TextDisplay>
<Modal.Label text="Name" description="A short, descriptive name">
<Modal.TextInput customId="name" maxLength={100} />
</Modal.Label>
<Modal.Label text="Description">
<Modal.TextInput
customId="description"
style="paragraph"
required={false}
/>
</Modal.Label>
</Modal>,
);Show it with showModal(form). Text inputs are short and required unless you
say otherwise.
There are two kinds of custom ID here. The modal's tells your bot which form was submitted, and each input's is the key you read that field by afterwards.
Pre-filled forms
Want each person to see different starting values? Put the form in a function and pass the values in as props:
import { Modal, renderModal } from "@hyperion-js/jsx";
type TodoFormProps = { initialName?: string };
const TodoForm = ({ initialName = "" }: TodoFormProps) => (
<Modal customId="todo.create" title="Create todo">
<Modal.Label text="Name">
<Modal.TextInput
customId="name"
value={initialName}
maxLength={100}
/>
</Modal.Label>
</Modal>
);
const form = renderModal(<TodoForm initialName="Review the change" />);Every render builds a new form, so one person's values can't leak into another's form. Fetch any suggestions first, then pass them in.
Picking things and uploading files
Labels can hold more than text inputs. Drop in any select menu, or a file upload:
import { Modal, renderModal, StringSelect, UserSelect } from "@hyperion-js/jsx";
const form = renderModal(
<Modal customId="ticket.create" title="New ticket">
<Modal.Label text="Priority">
<StringSelect customId="priority">
<StringSelect.Option label="Low" value="low" />
<StringSelect.Option label="High" value="high" />
</StringSelect>
</Modal.Label>
<Modal.Label text="Assign to">
<UserSelect customId="assignee" required={false} />
</Modal.Label>
<Modal.Label text="Screenshots">
<Modal.FileUpload
customId="screenshots"
maxValues={3}
fileTypes={["image"]}
required={false}
/>
</Modal.Label>
</Modal>,
);The selects are the same ones you use in messages (see
buttons and menus). In a form they're
required unless you pass required={false}, and they can't be disabled.
File uploads only work in modals. Limit what people can upload with
fileTypes: "image", "video", "audio", or an extension like ".pdf".
Good to know
- The submission arrives like any other modal submission, and you read each control by its custom ID. See the discord.js guide on modals.
- Each label wraps exactly one control, and custom IDs must be unique within the form.
- A form holds at most five labels and text displays.
- Radio buttons and checkboxes don't have JSX components yet, because the builders don't support them yet.
- Check permissions again when the submission comes back.
Using Hyperion? A modal handler can keep your form as its template. The modal reference lists every prop.
Back to the JSX guide.