Using ButtonKit
ButtonKit is an enhanced version of the native Discord.js ButtonBuilder
, designed to simplify the process of creating and handling button interactions in your Discord bot.
It is not recommended to use this to listen for button clicks forever since it creates collectors. For that purpose, it's recommended to use a regular "interactionCreate" event listener.
Handle button clicks
- CommonJS
- ESM
- TypeScript
const { ButtonKit } = require('commandkit');
const { ButtonStyle, ActionRowBuilder } = require('discord.js');
// Create a button
const button = new ButtonKit()
.setEmoji('👍')
.setStyle(ButtonStyle.Primary)
.setCustomId('button'); // Required to use onClick
const buttonRow = new ActionRowBuilder().addComponents(button);
const message = await channel.send({ components: [buttonRow] });
// Listen to the button interaction right away
button.onClick(
(interaction) => {
// Reply to the interaction
interaction.reply('You clicked the button!');
},
{ message },
);
import { ButtonKit } from 'commandkit';
import { ButtonStyle, ActionRowBuilder } from 'discord.js';
// Create a button
const button = new ButtonKit()
.setEmoji('👍')
.setStyle(ButtonStyle.Primary)
.setCustomId('button'); // Required to use onClick
const buttonRow = new ActionRowBuilder().addComponents(button);
const message = await channel.send({ components: [buttonRow] });
// Listen to the button interaction right away
button.onClick(
(interaction) => {
// Reply to the interaction
interaction.reply('You clicked the button!');
},
{ message },
);
import { ButtonKit } from 'commandkit';
import { type ButtonInteraction, ButtonStyle, ActionRowBuilder } from 'discord.js';
// Create a button
const button = new ButtonKit()
.setEmoji('👍')
.setStyle(ButtonStyle.Primary)
.setCustomId('button'); // Required to use onClick
const buttonRow = new ActionRowBuilder<ButtonKit>().addComponents(button);
const message = await channel.send({ components: [buttonRow] });
// Listen to the button interaction right away
button.onClick(
(interaction: ButtonInteraction) => {
// Reply to the interaction
interaction.reply('You clicked the button!');
},
{ message },
);
In the above example, you may notice how similar ButtonKit
is to the native Discord.js ButtonBuilder
class. That's because it's built on top of it. It introduces a new method called onClick
which will allow you to quickly handle button interactions without having to create collectors. CommandKit does that for you!
ButtonKit doesn't work without a custom ID, so ensure you provide one whenever instantiating a button. This is required to keep track of what button was clicked.
Arguments Explained
Here's an empty onClick
method without any arguments:
const myButton = new ButtonKit()
.setCustomId('custom_button')
.setLabel('Click me!')
.setStyle(ButtonStyle.Primary);
myButton.onClick();
The first argument required by this function is your handler function which will acknowledge button clicks (interactions) handled by ButtonKit. You can handle them like so:
myButton.onClick((buttonInteraction) => {
buttonInteraction.reply('You clicked a button!');
});
However, the code above won't actually work since ButtonKit doesn't have any idea where it's supposed to specifically listen button clicks from. To fix that, you need to pass in a second argument, also known as your options which houses all the collector configuration. The message
property is the message that ButtonKit will use to listen for button clicks.
const row = new ActionRowBuilder().addComponents(myButton);
const message = await channel.send({ components: [row] });
myButton.onClick(
(buttonInteraction) => {
buttonInteraction.reply('You clicked a button!');
},
{ message },
);
This also works with interaction replies. Just ensure you pass fetchReply
alongside your components:
const row = new ActionRowBuilder().addComponents(myButton);
const message = await interaction.reply({
components: [row],
fetchReply: true,
});
myButton.onClick(
(buttonInteraction) => {
buttonInteraction.reply('You clicked a button!');
},
{ message },
);
ButtonKit onClick
options
message
- Type:
Message
The message object that ButtonKit uses to listen for button clicks (interactions).
time
(optional)
- Type:
number
- Default:
86400000
The duration (in ms) the collector should run for and listen for button clicks.
autoReset
(optional)
- Type:
boolean
Whether or not the collector should automatically reset the timer when a button is clicked.
Additional optional options
Handle collector end
When setting up an onClick()
method using ButtonKit, you may also want to run some code after the collector ends running. The default timeout is 1 day, but you can modify this in onClickOptions#time
. To handle when the collector ends, you can setup an onEnd()
method like this:
const myButton = new ButtonKit()
.setCustomId('custom_button')
.setLabel('Click me!')
.setStyle(ButtonStyle.Primary);
const row = new ActionRowBuilder().addComponents(myButton);
const message = await interaction.reply({
components: [row],
fetchReply: true,
});
myButton
.onClick(
(buttonInteraction) => {
buttonInteraction.reply('You clicked a button!');
},
{ message },
)
.onEnd(() => {
console.log('Button collector ended.');
myButton.setDisabled(true);
message.edit({ components: [row] });
});
Dispose button collector
This feature is currently only available in the development version.
To dispose the button collector, you can make use of the dispose
method. By disposing the collector like this, your onEnd
handler (if any) will be called automatically.
myButton
.onClick(
(buttonInteraction) => {
buttonInteraction.reply('You clicked a button!');
},
{ message },
)
.onEnd(() => {
console.log('Button collector ended.');
myButton.setDisabled(true);
message.edit({ components: [row] });
});
myButton.dispose();