mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-14 10:33:30 +01:00
feat(guide): port legacy guide (#10938)
* feat: initial attempt at porting legacy guide * feat: completion of legacy guide backport * chore: lockfile shenanigans * fix: handle svgs * fix: replace svg with mermaid integration * chore: format * chore: remove unnecssary bullet * chore: cleanup code highlights * chore: explicit return * chore: move display components after interactive components in sidebar * chore: voice * top link should be installation * add docs link to sidebar * feat: subguide-based accent styles * chore: don't list faq twice * chore: mention display components in interactive components * fix: remove unoccs/order rule from guide * chore: redirect to legacy guide instead of /guide root * refactor: use `<kbd>` * refactor: more kbd use * Update apps/guide/content/docs/legacy/app-creation/handling-events.mdx Co-authored-by: Naiyar <137700126+imnaiyar@users.noreply.github.com> * chore: fix typos Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com> * chore: fix typos * chore: fix links regarding secret stores across coding platforms * chore: fix typo * chore: link node method directly Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com> * chore: typos Co-authored-by: Vlad Frangu <me@vladfrangu.dev> * chore: typo Co-authored-by: Vlad Frangu <me@vladfrangu.dev> * fix: prevent v14 changes from being listed twice * chore: prefer relative links * chore: missed link conversion * chore: missed link conversion * chore: fix link * chore: remove legacy code highlight markers * chore: rephrase and extend contributing guidelines * feat(setup): suggest cli flag over dotenv package * chore: move introduction in sidebar better navigation experience if the 'next page' in intro refers to getting started vs. updating/faq * fix: replace outdated link * fix: update voice dependencies * chore: update node install instructions * fix: list in missing access callout * chore: match bun env file format * chore: restore ffmpeg disclaimer * fix: lockfile conflict * chore: action row typo Co-authored-by: Vlad Frangu <me@vladfrangu.dev> * chore: no longer use at-next for pino --------- Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com> Co-authored-by: Naiyar <137700126+imnaiyar@users.noreply.github.com> Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: Context Menus
|
||||
---
|
||||
|
||||
Context Menus are application commands which appear when right clicking or tapping a user or a message, in the Apps submenu.
|
||||
|
||||
<Callout>
|
||||
This page is a follow-up to the [slash commands](../slash-commands/advanced-creation) section. Please carefully read
|
||||
those pages first so that you can understand the methods used in this section.
|
||||
</Callout>
|
||||
|
||||
## Registering context menu commands
|
||||
|
||||
To create a context menu command, use the `ContextMenuCommandBuilder` class. You can then set the type of the context menu (user or message) using the `setType()` method.
|
||||
|
||||
```js
|
||||
const { ContextMenuCommandBuilder, ApplicationCommandType } = require('discord.js');
|
||||
|
||||
const data = new ContextMenuCommandBuilder().setName('User Information').setType(ApplicationCommandType.User);
|
||||
```
|
||||
|
||||
## Receiving context menu command interactions
|
||||
|
||||
Context menus commands, just like slash commands, are received via an interaction. You can check if a given interaction is a context menu by invoking the `isContextMenuCommand()` method, or the `isMessageContextMenuCommand()` and `isUserContextMenuCommand()` methods to check for the specific type of context menu interaction:
|
||||
|
||||
```js
|
||||
client.on(Events.InteractionCreate, (interaction) => {
|
||||
if (!interaction.isUserContextMenuCommand()) return;
|
||||
console.log(interaction);
|
||||
});
|
||||
```
|
||||
|
||||
## Extracting data from context menus
|
||||
|
||||
For user context menus, you can get the targeted user by accessing the `targetUser` or `targetMember` property from the `UserContextMenuCommandInteraction`.
|
||||
|
||||
For message context menus, you can get the targeted message by accessing the `targetMessage` property from the `MessageContextMenuCommandInteraction`.
|
||||
|
||||
```js
|
||||
client.on(Events.InteractionCreate, (interaction) => {
|
||||
if (!interaction.isUserContextMenuCommand()) return;
|
||||
// Get the User's username from context menu
|
||||
const { username } = interaction.targetUser;
|
||||
console.log(username);
|
||||
});
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Context menu commands cannot have subcommands or any options.
|
||||
- Responding to context menu commands functions the same as slash commands. Refer to our [slash command responses](../slash-commands/response-methods) guide for more information.
|
||||
- Context menu command permissions also function the same as slash commands. Refer to our [slash command permissions](../slash-commands/permissions) guide for more information.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
3
apps/guide/content/docs/legacy/interactions/meta.json
Normal file
3
apps/guide/content/docs/legacy/interactions/meta.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Other Interactions"
|
||||
}
|
||||
192
apps/guide/content/docs/legacy/interactions/modals.mdx
Normal file
192
apps/guide/content/docs/legacy/interactions/modals.mdx
Normal file
@@ -0,0 +1,192 @@
|
||||
---
|
||||
title: Modals
|
||||
---
|
||||
|
||||
With modals you can create pop-up forms that allow users to provide you with formatted inputs through submissions. We'll cover how to create, show, and receive modal forms using discord.js!
|
||||
|
||||
<Callout>
|
||||
This page is a follow-up to the [interactions (slash commands) page](../slash-commands/advanced-creation). Please
|
||||
carefully read that section first, so that you can understand the methods used in this section.
|
||||
</Callout>
|
||||
|
||||
## Building and responding with modals
|
||||
|
||||
Unlike message components, modals aren't strictly components themselves. They're a callback structure used to respond to interactions.
|
||||
|
||||
<Callout>
|
||||
You can have a maximum of five `ActionRowBuilder`s per modal builder, and one `TextInputBuilder` within an
|
||||
`ActionRowBuilder`. Currently, you can only use `TextInputBuilder`s in modal action rows builders.
|
||||
</Callout>
|
||||
|
||||
To create a modal you construct a new `ModalBuilder`. You can then use the setters to add the custom id and title.
|
||||
|
||||
```js
|
||||
const { Events, ModalBuilder } = require('discord.js');
|
||||
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
if (interaction.commandName === 'ping') {
|
||||
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
|
||||
|
||||
// TODO: Add components to modal...
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
<Callout>
|
||||
The custom id is a developer-defined string of up to 100 characters. Use this field to ensure you can uniquely define
|
||||
all incoming interactions from your modals!
|
||||
</Callout>
|
||||
|
||||
The next step is to add the input fields in which users responding can enter free-text. Adding inputs is similar to adding components to messages.
|
||||
|
||||
At the end, we then call `ChatInputCommandInteraction#showModal` to display the modal to the user.
|
||||
|
||||
<Callout type="warn">
|
||||
If you're using typescript you'll need to specify the type of components your action row holds. This can be done by specifying the generic parameter in `ActionRowBuilder`:
|
||||
|
||||
```diff
|
||||
- new ActionRowBuilder()
|
||||
+ new ActionRowBuilder<ModalActionRowComponentBuilder>()
|
||||
```
|
||||
|
||||
</Callout>
|
||||
|
||||
```js
|
||||
const { ActionRowBuilder, Events, ModalBuilder, TextInputBuilder, TextInputStyle } = require('discord.js');
|
||||
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
if (interaction.commandName === 'ping') {
|
||||
// Create the modal
|
||||
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
|
||||
|
||||
// Add components to modal
|
||||
|
||||
// Create the text input components
|
||||
const favoriteColorInput = new TextInputBuilder()
|
||||
.setCustomId('favoriteColorInput')
|
||||
// The label is the prompt the user sees for this input
|
||||
.setLabel("What's your favorite color?")
|
||||
// Short means only a single line of text
|
||||
.setStyle(TextInputStyle.Short);
|
||||
|
||||
const hobbiesInput = new TextInputBuilder()
|
||||
.setCustomId('hobbiesInput')
|
||||
.setLabel("What's some of your favorite hobbies?")
|
||||
// Paragraph means multiple lines of text.
|
||||
.setStyle(TextInputStyle.Paragraph);
|
||||
|
||||
// An action row only holds one text input,
|
||||
// so you need one action row per text input.
|
||||
const firstActionRow = new ActionRowBuilder().addComponents(favoriteColorInput);
|
||||
const secondActionRow = new ActionRowBuilder().addComponents(hobbiesInput);
|
||||
|
||||
// Add inputs to the modal
|
||||
modal.addComponents(firstActionRow, secondActionRow);
|
||||
|
||||
// Show the modal to the user
|
||||
await interaction.showModal(modal); // [!code word:showModal]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Restart your bot and invoke the `/ping` command again. You should see a popup form resembling the image below:
|
||||
|
||||

|
||||
|
||||
<Callout type="warn">
|
||||
Showing a modal must be the first response to an interaction. You cannot `defer()` or `deferUpdate()` then show a
|
||||
modal later.
|
||||
</Callout>
|
||||
|
||||
### Input styles
|
||||
|
||||
Currently there are two different input styles available:
|
||||
|
||||
- `Short`, a single-line text entry;
|
||||
- `Paragraph`, a multi-line text entry similar to the HTML `<textarea>`;
|
||||
|
||||
### Input properties
|
||||
|
||||
In addition to the `customId`, `label` and `style`, a text input can be customised in a number of ways to apply validation, prompt the user, or set default values via the `TextInputBuilder` methods:
|
||||
|
||||
```js
|
||||
const input = new TextInputBuilder()
|
||||
// set the maximum number of characters to allow
|
||||
.setMaxLength(1_000)
|
||||
// set the minimum number of characters required for submission
|
||||
.setMinLength(10)
|
||||
// set a placeholder string to prompt the user
|
||||
.setPlaceholder('Enter some text!')
|
||||
// set a default value to pre-fill the input
|
||||
.setValue('Default')
|
||||
// require a value in this input field
|
||||
.setRequired(true);
|
||||
```
|
||||
|
||||
## Receiving modal submissions
|
||||
|
||||
### Interaction collectors
|
||||
|
||||
Modal submissions can be collected within the scope of the interaction that showed it by utilising an `InteractionCollector`, or the `ChatInputCommandInteraction#awaitModalSubmit` promisified method. These both provide instances of the `ModalSubmitInteraction` class as collected items.
|
||||
|
||||
For a detailed guide on receiving message components via collectors, please refer to the [collectors guide](../popular-topics/collectors#interaction-collectors).
|
||||
|
||||
### The interactionCreate event
|
||||
|
||||
To receive a `ModalSubmitInteraction` event, attach an `Client#interactionCreate` event listener to your client and use the `BaseInteraction#isModalSubmit` type guard to make sure you only receive modals:
|
||||
|
||||
```js
|
||||
client.on(Events.InteractionCreate, (interaction) => {
|
||||
if (!interaction.isModalSubmit()) return;
|
||||
console.log(interaction);
|
||||
});
|
||||
```
|
||||
|
||||
## Responding to modal submissions
|
||||
|
||||
The `ModalSubmitInteraction` class provides the same methods as the `ChatInputCommandInteraction` class. These methods behave equally:
|
||||
|
||||
- `reply()`
|
||||
- `editReply()`
|
||||
- `deferReply()`
|
||||
- `fetchReply()`
|
||||
- `deleteReply()`
|
||||
- `followUp()`
|
||||
|
||||
If the modal was shown from a `ButtonInteraction` or `StringSelectMenuInteraction`, it will also provide these methods, which behave equally:
|
||||
|
||||
- `update()`
|
||||
- `deferUpdate()`
|
||||
|
||||
```js
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isModalSubmit()) return;
|
||||
if (interaction.customId === 'myModal') {
|
||||
await interaction.reply({ content: 'Your submission was received successfully!' });
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
<Callout>
|
||||
If you're using typescript, you can use the `ModalSubmitInteraction#isFromMessage` typeguard, to make sure the
|
||||
received interaction was from a `MessageComponentInteraction`.
|
||||
</Callout>
|
||||
|
||||
## Extracting data from modal submissions
|
||||
|
||||
You'll most likely need to read the data sent by the user in the modal. You can do this by accessing the `ModalSubmitInteraction#fields`. From there you can call `ModalSubmitFields#getTextInputValue` with the custom id of the text input to get the value.
|
||||
|
||||
```js
|
||||
client.on(Events.InteractionCreate, (interaction) => {
|
||||
if (!interaction.isModalSubmit()) return;
|
||||
|
||||
// Get the data entered by the user
|
||||
const favoriteColor = interaction.fields.getTextInputValue('favoriteColorInput');
|
||||
const hobbies = interaction.fields.getTextInputValue('hobbiesInput');
|
||||
console.log({ favoriteColor, hobbies });
|
||||
});
|
||||
```
|
||||
Reference in New Issue
Block a user