Modals
Modals are dialogs that appear over Discord’s UI to collect structured text input from users. They can contain up to 5 text input fields.
Modals can only be shown in response to an interaction (button click, command, etc.) — they cannot be sent directly in a message.
Creating a modal handler
Create a file in src/components/modals/. Its custom ID is set via .setCustomId() and must match what you use when showing the modal.
import { Modal } from "@djs-core/runtime";
export default new Modal() .setCustomId("feedback-modal") .run(async (interaction) => { const name = interaction.fields.getTextInputValue("name-input"); const feedback = interaction.fields.getTextInputValue("feedback-input");
await interaction.reply({ content: `Thanks ${name}! We received your feedback.`, ephemeral: true, }); });Showing a modal
To display a modal, call interaction.showModal() from a command or button handler. Build it using discord.js’s ModalBuilder:
import { Command } from "@djs-core/runtime";import { ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder } from "discord.js";
export default new Command() .setDescription("Submit feedback") .run(async (interaction) => { const modal = new ModalBuilder() .setCustomId("feedback-modal") .setTitle("Give us feedback");
const nameInput = new TextInputBuilder() .setCustomId("name-input") .setLabel("Your name") .setStyle(TextInputStyle.Short) .setRequired(true);
const feedbackInput = new TextInputBuilder() .setCustomId("feedback-input") .setLabel("Your feedback") .setStyle(TextInputStyle.Paragraph) .setRequired(true);
modal.addComponents( new ActionRowBuilder<TextInputBuilder>().addComponents(nameInput), new ActionRowBuilder<TextInputBuilder>().addComponents(feedbackInput), );
await interaction.showModal(modal); });Passing data to a modal
Use .withData<T>() to declare a typed data payload, then .setData() when showing the modal.
import { Modal } from "@djs-core/runtime";
export default new Modal() .withData<{ targetUserId: string }>() .setCustomId("edit-nickname") .run(async (interaction, data) => { const nickname = interaction.fields.getTextInputValue("nickname-input");
await interaction.guild?.members.edit(data.targetUserId, { nick: nickname }); await interaction.reply({ content: "Nickname updated!", ephemeral: true }); });import editNicknameModal from "../../components/modals/edit-nickname";
// In a command or button handler:await interaction.showModal( editNicknameModal.setData({ targetUserId: interaction.targetUser.id }));Data passed via .setData() is stored server-side and retrieved automatically when the modal is submitted. It doesn’t appear in the custom ID visible to the user.