diff --git a/content/docs/reference/all.png b/content/docs/reference/all.png new file mode 100644 index 0000000..5e706c3 Binary files /dev/null and b/content/docs/reference/all.png differ diff --git a/content/docs/reference/button.png b/content/docs/reference/button.png new file mode 100644 index 0000000..d7353ba Binary files /dev/null and b/content/docs/reference/button.png differ diff --git a/content/docs/reference/components-v2.md b/content/docs/reference/components-v2.md new file mode 100644 index 0000000..66b63e6 --- /dev/null +++ b/content/docs/reference/components-v2.md @@ -0,0 +1,501 @@ ++++ +title = "Components V2" +weight = 920 +description = "Be fancier, use components!" ++++ + +## componentBuilder + +`componentBuilder` is a helper for building Discord’s new Components V2 (sections, buttons, menus, galleries). +It provides a simple template-based way to assemble complex message layouts without needing to write raw JSON. +You describe components with key–value pairs and `componentBuilder` handles conversion and validation for you. + +This makes it easier to: + +- Create rich messages with text, images, and files. +- Add interactive components like buttons and select menus. +- Group and style components with containers. +- Control delivery with meta options like ephemeral replies. + +### Text + +Displays plain text content, supporting markdown. Can be a string or a slice of strings. + +```yag +{{ $text := componentBuilder + "text" "Component Builder v2 test!" +}} + +{{ /* or */ }} + +{{ $text := componentBuilder + "text" (cslice + "### Ingredients" + "`200g` pasta sheets" + "`500g` minced beef" + "`300ml` tomato sauce" + ) +}} +``` + +![example of text](texts.png) + +### Section + +A layout block that shows text with one optional accessory: a button **OR** a thumbnail. + +`text`: A string, or slice of strings. + +`button`: [Button](/docs/reference/templates/functions#cbutton) (optional) + +`thumbnail`: sdict with keys media, description, spoiler (optional) + +```yag +{{ $section := componentBuilder + "section" (sdict + "text" "🍲 **Lasagna Recipe**" + "thumbnail" (sdict + "media" "https://http.cat/103" + "description" "Alt text" + "spoiler" false + ) + "button" (cbutton (sdict "label" "Set Servings" "custom_id" "set-servings" "style" "primary")) + ) +}} +``` + +![example of section](section.png) + +### Gallery + +Displays one or more media items with optional descriptions and spoiler flags. + +`media`: string + +`description`: string (optional) + +`spoiler`: bool (optional) + +```yag +{{ $gallery := componentBuilder + "gallery" (cslice + (sdict "media" "https://http.cat/103") + (sdict "media" "https://http.cat/420" "description" "I dont have food pics") + (sdict "media" "https://http.cat/451" "description" "So have random cats" "spoiler" true) + ) +}} +``` + +![example of gallery](gallery.png) + +### File + +Attaches text files to the message and optionally displays them. + +`content`: string (max 100 000 chars) + +`name`: string (filename, .txt appended automatically) + +```yag +{{ $file := componentBuilder + "file" (cslice + (sdict + "content" "Step 1: Boil pasta\nStep 2: Cook beef\nStep 3: Layer & bake" + "name" "lasagna_recipe" + ) + (sdict + "content" "Tips:\n- Use fresh herbs\n- Let it rest 10 min before serving" + "name" "lasagna_tips" + "spoiler" true + ) + ) +}} +``` + +![example of file](file.png) + +### Separator + +Adds spacing between components. + +`true`: large separator + +`false` or `nil`: small separator + +```yag +{{ $separator := componentBuilder "separator" true }} +``` + +### Container + +Groups multiple components with optional styling. + +`components`: ComponentBuilder or list of entries + +`color`: hex accent color (optional) + +`spoiler`: hides content until revealed (optional) + +```yag +{{ $container := componentBuilder + "container" (sdict + "color" 0xF5CDF6 + "spoiler" false + "components" (componentBuilder + "text" "🍲 **Lasagna Recipe**" + "buttons" (cslice + (cbutton (sdict "label" "Start" "custom_id" "start" "style" "primary")) + (cbutton (sdict "label" "Cancel" "custom_id" "cancel" "style" "danger")) + ) + ) + ) +}} +``` + +![example of container](container.png) + +### Buttons + +Interactive buttons users can click. Can be single or multiple. see [cbutton](/docs/reference/templates/functions#cbutton). + +- Maximum 25 buttons total (5 rows \* 5 buttons) + +- Link buttons don’t need a `custom_id` + +```yag +{{ $buttons := componentBuilder + "buttons" (cslice + (cbutton "label" "-" "custom_id" "decrease" "style" "danger") + (cbutton "label" "+" "custom_id" "increase" "style" "success") + (cbutton "label" "Random" "custom_id" "random" "style" "secondary") + ) +}} +``` + +![example of buttons](button.png) + +### Menus + +Select menus for user options. see [cmenu](/docs/reference/templates/functions#cmenu). + +- Maximum 5 menus per message + +- Each menu occupies its own row + +```yag +{{ $menu := componentBuilder + "menus" (cmenu + "custom_id" "unit-select" + "options" (cslice + (sdict "label" "Metric" "value" "metric") + (sdict "label" "Imperial" "value" "imperial") + (sdict "label" "Kelvin" "value" "kelvin") + ) + ) +}} +``` + +![example of menus](menu.png) + +### Interactive Components + +Mix of buttons and menus, auto-distributed. see [cbutton](/docs/reference/templates/functions#cbutton)/[cmenu](/docs/reference/templates/functions#cmenu). + +Accepts: + +- Single component + +- Slice of components + +- Slice of slices (to define rows) + +```yag +{{ $interactive := componentBuilder + "interactive_components" (cslice + (cbutton "label" "Approve" "custom_id" "approve" "style" "success") + (cbutton "label" "Reject" "custom_id" "reject" "style" "danger") + (cmenu + "custom_id" "priority-select" + "options" (cslice + (sdict "label" "High" "value" "high") + (sdict "label" "Medium" "value" "medium") + (sdict "label" "Low" "value" "low") + ) + ) + ) +}} +``` + +### Meta keys + +- `allowed_mentions`: control pings (users, roles, everyone) + +- `reply`: message ID to reply to (only available in interactions) + +- `silent`: suppress notifications + +- `ephemeral`: message visible only to interaction user + +###### Example + +This example combines text, sections, gallery, files, buttons, menus, and container styling into a single, cohesive layout. + +```yag +{{ $section := sdict + "text" "🍲 **Lasagna Recipe**" + "button" (cbutton "label" "Set Servings" "custom_id" "set-servings" "style" "primary") +}} + +{{ $pasta := cslice "### Ingredients" "`200g` pasta sheets" "`500g` minced beef" "`300ml` tomato sauce" "`200g` mozzarella cheese" "`1` onion, diced" }} + +{{ $oven := cslice "### Oven Settings" "Mode: `Bake`" "Temp: `180°C`" "Time: `45 minutes`" }} + +{{ $gallery := cslice + (sdict "media" "https://http.cat/420" "description" "Step 1: Prep ingredients") + (sdict "media" "https://http.cat/451" "description" "Step 2: Into the oven!" "spoiler" true) +}} + +{{ $file := cslice + (sdict + "content" "Step 1: Boil pasta\nStep 2: Cook beef with onion\nStep 3: Layer pasta, beef, sauce, cheese\nStep 4: Bake at 180°C for 45 min" + "name" "lasagna_recipe" + ) + (sdict + "content" "Tips:\n- Use fresh herbs for better flavor\n- Let it rest 10 min before serving" + "name" "lasagna_tips" + "spoiler" true + ) +}} + +{{ $buttons := cslice + (cbutton "label" "➖ Less Cheese" "custom_id" "less-cheese" "style" "danger") + (cbutton "label" "➕ More Cheese" "custom_id" "more-cheese" "style" "success") + (cbutton "label" "🍷 Suggest Wine Pairing" "custom_id" "wine" "style" "secondary") +}} + +{{ $menus := cmenu + "custom_id" "sauce-select" + "options" (cslice + (sdict "label" "Classic Tomato" "value" "tomato") + (sdict "label" "White Sauce" "value" "bechamel") + (sdict "label" "Spicy Arrabbiata" "value" "arrabbiata") + ) +}} + +{{ $comp := componentBuilder + "silent" true + "container" (sdict + "color" 0xF5CDF6 + "components" (componentBuilder + "section" $section + "text" $pasta + "separator" true + "text" $oven + "gallery" $gallery + "file" $file + "separator" true + "buttons" $buttons + "menus" $menus + ) + ) +}} + +{{ sendMessage nil $comp }} +``` + +![example of full](all.png) + +## Component Builder Helper Functions + +The helper function provides methods to construct, manipulate, and get Discord V2 message components programmatically. + +These methods allow you to build complex layouts incrementally and retrieve them in a format that Discord understands. + +### componentBuilder.Add + +Adds a single component entry to the builder under the given key. + +```yag +{{ $cb.Add }} +``` + +Parameters: + +- `key` – The top-level key for the component (e.g., "text", "section", "buttons"). +- `value` – The component data (string, sdict, Button, SelectMenu, etc.). + +###### Example + +```yag +{{ $builder := componentBuilder }} +{{ $section := sdict + "text" "🍲 **Lasagna Recipe**" + "button" (cbutton "label" "Set Servings" "custom_id" "set-servings" "style" "primary") +}} +{{ $builder.Add "section" $section }} +``` + +### componentBuilder.AddSlice + +Adds multiple components under one key. + +```yag +{{ $cb.AddSlice }} +``` + +Parameters: + +- `key` – The top-level key for the component (e.g., "text", "section", "buttons"). +- `values` – The component data (string, sdict, Button, SelectMenu, etc.). + +###### Example + +```yag +{{ $builder := componentBuilder }} +{{ $pasta := cslice + "### Ingredients" + "`200g` pasta sheets" + "`500g` minced beef" + "`300ml` tomato sauce" + "`200g` mozzarella cheese" + "`1` onion, diced" +}} +{{ $builder.AddSlice "text" $pasta }} +``` + +### componentBuilder.Merge + +Combine another builder into the current one. + +```yag +{{ $cb.Merge }} +``` + +Parameters: + +- `other` – The builder to merge. + +###### Example + +```yag +{{ $builder1 := componentBuilder }} +{{ $builder2 := componentBuilder }} +{{ $oven := cslice + "### Oven Settings" + "Mode: `Bake`" + "Temp: `180°C`" + "Time: `45 minutes`" +}} +{{ $section := sdict + "text" "🍲 **Lasagna Recipe**" + "button" (cbutton "label" "Set Servings" "custom_id" "set-servings" "style" "primary") +}} +{{ $builder1.Add "section" $section }} +{{ $builder2.AddSlice "text" $oven }} +{{ $builder1.Merge $builder2 }} +``` + +### componentBuilder.Get + +Retrieve components stored under a key. + +```yag +{{ $components := $cb.Get }} +``` + +Parameters: + +- `key` – The top-level key for the component (e.g., "text", "section", "buttons"). + +###### Example + +```yag +{{ $textComponents := $builder1.Get "text" }} +``` + +`$textComponents` now contains the ingredient and oven text slices. + +--- + +Here's an example of how to use the helper function to create a complex layout: + +###### Example (with helper function) + +```yag +{{ $section := sdict + "text" "🍲 **Lasagna Recipe**" + "button" (cbutton "label" "Set Servings" "custom_id" "set-servings" "style" "primary") +}} +{{ $pasta := cslice + "### Ingredients" + "`200g` pasta sheets" + "`500g` minced beef" + "`300ml` tomato sauce" + "`200g` mozzarella cheese" + "`1` onion, diced" +}} +{{ $oven := cslice + "### Oven Settings" + "Mode: `Bake`" + "Temp: `180°C`" + "Time: `45 minutes`" +}} +{{ $gallery := cslice + (sdict "media" "https://http.cat/420" "description" "Step 1: Prep ingredients") + (sdict "media" "https://http.cat/451" "description" "Step 2: Into the oven!" "spoiler" true) +}} +{{ $file := cslice + (sdict + "content" "Step 1: Boil pasta\nStep 2: Cook beef with onion\nStep 3: Layer pasta, beef, sauce, cheese\nStep 4: Bake at 180°C for 45 min" + "name" "lasagna_recipe" + ) + (sdict + "content" "Tips:\n- Use fresh herbs for better flavor\n- Let it rest 10 min before serving" + "name" "lasagna_tips" + "spoiler" true + ) +}} +{{ $buttons := cslice + (cbutton "label" "➖ Less Cheese" "custom_id" "less-cheese" "style" "danger") + (cbutton "label" "➕ More Cheese" "custom_id" "more-cheese" "style" "success") + (cbutton "label" "🍷 Suggest Wine Pairing" "custom_id" "wine" "style" "secondary") +}} +{{ $menus := cmenu + "custom_id" "sauce-select" + "options" (cslice + (sdict "label" "Classic Tomato" "value" "tomato") + (sdict "label" "White Sauce" "value" "bechamel") + (sdict "label" "Spicy Arrabbiata" "value" "arrabbiata") + ) +}} + +{{ $builder := componentBuilder }} + +{{ $builder.Add "section" $section }} + +{{ $builder.AddSlice "text" $pasta }} + +{{ $builder.Add "separator" true }} + +{{ $builder.AddSlice "text" $oven }} + +{{ $builder.Add "separator" true }} + +{{ $builder.Add "gallery" $gallery }} +{{ $builder.Add "file" $file }} + +{{ $builder.Add "separator" true }} + +{{ $builder.Add "buttons" $buttons }} +{{ $builder.Add "menus" $menus }} + +{{ $container := componentBuilder }} + +{{ $container.Add "container" (sdict + "color" 0xF5CDF6 + "components" $builder + ) +}} + +{{ sendMessage nil $container }} +``` diff --git a/content/docs/reference/container.png b/content/docs/reference/container.png new file mode 100644 index 0000000..a88461e Binary files /dev/null and b/content/docs/reference/container.png differ diff --git a/content/docs/reference/file.png b/content/docs/reference/file.png new file mode 100644 index 0000000..0cb2607 Binary files /dev/null and b/content/docs/reference/file.png differ diff --git a/content/docs/reference/gallery.png b/content/docs/reference/gallery.png new file mode 100644 index 0000000..5a17c32 Binary files /dev/null and b/content/docs/reference/gallery.png differ diff --git a/content/docs/reference/menu.png b/content/docs/reference/menu.png new file mode 100644 index 0000000..c36dcc2 Binary files /dev/null and b/content/docs/reference/menu.png differ diff --git a/content/docs/reference/section.png b/content/docs/reference/section.png new file mode 100644 index 0000000..e719eb8 Binary files /dev/null and b/content/docs/reference/section.png differ diff --git a/content/docs/reference/templates/functions.md b/content/docs/reference/templates/functions.md index 8b3c0af..0fb454a 100644 --- a/content/docs/reference/templates/functions.md +++ b/content/docs/reference/templates/functions.md @@ -779,6 +779,112 @@ object](/docs/reference/templates/syntax-and-data#message). Is also valid for ep --- +## Component V2 + +Components V2 provides a new way to create interactive and visually appealing message layouts in Discord applications, +making it easier to control message formatting and user interaction while maintaining line length under 120 characters. + +### componentBuilder + +A `componentBuilder` simplifies building Discord's ComponentsV2 in custom commands. + +```yag +{{ $component := componentBuilder (sdict [text] [section] [gallery] [file] [separator] [container] [buttons] [menus] [interactive_components] [allowed_mentions] [reply] [silent] [ephemeral]) }} +``` + +Returns a complex message object with the given components. + +All keys are optional, but the Discord API will reject completey empty messages, so some content is required. + +- `text`: A string or a slice of strings. +- `section`: A layout block that shows text with one optional accessory: a button **OR** a thumbnail with the following keys: + - `text`: A string or a slice of strings. + - `button`: A [button object](#cbutton). + - `thumbnail`: An sdict with the following keys: + - `media`: A string. + - `description`: A string. + - `spoiler`: A bool. +- `gallery`: Displays one or more media items with optional descriptions and spoiler flags with the following keys: + - `media`: A string. + - `description`: A string. + - `spoiler`: A bool. +- `file`: Attaches text files to the message and optionally displays them with the following keys: + - `content`: A string. (max 100 000 chars) + - `name`: A string. (.txt appended automatically) +- `separator`: Adds spacing between components with the following keys: + - `true`: large separator + - `false` or `nil`: small separator +- `container`: Top-level layout. Containers offer the ability to visually encapsulate a collection of components, + and have an optional customizable accent color bar. Contains the following keys: + - `components`: A [componentBuilder](#componentbuilder) or a slice thereof. + - `color`: hex accent color (optional). + - `spoiler`: hides content until revealed (optional). +- `buttons`: Interactive [buttons](#cbutton) users can click. Can be single or multiple. +- `menus`: Interactive [menus](#cmenu)s users can select from. Can be single or multiple. +- `interactive_components`: Mix of buttons and menus, auto-distributed. +- `allowed_mentions`: A sdict with the following keys: + - `users`: A slice of user IDs. + - `roles`: A slice of role IDs. + - `everyone`: A bool. + - `replied_user`: A bool. +- `reply`: A sdict with the following keys: + - `message_id`: A string. + - `thread_id`: A string. +- `silent`: A bool. +- `ephemeral`: A bool. + +### Component Builder Functions + +The `ComponentBuilder` simplifies building Discord's V2 components, allowing complex layouts to be built incrementally. +It provides methods for constructing, manipulating, and exporting components in a format Discord understands, +ensuring line length doesn't exceed 120 characters. + +#### ComponentBuilder.Add + +Adds a single component entry to the builder under the given key. + +```yag +{{ $builder.Add }} +``` + +- `key` – The top-level key for the component (e.g., "text", "section", "buttons"). +- `value` – The component data (string, sdict, Button, SelectMenu, etc.). + +#### ComponentBuilder.AddSlice + +Adds multiple components under one key. + +```yag +{{ $builder.AddSlice }} +``` + +- `key` – The top-level key for the component (e.g., "text", "section", "buttons"). +- `values` – The component data (string, sdict, Button, SelectMenu, etc.). + +#### ComponentBuilder.Merge + +Combine another builder into the current one. + +```yag +{{ $builder.Merge }} +``` + +- `other` – The other component builder to merge. + +#### ComponentBuilder.Get + +Returns the component data for the given key. + +```yag +{{ $value := .Get }} +``` + +- `key` – The top-level key for the component (e.g., "text", "section", "buttons"). + +Example usage can be found at the [Components v2](/docs/reference/components-v2). + +--- + ## Math #### abs diff --git a/content/docs/reference/texts.png b/content/docs/reference/texts.png new file mode 100644 index 0000000..0b5892a Binary files /dev/null and b/content/docs/reference/texts.png differ