Components

User Select Menus

Learn how to create and use user select menu components with djs-core.

User select menus allow users to select one or more Discord users from the server. They're useful for tagging users, assigning roles, or creating user-based interactions.

Unlike string select menus that require predefined options, user select menus dynamically show all users in the server. Users can be selected directly from Discord's user picker.

Creating a User Select Menu

User select menus in djs-core are created using the UserSelectMenu class. Each select menu component file in src/components/selects/user/ is automatically registered.

Use user select menus when you need users to select actual Discord users, like tagging people, assigning permissions, or choosing team members. For static options, use string select menus instead.

Basic User Select Menu

import { UserSelectMenu } from "@djs-core/runtime";

export default new UserSelectMenu()
    .setPlaceholder("Select a user")
    .run(async (interaction) => {
        const selectedUser = interaction.users.first();
        if (selectedUser) {
            await interaction.reply(`You selected: ${selectedUser.username}`);
        }
    });

Multiple User Selection

User select menus can allow users to select multiple users:

import { UserSelectMenu } from "@djs-core/runtime";

export default new UserSelectMenu()
    .setPlaceholder("Select users")
    .setMinValues(1)
    .setMaxValues(5)
    .run(async (interaction) => {
        const selectedUsers = interaction.users.map((user) => user.username);
        await interaction.reply(`Selected users: ${selectedUsers.join(", ")}`);
    });

Accessing Selected Users

The interaction.users collection contains all selected users. Here's what's available:

interaction.users
Collection
Collection of all selected User objects - Use .first(), .map(), .forEach(), etc.
interaction.members
Collection
Collection of GuildMember objects (only available in guilds) - Contains server-specific member data
interaction.inGuild()
method
Check if the interaction happened in a server (not DMs) - Returns boolean
import { UserSelectMenu } from "@djs-core/runtime";

export default new UserSelectMenu()
    .setPlaceholder("Select users to mention")
    .run(async (interaction) => {
        const mentions = interaction.users.map((user) => user.toString()).join(" ");
        await interaction.reply(`Mentioned users: ${mentions}`);
    });

Accessing Guild Members

You can also access guild member information if the interaction is in a server:

import { UserSelectMenu } from "@djs-core/runtime";

export default new UserSelectMenu()
    .setPlaceholder("Select a member")
    .run(async (interaction) => {
        if (!interaction.inGuild()) {
            await interaction.reply("This menu only works in servers!");
            return;
        }
        
        const selectedMember = interaction.members.first();
        if (selectedMember) {
            await interaction.reply(
                `Selected member: ${selectedMember.displayName} (${selectedMember.user.username})`,
            );
        }
    });

Using User Select Menus in Commands

User select menus are typically sent as part of a command response:

import { Command, UserSelectMenu } from "@djs-core/runtime";
import { ActionRowBuilder } from "discord.js";
import userSelect from "../../components/selects/user/mention";

export default new Command()
    .setDescription("Mention users")
    .run(async (interaction) => {
        const row = new ActionRowBuilder<UserSelectMenu>().addComponents(userSelect);
        
        await interaction.reply({
            content: "Select users to mention:",
            components: [row],
        });
    });

User Select Menu Data

User 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.

Component Definition (without data)

src/components/selects/user/assign.ts
import { UserSelectMenu } from "@djs-core/runtime";

export default new UserSelectMenu<{ action: string }>()
    .setPlaceholder("Select users to assign")
    .run(async (interaction, data) => {
        const users = interaction.users.map((u) => u.username);
        await interaction.reply(
            `Performing ${data.action} for: ${users.join(", ")}`,
        );
    });

Using Select Menu with Data

src/interactions/commands/assign.ts
import { Command, UserSelectMenu } from "@djs-core/runtime";
import { ActionRowBuilder } from "discord.js";
import assignSelect from "../../components/selects/user/assign";

export default new Command()
    .setDescription("Assign to users")
    .run(async (interaction) => {
        const row = new ActionRowBuilder<UserSelectMenu>().addComponents(
            assignSelect.setData({ action: "assign_role" }),
        );
        
        await interaction.reply({
            content: "Select users to assign:",
            components: [row],
        });
    });

Min and Max Values

Control how many users can be selected:

import { UserSelectMenu } from "@djs-core/runtime";

export default new UserSelectMenu()
    .setPlaceholder("Select 2-5 team members")
    .setMinValues(2)
    .setMaxValues(5)
    .run(async (interaction) => {
        const teamMembers = interaction.users.map((u) => u.username);
        await interaction.reply(
            `Team created with ${teamMembers.length} members: ${teamMembers.join(", ")}`,
        );
    });

Disabled User Select Menu

User select menus can be disabled:

import { UserSelectMenu } from "@djs-core/runtime";

export default new UserSelectMenu()
    .setPlaceholder("This menu is disabled")
    .setDisabled(true)
    .run(async (interaction) => {
        await interaction.reply("Menu is disabled");
    });