Sunar

Using Components

Learn how to add interactivity to your application using Discord components.

Before you start using components, make sure you are handling interactions. Refer to the Interactions handling guide for more information.

Discord apps support three types of message components: layout components, content components, and interactive components. Each type of component has its own purpose and use cases.

Display Components

First, let's create a container component with a text display component inside it, a user select menu, and a button:

import { Slash, execute } from "sunar";
import { ContainerBuilder, UserSelectMenuBuilder, ButtonStyle, MessageFlags } from "discord.js";

const slash = new Slash({
    name: "component-example",
    description: "Example of using components"
});

execute(slash, async (interaction) => {
    const exampleContainer = new ContainerBuilder()
    	.setAccentColor(0x0099ff)
    	.addTextDisplayComponents((textDisplay) =>
    		textDisplay.setContent(
    			'This text is inside a Text Display component! You can use **any __markdown__** available inside this component too.',
    		),
    	)
    	.addActionRowComponents((actionRow) =>
    		actionRow.setComponents(new UserSelectMenuBuilder().setCustomId('exampleSelect').setPlaceholder('Select users')),
    	)
    	.addSeparatorComponents((separator) => separator)
    	.addSectionComponents((section) =>
    		section
    			.addTextDisplayComponents(
    				(textDisplay) =>
    					textDisplay.setContent(
    						'This text is inside a Text Display component! You can use **any __markdown__** available inside this component too.',
    					),
    				(textDisplay) => textDisplay.setContent('And you can place one button or one thumbnail component next to it!'),
    			)
    			.setButtonAccessory((button) =>
    				button.setCustomId('exampleButton').setLabel('Button inside a Section').setStyle(ButtonStyle.Primary),
    			),
    	);

    await channel.send({
    	components: [exampleContainer],
    	flags: MessageFlags.IsComponentsV2,
    });
});

export { slash };

This example is adapted from the official discord.js guide, demonstrating how to create structured and interactive message layouts using the new Components V2 API.

Now, let's handle the interactions for user select menu and button:

import { Button, SelectMenu, Slash, execute } from 'sunar';
import { ContainerBuilder, UserSelectMenuBuilder, ButtonStyle, MessageFlags } from 'discord.js';

const slash = new Slash({
    name: 'component-example',
    description: 'Example of using components'
});

execute(slash, async (interaction) => {
    const exampleContainer = new ContainerBuilder()
    	.setAccentColor(0x0099ff)
    	.addTextDisplayComponents((textDisplay) =>
    		textDisplay.setContent(
    			'This text is inside a Text Display component! You can use **any __markdown__** available inside this component too.',
    		),
    	)
    	.addActionRowComponents((actionRow) =>
    		actionRow.setComponents(new UserSelectMenuBuilder().setCustomId('exampleSelect').setPlaceholder('Select users')),
    	)
    	.addSeparatorComponents((separator) => separator)
    	.addSectionComponents((section) =>
    		section
    			.addTextDisplayComponents(
    				(textDisplay) =>
    					textDisplay.setContent(
    						'This text is inside a Text Display component! You can use **any __markdown__** available inside this component too.',
    					),
    				(textDisplay) => textDisplay.setContent('And you can place one button or one thumbnail component next to it!'),
    			)
    			.setButtonAccessory((button) =>
    				button.setCustomId('exampleButton').setLabel('Button inside a Section').setStyle(ButtonStyle.Primary),
    			),
    	);

    await channel.send({
    	components: [exampleContainer],
    	flags: MessageFlags.IsComponentsV2,
    });
});

const button = new Button({ id: 'exampleButton' });

execute(button, async (interaction) => {
    // Do something...
});

const select = new SelectMenu({
	id: 'exampleSelect',
	type: ComponentType.UserSelect,
});

execute(select, (interaction) => {
	const value = interaction.values.at(0);
	// Do something...
});

export { button, select, slash };

How is this guide?

Last updated on