Message Components

Message components—we'll call them "components" moving forward—are a framework for adding interactive elements to the messages your app or bot sends. They're accessible, customizable, and easy to use.

There are several different types of components; this documentation will outline the basics of this new framework and each example.

What is a Component

Components are a new field on the message object, so you can use them whether you're sending messages or responding to a slash command or other interaction.

The top-level components field is an array of Action Row components.

Component Object

Component Structure
FieldTypeDescriptionValid For
typeintegercomponent typeall types
custom_id?stringa developer-defined identifier for the component, max 100 charactersButtons, Select Menus
disabled?booleanwhether the component is disabled, default falseButtons, Select Menus
style?integerone of button stylesButtons
label?stringtext that appears on the button, max 80 charactersButtons
emoji?partial emojiname, id, and animatedButtons
url?stringa url for link-style buttonsButtons
optionsarray of select optionsthe choices in the select, max 25Select Menus
placeholder?stringcustom placeholder text if nothing is selected, max 100 charactersSelect Menus
min_values?integerthe minimum number of items that must be chosen; default 1, min 0, max 25Select Menus
max_values?integerthe maximum number of items that can be chosen; default 1, max 25Select Menus
components?array of componentsa list of child componentsAction Rows
Component Types
TypeNameDescription
1Action RowA container for other components
2ButtonA button object
3Select MenuA select menu for picking from choices
Example Component
{
"content": "This is a message with components",
"components": [
{
"type": 1,
"components": []
}
]
}

Action Rows

An Action Row is a non-interactive container component for other types of components. It has a type: 1 and a sub-array of components of other types.

  • You can have up to 5 Action Rows per message
  • An Action Row cannot contain another Action Row
{
"content": "This is a message with components",
"components": [
{
"type": 1,
"components": [
{
"type": 2,
"label": "Click me!",
"style": 1,
"custom_id": "click_one"
}
]
}
]
}

Responding to a Component Interaction

Responding to a user interacting with a component is the same as other interaction types, like application commands. You can simply ACK the request, send a followup message, or edit the original message to something new. Check out Responding to An Interaction and interaction response for more.

Custom ID

Components, aside from Action Rows, must have a custom_id field. This field is defined by the developer when sending the component payload, and is returned in the interaction payload sent when a user interacts with the component. For example, if you set custom_id: click_me on a button, you'll receive an interaction containing custom_id: click_me when a user clicks that button.

custom_id must be unique per component; multiple buttons on the same message must not share the same custom_id. This field is a string of max 100 characters, and can be used flexibly to maintain state or pass through other important data.

Buttons

Buttons are interactive components that render on messages. They can be clicked by users, and send an interaction to your app when clicked.

  • Buttons must be sent inside an Action Row
  • An Action Row can contain up to 5 buttons
  • An Action Row containing buttons cannot also contain a select menu

Button Object

Button Structure
FieldTypeDescription
typeinteger2 for a button
styleintegerone of button styles
label?stringtext that appears on the button, max 80 characters
emoji?partial emojiname, id, and animated
custom_id?stringa developer-defined identifier for the button, max 100 characters
url?stringa url for link-style buttons
disabled?booleanwhether the button is disabled (default false)

Buttons come in a variety of styles to convey different types of actions. These styles also define what fields are valid for a button.

  • Non-link buttons must have a custom_id, and cannot have a url
  • Link buttons must have a url, and cannot have a custom_id
  • Link buttons do not send an interaction to your app when clicked
Button Styles
NameValueColorRequired Field
Primary1blurplecustom_id
Secondary2greycustom_id
Success3greencustom_id
Danger4redcustom_id
Link5grey, navigates to a URLurl

An image showing the different button styles

When a user clicks on a button, your app will receive an interaction including the message the button was on:

Component Interaction Object

Sample Component Interaction
{
"version": 1,
"type": 3,
"token": "unique_interaction_token",
"message": {
"type": 0,
"tts": false,
"timestamp": "2021-05-19T02:12:51.710000+00:00",
"pinned": false,
"mentions": [],
"mention_roles": [],
"mention_everyone": false,
"id": "844397162624450620",
"flags": 0,
"embeds": [],
"edited_timestamp": null,
"content": "This is a message with components.",
"components": [
{
"type": 1,
"components": [
{
"type": 2,
"label": "Click me!",
"style": 1,
"custom_id": "click_one"
}
]
}
],
"channel_id": "345626669114982402",
"author": {
"id": 53908232506183680,
"username": "mason",
"global_name": "Mason",
"avatar": "a_d5efa99b3eeaa7dd43acca82f5692432",
"discriminator": "0",
"public_flags": 131141,
"avatar_decoration_data": null,
"primary_guild": null
},
"attachments": []
},
"member": {
"user": {
"id": "53908232506183680",
"username": "mason",
"global_name": "Mason",
"avatar": "a_d5efa99b3eeaa7dd43acca82f5692432",
"discriminator": "0",
"public_flags": 131141,
"avatar_decoration_data": null,
"primary_guild": null
},
"roles": ["290926798626357999"],
"premium_since": null,
"permissions": "17179869183",
"pending": false,
"nick": null,
"mute": false,
"joined_at": "2017-03-13T19:19:14.040000+00:00",
"deaf": false,
"avatar": null
},
"id": "846462639134605312",
"guild_id": "290926798626357999",
"data": {
"custom_id": "click_one",
"component_type": 2
},
"channel_id": "345626669114982999",
"application_id": "290926444748734465"
}

