Modals
Modals are pop-up forms shown in response to a command or component interaction. Build them with ModalBuilder and read submissions from...
Modals are pop-up forms shown in response to a command or component interaction. Build them with ModalBuilder and read submissions from ModalSubmitInteraction.
Building
import { ModalBuilder, TextInputStyle } from 'athena';
const modal = new ModalBuilder('Feedback', 'feedback-form');
modal.addTextInput({ custom_id: 'subject', style: TextInputStyle.Short, label: 'Subject', required: true, max_length: 100 });
modal.addTextInput({ custom_id: 'body', style: TextInputStyle.Paragraph, label: 'What happened', required: true, max_length: 4000 });
await interaction.createModal(modal.toJSON());Constructor: title (max 45 chars) and custom_id (max 100 chars, reused on submission). Each addTextInput becomes its own row; Discord allows up to 5.
Text input fields
| Field | Notes |
|---|---|
custom_id | identifier within the modal |
style | TextInputStyle.Short or TextInputStyle.Paragraph |
label | shown above the input |
placeholder | hint text |
min_length / max_length | bounds, hard cap 4000 |
required | defaults to false |
value | pre-fill |
File upload component
Discord's modal file upload, wrapped in a label:
modal.addFileUpload({ custom_id: 'screenshot', label: 'Attach a screenshot', min_values: 0, max_values: 3, required: false });Showing a modal
A modal must be the first response to an interaction; you cannot defer first. It works from a command or a component interaction.
async handleCommand(context, interaction) {
await interaction.createModal(modal.toJSON());
}Handling submissions
A submission fires interactionCreate with a ModalSubmitInteraction. Read values from fields:
client.on('interactionCreate', async (interaction) => {
if (!interaction.isModal() || interaction.data.custom_id !== 'feedback-form') return;
const subject = interaction.fields.get('subject');
const body = interaction.fields.get('body');
await interaction.createMessage({ content: `Thanks: ${subject}`, flags: MessageFlags.Ephemeral });
});With the commands framework, implement handleModal and route by custom_id prefix.
Tips
- Encode any context you need into the
custom_id(for examplefeedback-form:<userID>); modals carry no other state across the submit boundary. - You cannot show a second modal in response to a modal submission. Defer or send a normal message instead.