EDA.Component (EDA v0.3.0)

Copy Markdown View Source

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 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

action_row(components)

@spec action_row(list()) :: map()

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)
])

button(label, opts \\ [])

@spec button(
  String.t(),
  keyword()
) :: map()

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 - If true, 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)

channel_select(custom_id, opts \\ [])

@spec channel_select(
  String.t(),
  keyword()
) :: map()

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")

container(opts)

@spec container(keyword()) :: map()

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 - If true, content is hidden behind a spoiler

Example

container(
  accent_color: 0xFF0000,
  components: [
    text_display("Hello!"),
    separator(),
    text_display("World!")
  ]
)

disable_all(components)

@spec disable_all([map()] | nil) :: [map()]

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
)

file(url, opts \\ [])

@spec file(
  String.t(),
  keyword()
) :: map()

Creates a file component (type 13).

The URL must use the attachment:// scheme.

Options

  • :spoiler - If true, file is hidden behind a spoiler

Example

file("attachment://report.pdf")

media_gallery(items)

@spec media_gallery([map()]) :: map()

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")
])

media_item(url, opts \\ [])

@spec media_item(
  String.t(),
  keyword()
) :: map()

Creates a media item for use in media_gallery/1.

Options

  • :description - Caption for the media item
  • :spoiler - If true, item is hidden behind a spoiler

Example

media_item("https://example.com/image.png", description: "My image")

mentionable_select(custom_id, opts \\ [])

@spec mentionable_select(
  String.t(),
  keyword()
) :: map()

Creates a mentionable select menu component (type 7).

Example

mentionable_select("pick_mention", placeholder: "Choose user or role")

role_select(custom_id, opts \\ [])

@spec role_select(
  String.t(),
  keyword()
) :: map()

Creates a role select menu component (type 6).

Example

role_select("pick_role", placeholder: "Choose a role")

section(text, opts \\ [])

@spec section(
  map() | [map()],
  keyword()
) :: map()

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"))

select_option(label, value, opts \\ [])

@spec select_option(String.t(), String.t(), keyword()) :: map()

Creates an option for string_select/3.

Options

  • :description - Description shown under the option label (max 100 chars)
  • :emoji - Emoji map
  • :default - If true, this option is pre-selected

Example

select_option("Red", "red", description: "The color red", emoji: %{name: "🔴"})

separator(opts \\ [])

@spec separator(keyword()) :: map()

Creates a separator component (type 14).

Options

  • :divider - Whether to show a visible line (default true)
  • :spacing - :small (1) or :large (2)

Example

separator()
separator(spacing: :large)
separator(divider: false, spacing: :small)

string_select(custom_id, options, opts \\ [])

@spec string_select(String.t(), [map()], keyword()) :: map()

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 - If true, 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")

text_display(content)

@spec text_display(String.t()) :: map()

Creates a text display component (type 10).

Supports full markdown.

Example

text_display("# Hello World")
text_display("**Bold** and *italic*")

thumbnail(url, opts \\ [])

@spec thumbnail(
  String.t(),
  keyword()
) :: map()

Creates a thumbnail component (type 11).

Options

  • :description - Alt text / description
  • :spoiler - If true, 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)

user_select(custom_id, opts \\ [])

@spec user_select(
  String.t(),
  keyword()
) :: map()

Creates a user select menu component (type 5).

Options

  • :placeholder - Placeholder text
  • :min_values / :max_values - Selection range
  • :disabled - If true, select is greyed out

Example

user_select("pick_user", placeholder: "Choose a user")