Builder for Discord Components V2.
All builders return plain maps ready for JSON encoding — no structs needed.
Components V2 messages require the IS_COMPONENTS_V2 flag (1 << 15 = 32768).
Example
import EDA.Component
msg =
container(
accent_color: 0x5865F2,
components: [
text_display("# Welcome!"),
separator(spacing: :large),
section(
text_display("Check out this cool feature"),
accessory: thumbnail("https://example.com/thumb.png")
),
action_row([
button("Click me", custom_id: "btn_1", style: :primary),
link_button("Visit", "https://example.com")
])
]
)
EDA.API.Message.create(channel_id, components: [msg], v2: true)
Summary
Functions
Creates an action row component (type 1).
Creates a button component (type 2).
Creates a channel select menu component (type 8).
Creates a container component (type 17) — the top-level V2 wrapper.
Recursively disables all interactive components (buttons, select menus) in a component tree.
Creates a file component (type 13).
Convenience for creating a link-style button.
Creates a media gallery component (type 12).
Creates a media item for use in media_gallery/1.
Creates a mentionable select menu component (type 7).
Creates a role select menu component (type 6).
Creates a section component (type 9).
Creates an option for string_select/3.
Creates a separator component (type 14).
Creates a string select menu component (type 3).
Creates a text display component (type 10).
Creates a thumbnail component (type 11).
Creates a user select menu component (type 5).
Functions
Creates an action row component (type 1).
Holds up to 5 buttons, or exactly 1 select menu.
Example
action_row([
button("Yes", custom_id: "confirm", style: :success),
button("No", custom_id: "cancel", style: :danger)
])
Creates a button component (type 2).
Options
:style- Button style atom::primary,:secondary,:success,:danger,:link,:premium:custom_id- Unique ID for non-link buttons (max 100 chars):url- URL for link-style buttons:emoji- Emoji map%{name: "👍"}or%{id: "12345", name: "custom"}:disabled- Iftrue, button is greyed out:sku_id- SKU ID for premium buttons
Example
button("Click me", custom_id: "my_btn", style: :primary)
button("Visit", url: "https://example.com", style: :link)
Creates a channel select menu component (type 8).
Options
:channel_types- List of channel type atoms to filter- Plus all common select options (
:placeholder,:min_values,:max_values,:disabled)
Example
channel_select("pick_channel", channel_types: [:guild_text], placeholder: "Choose a channel")
Creates a container component (type 17) — the top-level V2 wrapper.
Options
:components- List of child components (max 10, required):accent_color- Integer color value for the left border:spoiler- Iftrue, content is hidden behind a spoiler
Example
container(
accent_color: 0xFF0000,
components: [
text_display("Hello!"),
separator(),
text_display("World!")
]
)
Recursively disables all interactive components (buttons, select menus) in a component tree.
Useful after a user interacts with a message — disable all buttons/selects to prevent further clicks, then update the message.
Non-interactive components (text, thumbnails, separators, etc.) are left untouched.
Examples
disabled = EDA.Component.disable_all(message["components"])
EDA.Interaction.respond(interaction,
type: :update,
components: disabled
)
Creates a file component (type 13).
The URL must use the attachment:// scheme.
Options
:spoiler- Iftrue, file is hidden behind a spoiler
Example
file("attachment://report.pdf")
Convenience for creating a link-style button.
Example
link_button("Visit", "https://example.com")
link_button("Docs", "https://docs.example.com", emoji: %{name: "📚"})
Creates a media gallery component (type 12).
Takes a list of 1–10 media items built with media_item/2.
Example
media_gallery([
media_item("https://example.com/img1.png", description: "First"),
media_item("https://example.com/img2.png")
])
Creates a media item for use in media_gallery/1.
Options
:description- Caption for the media item:spoiler- Iftrue, item is hidden behind a spoiler
Example
media_item("https://example.com/image.png", description: "My image")
Creates a mentionable select menu component (type 7).
Example
mentionable_select("pick_mention", placeholder: "Choose user or role")
Creates a role select menu component (type 6).
Example
role_select("pick_role", placeholder: "Choose a role")
Creates a section component (type 9).
A section contains 1–3 text displays and an optional accessory (thumbnail or button).
Examples
section(text_display("Some text"), accessory: thumbnail("https://example.com/img.png"))
section([
text_display("Line 1"),
text_display("Line 2")
], accessory: button("Click", custom_id: "btn"))
Creates an option for string_select/3.
Options
:description- Description shown under the option label (max 100 chars):emoji- Emoji map:default- Iftrue, this option is pre-selected
Example
select_option("Red", "red", description: "The color red", emoji: %{name: "🔴"})
Creates a separator component (type 14).
Options
:divider- Whether to show a visible line (defaulttrue):spacing-:small(1) or:large(2)
Example
separator()
separator(spacing: :large)
separator(divider: false, spacing: :small)
Creates a string select menu component (type 3).
Options
:placeholder- Placeholder text shown when nothing is selected:min_values- Minimum selections required (default 1):max_values- Maximum selections allowed (default 1):disabled- Iftrue, select is greyed out
Example
string_select("color_select", [
select_option("Red", "red"),
select_option("Blue", "blue", description: "A cool color"),
select_option("Green", "green", emoji: %{name: "🟢"})
], placeholder: "Pick a color")
Creates a text display component (type 10).
Supports full markdown.
Example
text_display("# Hello World")
text_display("**Bold** and *italic*")
Creates a thumbnail component (type 11).
Options
:description- Alt text / description:spoiler- Iftrue, image is hidden behind a spoiler
Example
thumbnail("https://example.com/img.png")
thumbnail("https://example.com/img.png", description: "A nice image", spoiler: true)
Creates a user select menu component (type 5).
Options
:placeholder- Placeholder text:min_values/:max_values- Selection range:disabled- Iftrue, select is greyed out
Example
user_select("pick_user", placeholder: "Choose a user")