Table of Contents

Modals

The package DisCatSharp.Interactivity is required for this to work.

You probably heard about the modal feature in Discord. It's a feature that allows you to create a popup window that can be used to ask for information from the user. This is a great way to create a more interactive user experience.

The code below shows an example application command on how this could look.

For waiting on submissions and building interactivity-driven modal flows, also read the interactivity modal guide.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using DisCatSharp;
using DisCatSharp.Entities;
using DisCatSharp.Enums;
using DisCatSharp.Interactivity;
using DisCatSharp.Interactivity.Enums;
using DisCatSharp.Interactivity.Extensions;
[SlashCommand("cats_modal", "A modal with questions about cats!")]
public async Task SendCatsModalAsync(InteractionContext ctx)
{
	var builder = new DiscordInteractionModalBuilder();
	builder.WithCustomId("cats_modal");
	builder.WithTitle("Cats");

	List<DiscordStringSelectComponentOption> cats = [new("Yes", "I love cats", isDefault: true), new("No", "I hate cats")];
    builder.AddModalComponents(new DiscordTextDisplayComponent("Cats are the best things"));
	builder.AddLabelComponent(new DiscordLabelComponent("Cats", "Do you like cats?").WithSelectComponent(new DiscordStringSelectComponent("Choose carefully..", cats, customId: "cat_select", minOptions: 1)));
	builder.AddLabelComponent(new DiscordLabelComponent("Like", "What do you like about cats?").WithTextComponent(new(TextComponentStyle.Paragraph, customId: "cat_like")));
	builder.AddLabelComponent(new DiscordLabelComponent("Dislike", "What do you dislike about cats?").WithTextComponent(new(TextComponentStyle.Small, customId: "cat_dislike")));

	await ctx.CreateModalResponseAsync(builder);

	var res = await ctx.Client.GetInteractivity().WaitForModalAsync(builder.CustomId, TimeSpan.FromMinutes(1));

	if (res.TimedOut)
		return;

	await res.Result.Interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource);

	var catSelectChoice = (res.Result.Interaction.Data.ModalComponents
		.OfType<DiscordLabelComponent>()
		.Where(x => x.Component is DiscordStringSelectComponent)
		.FirstOrDefault()?.Component as DiscordStringSelectComponent)?.SelectedValues?.FirstOrDefault();

	var catLikeText = (res.Result.Interaction.Data.ModalComponents
		.OfType<DiscordLabelComponent>()
		.Where(x => x.Component is DiscordTextInputComponent y && y.CustomId is "cat_like")
		.FirstOrDefault()?.Component as DiscordTextInputComponent)?.Value;

	var catDislikeText = (res.Result.Interaction.Data.ModalComponents
		.OfType<DiscordLabelComponent>()
		.Where(x => x.Component is DiscordTextInputComponent y && y.CustomId is "cat_dislike")
		.FirstOrDefault()?.Component as DiscordTextInputComponent)?.Value;

	var webhookBuilder = new DiscordWebhookBuilder().WithV2Components();
	var container = new DiscordContainerComponent([
		new DiscordTextDisplayComponent(builder.Title.Header2()),
		new DiscordTextDisplayComponent("Do you like cats?".Header3() + $"\n{(catSelectChoice ?? "No selection").Italic()}"),
		new DiscordTextDisplayComponent("What do you like about cats?".Header3() + $"\n{(catLikeText ?? "No input").BlockCode()}"),
		new DiscordTextDisplayComponent("What do you dislike about cats?".Header3() + $"\n{(catDislikeText ?? "No input").Italic()}"),
	]);
	webhookBuilder.AddComponents(container);
	await res.Result.Interaction.EditOriginalResponseAsync(webhookBuilder);
}