Select Menus

Select menus are another interactive component that renders on messages. On desktop, clicking on a select menu opens a dropdown-style UI; on mobile, tapping a select menu opens up a half-sheet with the options.

A select menu open on desktop

Select menus support single-select and multi-select behavior, meaning you can prompt a user to choose just one item from a list, or multiple. When a user finishes making their choice by clicking out of the dropdown or closing the half-sheet, your app will receive an interaction.

  • Select menus must be sent inside an Action Row
  • An Action Row can contain only one select menu
  • An Action Row containing a select menu cannot also contain buttons
Select Menu Example
// This is a message
{
"content": "Mason is looking for new arena partners. What classes do you play?",
"components": [
{
"type": 1,
"components": [
{
"type": 3,
"custom_id": "class_select_1",
"options": [
{
"label": "Rogue",
"value": "rogue",
"description": "Sneak n stab",
"emoji": {
"name": "rogue",
"id": "625891304148303894"
}
},
{
"label": "Mage",
"value": "mage",
"description": "Turn 'em into a sheep",
"emoji": {
"name": "mage",
"id": "625891304081063986"
}
},
{
"label": "Priest",
"value": "priest",
"description": "You get heals when I'm done doing damage",
"emoji": {
"name": "priest",
"id": "625891303795982337"
}
}
],
"placeholder": "Choose a class",
"min_values": 1,
"max_values": 3
}
]
}
]
}

Select Menu Object

Select Menu Structure
FieldTypeDescription
typeinteger3 for a select menu
custom_idstringa developer-defined identifier for the button, max 100 characters
optionsarray of select optionsthe choices in the select, max 25
placeholder?stringcustom placeholder text if nothing is selected, max 100 characters
min_values?integerthe minimum number of items that must be chosen; default 1, min 0, max 25
max_values?integerthe maximum number of items that can be chosen; default 1, max 25
disabled?booleandisable the select, default false
Select Option Structure
FieldTypeDescription
labelstringthe user-facing name of the option, max 100 characters
valuestringthe dev-define value of the option, max 100 characters
description?stringan additional description of the option, max 100 characters
emoji?partial emoji objectid, name, and animated
default?booleanwill render this option as selected by default
Select Menu Interaction
{
"application_id": "845027738276462632",
"channel_id": "772908445358620702",
"data": {
"component_type": 3,
"custom_id": "class_select_1",
"values": ["mage", "rogue"]
},
"guild_id": "772904309264089089",
"id": "847587388497854464",
"member": {
"avatar": null,
"deaf": false,
"joined_at": "2020-11-02T19:25:47.248000+00:00",
"mute": false,
"nick": "Bot Man",
"pending": false,
"permissions": "17179869183",
"premium_since": null,
"roles": ["785609923542777878"],
"user": {
"id": "53908232506183680",
"username": "mason",
"global_name": "Mason",
"avatar": "a_d5efa99b3eeaa7dd43acca82f5692432",
"discriminator": "0",
"public_flags": 131141,
"avatar_decoration_data": null,
"primary_guild": null
}
},
"message": {
"application_id": "845027738276462632",
"attachments": [],
"author": {
"id": "845027738276462632",
"username": "interactions_test",
"global_name": "Interactions Test",
"avatar": "a_d5efa99b3eeaa7dd43acca82f5692432",
"discriminator": "0",
"public_flags": 131141,
"bot": true,
"avatar_decoration_data": null,
"primary_guild": null
},
"channel_id": "772908445358620702",
"components": [
{
"components": [
{
"custom_id": "class_select_1",
"max_values": 1,
"min_values": 1,
"options": [
{
"description": "Sneak n stab",
"emoji": {
"id": "625891304148303894",
"name": "rogue"
},
"label": "Rogue",
"value": "rogue"
},
{
"description": "Turn 'em into a sheep",
"emoji": {
"id": "625891304081063986",
"name": "mage"
},
"label": "Mage",
"value": "mage"
},
{
"description": "You get heals when I'm done doing damage",
"emoji": {
"id": "625891303795982337",
"name": "priest"
},
"label": "Priest",
"value": "priest"
}
],
"placeholder": "Choose a class",
"type": 3
}
],
"type": 1
}
],
"content": "Mason is looking for new arena partners. What classes do you play?",
"edited_timestamp": null,
"embeds": [],
"flags": 0,
"id": "847587334500646933",
"interaction": {
"id": "847587333942935632",
"name": "dropdown",
"type": 2,
"user": {
"id": "53908232506183680",
"username": "mason",
"global_name": "Mason",
"avatar": "a_d5efa99b3eeaa7dd43acca82f5692432",
"discriminator": "0",
"public_flags": 131141,
"avatar_decoration_data": null,
"primary_guild": null
}
},
"mention_everyone": false,
"mention_roles": [],
"mentions": [],
"pinned": false,
"timestamp": "2021-05-27T21:29:27.956000+00:00",
"tts": false,
"type": 20,
"webhook_id": "845027738276462632"
},
"token": "UNIQUE_TOKEN",
"type": 3,
"version": 1
}