ModalBuilder class final

A builder for constructing Discord modal dialogs (popup forms).

The ModalBuilder provides a fluent API for creating interactive modal dialogs that collect user input through TextInput fields, SelectMenu components, and informational TextDisplay elements using Discord's modal specification.

Modals are popup forms that appear when triggered by interactions (like button clicks) and require user input before submission. Each modal must have a unique customId for tracking submissions.

Usage

Create a modal and add input components using method chaining:

final modal = ModalBuilder('user_feedback')
  ..setTitle('Share Your Feedback')
  ..addTextInput(
    customId: 'feedback_text',
    label: 'Your Feedback',
    style: TextInputStyle.paragraph,
    placeholder: 'Tell us what you think...',
    minLength: 10,
    maxLength: 500,
    isRequired: true,
  )
  ..addTextInput(
    customId: 'email',
    label: 'Email (Optional)',
    style: TextInputStyle.short,
    placeholder: 'your.email@example.com',
    isRequired: false,
  );

// Show the modal in response to an interaction
await interaction.showModal(modal);

Features

  • Text Inputs: Short single-line or paragraph multi-line text fields
  • Select Menus: Dropdown selection components for choosing from options
  • Text Display: Non-editable informational text
  • Validation: Built-in min/max length validation for text inputs
  • Flexible Layout: Automatic component organization with labels and descriptions

Examples

Simple feedback form

final modal = ModalBuilder('feedback_form')
  .setTitle('Quick Feedback')
  .addTextInput(
    customId: 'message',
    label: 'Your Message',
    style: TextInputStyle.paragraph,
    placeholder: 'What would you like to tell us?',
    maxLength: 1000,
  );

User registration form

final modal = ModalBuilder('user_registration')
  .setTitle('Create Your Profile')
  .addText('Please fill in all required fields below:')
  .addTextInput(
    customId: 'username',
    label: 'Username',
    style: TextInputStyle.short,
    placeholder: 'Choose a unique username',
    minLength: 3,
    maxLength: 20,
    isRequired: true,
    description: 'Must be 3-20 characters',
  )
  .addTextInput(
    customId: 'display_name',
    label: 'Display Name',
    style: TextInputStyle.short,
    placeholder: 'How should we display your name?',
    maxLength: 32,
    isRequired: true,
  )
  .addTextInput(
    customId: 'bio',
    label: 'Bio',
    style: TextInputStyle.paragraph,
    placeholder: 'Tell us about yourself...',
    maxLength: 500,
    isRequired: false,
    description: 'Optional - max 500 characters',
  );

Support ticket form with select menu

final categoryMenu = SelectMenu(
  customId: 'ticket_category',
  placeholder: 'Choose a category',
  options: [
    SelectMenuOption(label: 'Technical Issue', value: 'tech'),
    SelectMenuOption(label: 'Billing Question', value: 'billing'),
    SelectMenuOption(label: 'Feature Request', value: 'feature'),
    SelectMenuOption(label: 'Other', value: 'other'),
  ],
);

final modal = ModalBuilder('support_ticket')
  .setTitle('Open Support Ticket')
  .addText('We\'re here to help! Please provide details about your issue.')
  .addSelectMenu(
    customId: 'category',
    label: 'Issue Category',
    menu: categoryMenu,
    description: 'Select the category that best matches your issue',
  )
  .addTextInput(
    customId: 'subject',
    label: 'Subject',
    style: TextInputStyle.short,
    placeholder: 'Brief summary of your issue',
    maxLength: 100,
    isRequired: true,
  )
  .addTextInput(
    customId: 'description',
    label: 'Detailed Description',
    style: TextInputStyle.paragraph,
    placeholder: 'Please provide as much detail as possible...',
    minLength: 20,
    maxLength: 2000,
    isRequired: true,
  );

Pre-filled form (editing existing data)

final modal = ModalBuilder('edit_profile')
  .setTitle('Edit Profile')
  .addTextInput(
    customId: 'bio',
    label: 'Biography',
    style: TextInputStyle.paragraph,
    value: existingUser.bio, // Pre-fill with existing value
    maxLength: 500,
  )
  .addTextInput(
    customId: 'location',
    label: 'Location',
    style: TextInputStyle.short,
    value: existingUser.location, // Pre-fill with existing value
    maxLength: 50,
  );

Best Practices

  • Keep it focused: Modals should be quick to fill out (5 fields or fewer)
  • Clear labels: Use descriptive labels that explain what input is expected
  • Helpful placeholders: Provide example text in placeholders
  • Appropriate validation: Set reasonable min/max lengths for text inputs
  • Descriptions: Use descriptions for complex or optional fields
  • Pre-fill when editing: Use the value parameter to pre-populate fields
  • Handle all cases: Always handle both successful submissions and dismissals

See also:

Constructors

ModalBuilder(String _customId)
Creates a new ModalBuilder with the specified customId.

Properties

hashCode int
The hash code for this object.
no setterinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

addSelectMenu({required String label, required SelectMenu menu, String? description}) → void
Adds a select menu (dropdown) to the modal.
addText(String text) → void
Adds non-editable text to the modal.
addTextInput({required String customId, required String label, TextInputStyle style = TextInputStyle.short, String? placeholder, String? value, int? minLength, int? maxLength, bool? isRequired, String? description}) → void
Adds a text input field to the modal.
build() Map<String, dynamic>
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
setTitle(String title) → void
Sets the modal's title.
toString() String
A string representation of this object.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited