Buttons and menus
A message sent by a command can have buttons and menus. When someone uses one, the same command runs again, and it knows which button it was. That way one command holds a whole system: the message, its buttons, and what each one does.
The idea
Section titled “The idea”{{ if eq .Trigger "command" }} {{ sendMessage nil (complexMessage "content" "Do you like pizza?" "components" (cslice (crow (cbutton "label" "Yes" "id" "yes" "style" "success") (cbutton "label" "No" "id" "no" "style" "danger")))) }}{{ return }}{{ end }}
{{/* From here on, a button was used */}}{{ respond (printf "You pressed **%s**." .Button.ID) true }}.Triggersays why the code is running:"command"(someone typed the command),"button"or"select"(someone used a button or a menu)..Button.IDis the"id"of the button that was used, and.Button.Datais its"data".- For a menu,
.Valuesis the list of the options that were chosen. {{ return }}ends the code, so the part for the command does not run when a button is used.
cbutton
Section titled “cbutton”cbutton makes a button from pairs of a name and a value.
| Name | Value |
|---|---|
label |
The text of the button, up to 80 characters |
emoji |
An emoji such as "👆", instead of or together with the label |
id |
The name of the button, 1 to 20 letters, numbers, - or _. Required, unless it has a url |
data |
Extra text for the button, up to 20 letters, numbers, ., - or _. It comes back in .Button.Data |
style |
"primary", "secondary" (the default), "success" or "danger" |
url |
Makes a link button. It starts with http:// or https://, and it has no id: it just opens the link |
disabled |
true for a button that cannot be used |
user |
A user ID. Only that member can use the button; anyone else is told “This is not for you” |
A button needs a label or an emoji.
cselect
Section titled “cselect”A menu of options, from pairs of a name and a value.
| Name | Value |
|---|---|
id |
The name of the menu, as for a button. Required |
options |
A list of options, each one cslice "label" "value" or cslice "label" "value" "description". From 1 to 25 |
placeholder |
The text shown when nothing is chosen, up to 150 characters |
min, max |
How many options can be chosen. By default 1 and 1 |
user |
A user ID, like in a button |
{{ sendMessage nil (complexMessage "components" (cslice (crow (cselect "id" "pick" "placeholder" "Choose one" "options" (cslice (cslice "Pizza" "pizza" "Cheesy") (cslice "Sushi" "sushi")))))) }}When a menu is used, .Values holds the value of each option that was chosen, for example (index .Values 0).
crow puts components in a row. A row holds up to 5 buttons, or one menu by itself. A message holds up to 5 rows:
"components" (cslice (crow button1 button2) (crow menu))Modals: forms that pop up
Section titled “Modals: forms that pop up”A button or a menu can open a modal, a form with text fields that pops up over Discord. When the person sends it, the same command runs again, with what they wrote.
{{ if eq .Trigger "command" }} {{ sendMessage nil (complexMessage "content" "Have an idea?" "components" (cslice (crow (cbutton "label" "Suggest" "id" "open" "style" "primary")))) }}{{ return }}{{ end }}
{{ if eq .Trigger "button" }} {{ showModal (cmodal "id" "send" "title" "Your suggestion" "fields" (cslice (ctext "id" "title" "label" "Title" "max" 80) (ctext "id" "details" "label" "Details" "style" "paragraph" "required" false))) }}{{ return }}{{ end }}
{{/* From here on, the form was sent */}}{{ respond (printf "You wrote: **%s**" .Fields.title) true }}.Triggeris"modal"when the form was sent..Modal.IDis the"id"of the modal and.Modal.Dataits"data"..Fieldsholds what was written, by theidof each field:.Fields.title,.Fields.details. A field left empty is an empty text.showModalonly works when the command runs because of a button or a menu. A modal cannot open another modal, and a command typed in chat cannot open one.respondanswers the form, in private withtrue.updateMessagechanges the message the button was on.- Opening the modal is the answer to the click, so a run can use
showModalorrespond/updateMessage, not both.
cmodal
Section titled “cmodal”| Name | Value |
|---|---|
id |
The name of the modal, as for a button. Required |
title |
The title at the top, up to 45 characters. Required |
fields |
A list of 1 to 5 fields made with ctext. Required |
data |
Extra text, like the data of a button. It comes back in .Modal.Data |
| Name | Value |
|---|---|
id |
The name of the field, 1 to 20 letters, numbers or _. Required. It is how .Fields finds it |
label |
The text above the field, up to 45 characters. Required |
style |
"short" (one line, the default) or "paragraph" (many lines) |
placeholder |
A hint shown while the field is empty, up to 100 characters |
value |
Text the field starts with, up to 4000 characters |
required |
false lets the person leave it empty. By default it is required |
min, max |
The least and the most characters, from 0 to 4000 |
Answering a click
Section titled “Answering a click”When a button or a menu is used, the person is waiting for an answer. In the code of a button you can:
| Function | What it does |
|---|---|
respond message |
Answers the click with a new message, seen by everyone |
respond message true |
The same, but only the person who clicked sees it |
updateMessage message |
Changes the message the button is on. What you do not give stays: if you only give an embed, the buttons stay |
| Printing text | If the code prints text and does not use respond or updateMessage, that text is the answer |
If the code does none of those, the click is simply acknowledged and nothing is shown. Only one of respond and updateMessage can be used in a run.
message is a text, a cembed or a complexMessage, like in Embeds and messages. It can also hold new "components".
The other actions (addRole, sendMessage…) work in a click too, for the person who clicked, with the same checks.
What the code can read in a click
Section titled “What the code can read in a click”Everything in Data is there, about the person who clicked, plus:
.Message.ID,.Message.Contentand.Message.Embeds(a list of maps withTitle,Description,Footer,Author,AuthorIcon,FooterIcon,Thumbnail,ImageandColor) of the message the button is on..Trigger,.Buttonand.Values, as above. When a modal was sent,.Modaland.Fields.
.Args is empty in a click.
Good to know
Section titled “Good to know”- A button keeps working as long as the command exists and has code. If the command is removed, the click answers “That command does not exist anymore.”
- Using the same button twice in a row in a very short time is ignored.
- Direct messages cannot have buttons or menus.
- Each handler runs with the same limits as a command.
- Use stored data to remember what people chose. The id of the message (
.Message.ID) is a good key for things that belong to one message, such as a vote.
A complete example: a vote
Section titled “A complete example: a vote”The vote template is a yes or no vote where each person has one vote and can change it. Install it with
!customcommand template vote and read its code with !customcommand codeshow vote.
