Components¶
Components (Buttons, Select Menus and soon Text Input Fields) can be added to any message by passing them to the components
argument in any .send()
method.
Layout¶
All types of components must be part of Action Rows, which are containers that a message can have. Each message can have up to 5 action rows, with each action row containing a maximum of 5 buttons OR a single select menu.
If you don't really care of the layout in which your components are set, you can pass in directly the components without actually creating the Action Rows - the library will handle it itself. However, if the layout is important for you (let's say, you want a row with 3 buttons, then a row with a select menu and finally another row with 2 buttons), then you will need to specify the layout yourself by either defining the action rows or using the spread_to_rows()
function.
They are organised in a 5x5 grid, so you either have to manage the layout yourself, use spread_to_rows()
where we organise them for you, or have a single component.
If you want to define the layout yourself, you have to put them in an ActionRow()
. The components
parameter need a list of up to five ActionRow()
.
Your list of components will be transformed into ActionRow
s behind the scenes.
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
For simplicity's sake, example one will be used for all examples going forward.
If you want to delete components, you need to pass components=[]
to .edit()
.
Buttons¶
Buttons can be clicked on, or be set as disabled if you wish.
1 2 3 4 5 6 7 |
|
For more information, please visit the API reference here.
Button Styles¶
There are a bunch of colours and styles you can choose from.
The colours correspond to the styles found in ButtonStyle
. Click here for more information.
If you use ButtonStyle.URL
, you can pass a URL to the button with the url
argument. Users who click the button will get redirected to your URL.
1 2 3 4 5 6 7 8 9 |
|
ButtonStyle.URL
does not receive events, or work with callbacks.
Select Menus¶
Sometimes there might be more than a handful options which users need to decide between. That's when a SelectMenu
should probably be used.
Select Menus are very similar to Buttons. The main difference is that you get a list of options to choose from.
If you want to use string options, then you use the StringSelectMenu
. Simply pass a list of strings to options
and you are good to go. You can also explicitly pass SelectOptions
to control the value attribute.
You can also define how many options users can choose by setting min_values
and max_values
.
1 2 3 4 5 6 7 8 9 10 |
|
Note
You can only have up to 25 options in a Select
Alternatively, you can use RoleSelectMenu
, UserSelectMenu
and ChannelSelectMenu
to select roles, users and channels respectively. These select menus are very similar to StringSelectMenu
, but they don't allow you to pass a list of options; it's all done behind the scenes.
For more information, please visit the API reference here.
Responding¶
Now that we know how to send components, we need to learn how to respond to a user when a component is interacted with. There are three ways to respond to components.
If you add your component to a temporary message asking for additional user input, you should probably use bot.wait_for_component()
. These have the downside that, for example, they won't work anymore after restarting your bot. On the positive side, they are defined in the same function where your button is sent, so you can easily use variables that you defined before the user used the component.
Otherwise, you are looking for a persistent callback. For that, you want to define a custom_id
when creating your component.
When responding to a component you need to satisfy Discord either by responding to the context with ctx.send()
or by editing the component with ctx.edit_origin()
.
This function supports checks and timeouts.
In this example, we are checking that the username starts with "a" and clicks the button within 30 seconds. If his username doesn't start with an "a", then we send it an ephemeral message to notify him. If the button times out, we edit the message so that the button is disabled and cannot be clicked anymore.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
You can also use this to check for a normal message instead of a component interaction.
For more information, please visit the API reference here.
You can listen to the on_component()
event and then handle your callback. This works even after restarts!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
If you have a lot of components, putting everything in the on_component()
event can get messy really quick.
Similarly to Option 1, you can define @component_callback
listeners. This works after restarts too.
You have to pass your custom_id
to @component_callback(custom_id)
for the library to be able to register the callback function to the wanted component.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Regex (regular expressions) can be a great way to pass information from the component creation directly to the component response callback, in a persistent manner.
Below is an example of how regex can be used to create a button and how to respond to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Just like normal @component_callback
, you can specify a regex pattern to match your custom_ids, instead of explicitly passing strings. This is useful if you have a lot of components with similar custom_ids, and you want to handle them all in the same callback.
Please do bare in mind that using regex patterns can be a bit slower than using strings, especially if you have a lot of components.
Note
As explained previously, the main difference between a Button and a Select Menu is that you can retrieve a list of options that were chosen by the user for a Select Menu. In this case, this list of options can be found in ctx.values
.