Mentionable select menus allow users to select one or more Discord users or roles from the server. They combine the functionality of user and role select menus into a single component.
Mentionable select menus in djs-core are created using the MentionableSelectMenu class. Each select menu component file in src/components/selects/mentionable/ is automatically registered.
import { MentionableSelectMenu } from "@djs-core/runtime";
export default new MentionableSelectMenu()
.setPlaceholder("Select a user or role")
.run(async (interaction) => {
const selectedUser = interaction.users.first();
const selectedRole = interaction.roles.first();
if (selectedUser) {
await interaction.reply(`You selected user: ${selectedUser.username}`);
} else if (selectedRole) {
await interaction.reply(`You selected role: ${selectedRole.name}`);
}
});
Mentionable select menus can allow users to select multiple users and/or roles:
import { MentionableSelectMenu } from "@djs-core/runtime";
export default new MentionableSelectMenu()
.setPlaceholder("Select users or roles")
.setMinValues(1)
.setMaxValues(5)
.run(async (interaction) => {
const users = interaction.users.map((u) => u.username);
const roles = interaction.roles.map((r) => r.name);
let message = "";
if (users.length > 0) {
message += `Users: ${users.join(", ")}\n`;
}
if (roles.length > 0) {
message += `Roles: ${roles.join(", ")}`;
}
await interaction.reply(message || "Nothing selected");
});
You can access both users and roles from the interaction:
import { MentionableSelectMenu } from "@djs-core/runtime";
export default new MentionableSelectMenu()
.setPlaceholder("Select users or roles to tag")
.run(async (interaction) => {
const userMentions = interaction.users.map((u) => u.toString()).join(" ");
const roleMentions = interaction.roles.map((r) => r.toString()).join(" ");
let message = "";
if (userMentions) {
message += `Users: ${userMentions}\n`;
}
if (roleMentions) {
message += `Roles: ${roleMentions}`;
}
await interaction.reply(message || "Nothing selected");
});
You can check what type of mentionable was selected:
import { MentionableSelectMenu } from "@djs-core/runtime";
export default new MentionableSelectMenu()
.setPlaceholder("Select a user or role")
.run(async (interaction) => {
const selectedUser = interaction.users.first();
const selectedRole = interaction.roles.first();
if (selectedUser) {
await interaction.reply({
content: `Selected a user: ${selectedUser.username} (${selectedUser.id})`,
});
} else if (selectedRole) {
await interaction.reply({
content: `Selected a role: ${selectedRole.name} (${selectedRole.id})`,
});
}
});
For users selected in a server, you can also access guild member information:
import { MentionableSelectMenu } from "@djs-core/runtime";
export default new MentionableSelectMenu()
.setPlaceholder("Select users or roles")
.run(async (interaction) => {
if (!interaction.inGuild()) {
await interaction.reply("This menu only works in servers!");
return;
}
let message = "";
if (interaction.users.size > 0) {
const members = interaction.members.map((m) => m.displayName);
message += `Members: ${members.join(", ")}\n`;
}
if (interaction.roles.size > 0) {
const roles = interaction.roles.map((r) => r.name);
message += `Roles: ${roles.join(", ")}`;
}
await interaction.reply(message || "Nothing selected");
});
Mentionable select menus are typically sent as part of a command response:
import { Command, MentionableSelectMenu } from "@djs-core/runtime";
import { ActionRowBuilder } from "discord.js";
import mentionableSelect from "../../components/selects/mentionable/tag";
export default new Command()
.setDescription("Tag users or roles")
.run(async (interaction) => {
const row = new ActionRowBuilder<MentionableSelectMenu>().addComponents(
mentionableSelect,
);
await interaction.reply({
content: "Select users or roles to tag:",
components: [row],
});
});
Mentionable select menus can receive custom data. Important: The data is set when you use the select menu from a command or another component, not in the component definition.
import { MentionableSelectMenu } from "@djs-core/runtime";
export default new MentionableSelectMenu<{ action: string }>()
.setPlaceholder("Select users or roles to notify")
.run(async (interaction, data) => {
const users = interaction.users.map((u) => u.username);
const roles = interaction.roles.map((r) => r.name);
await interaction.reply(
`Performing ${data.action} for users: ${users.join(", ") || "none"} and roles: ${roles.join(", ") || "none"}`,
);
});
import { Command, MentionableSelectMenu } from "@djs-core/runtime";
import { ActionRowBuilder } from "discord.js";
import notifySelect from "../../components/selects/mentionable/notify";
export default new Command()
.setDescription("Send notifications")
.run(async (interaction) => {
const row = new ActionRowBuilder<MentionableSelectMenu>().addComponents(
notifySelect.setData({ action: "send_notification" }),
);
await interaction.reply({
content: "Select users or roles to notify:",
components: [row],
});
});
Control how many mentionables can be selected:
import { MentionableSelectMenu } from "@djs-core/runtime";
export default new MentionableSelectMenu()
.setPlaceholder("Select 1-3 users or roles")
.setMinValues(1)
.setMaxValues(3)
.run(async (interaction) => {
const totalSelected = interaction.users.size + interaction.roles.size;
await interaction.reply(`Selected ${totalSelected} mentionable(s)`);
});
Mentionable select menus can be disabled:
import { MentionableSelectMenu } from "@djs-core/runtime";
export default new MentionableSelectMenu()
.setPlaceholder("This menu is disabled")
.setDisabled(true)
.run(async (interaction) => {
await interaction.reply("Menu is disabled");
});