Skip to main content

Overview

Component types define the structure of interactive elements like buttons, select menus, and other UI components.

ComponentJson

Base type for all component objects.
type ComponentJson = {
  type: number
  [key: string]: JsonValue
}
All components must have a type field corresponding to Discord’s component types.

ComponentLike

Union type accepting either a builder or a plain JSON object.
type ComponentLike = ComponentBuilder | ComponentJson
Used in methods that accept components in either format.

ComponentBuilder

Interface for component builders.
type ComponentBuilder = {
  toJSON: () => ComponentJson
}
All builder classes implement this interface, allowing them to be converted to JSON.

ComponentType

Enum of Discord component type constants.
const ComponentType = {
  ActionRow: 1,
  Button: 2,
  StringSelect: 3,
  InputText: 4,
  UserSelect: 5,
  RoleSelect: 6,
  MentionableSelect: 7,
  ChannelSelect: 8,
  Section: 9,
  TextDisplay: 10,
  Thumbnail: 11,
  MediaGallery: 12,
  File: 13,
  Separator: 14,
  Container: 17,
  Label: 18,
  FileUpload: 19
} as const

Example

const buttonJson: ComponentJson = {
  type: ComponentType.Button,
  style: 1,
  label: 'Click me',
  custom_id: 'my_button'
}

ButtonStyle

Enum of button style constants.
const ButtonStyle = {
  Primary: 1,    // Blue (blurple)
  Secondary: 2,  // Gray
  Success: 3,    // Green
  Danger: 4      // Red
} as const

type ButtonStyle = 1 | 2 | 3 | 4

Example

import { ButtonStyles } from 'flora'

const btn = button()
  .setStyle(ButtonStyles.Primary)
  .setLabel('Confirm')
  .toJSON()

InputTextStyle

Enum of text input style constants.
const InputTextStyle = {
  Short: 1,      // Single line
  Paragraph: 2   // Multi-line
} as const

type InputTextStyle = 1 | 2

Example

import { InputTextStyles } from 'flora'

const input = inputText('feedback')
  .setStyle(InputTextStyles.Paragraph)
  .setPlaceholder('Enter your feedback...')
  .toJSON()

SelectOption

Option for string select menus.
type SelectOption = {
  label: string
  value: string
  description?: string
  emoji?: JsonValue
  default?: boolean
}

Properties

label
string
required
The text shown to users
value
string
required
The value sent when selected (not shown to users)
description
string
Additional description text
emoji
JsonValue
Emoji to display (string for unicode, object for custom)
default
boolean
Whether this option is selected by default

Example

const options: SelectOption[] = [
  {
    label: 'Red Team',
    value: 'team_red',
    description: 'Join the red team',
    emoji: '❤️',
    default: false
  },
  {
    label: 'Blue Team',
    value: 'team_blue',
    description: 'Join the blue team',
    emoji: '💙'
  }
]

const select = stringSelect('team_select')
  .setOptions(options)
  .toJSON()

SelectDefaultValue

Default value for auto-populated selects.
type SelectDefaultValue = {
  id: string
  type: 'user' | 'role' | 'channel'
}

Properties

id
string
required
Snowflake ID of the default entity
type
'user' | 'role' | 'channel'
required
Type of entity being selected

Example

const userSelectMenu = userSelect('choose_user')
  .setDefaultValues([
    { id: '123456789', type: 'user' },
    { id: '987654321', type: 'user' }
  ])
  .toJSON()

MediaItemEntry

Entry for media gallery items.
type MediaItemEntry = {
  media: { url: string }
  description?: string
  spoiler?: boolean
}

Properties

media
{ url: string }
required
Media object containing the image/video URL
description
string
Alt text or description
spoiler
boolean
Whether to mark as spoiler

Example

const items: MediaItemEntry[] = [
  {
    media: { url: 'https://example.com/image1.png' },
    description: 'First image'
  },
  {
    media: { url: 'https://example.com/image2.png' },
    spoiler: true
  }
]

const gallery = mediaGallery()
  .setItems(items)
  .toJSON()

MessageReplyOptions

Options for replying to messages or interactions.
type MessageReplyOptions = {
  content?: string
  embeds?: RawEmbed[]
  attachments?: RawAttachment[]
  components?: JsonValue[]
  tts?: boolean
  allowedMentions?: RawAllowedMentions
  replyTo?: string | null
  ephemeral?: boolean
  flags?: number
}

Properties

content
string
The message text content
embeds
RawEmbed[]
Array of embeds (max 10)
attachments
RawAttachment[]
Files to attach
components
JsonValue[]
Interactive components (buttons, select menus)
tts
boolean
Whether to use text-to-speech
allowedMentions
RawAllowedMentions
Control which mentions are allowed
replyTo
string | null
Message ID to reply to (null to not reply)
ephemeral
boolean
Only for interactions: make the response visible only to the user
flags
number
Message flags bitfield

Example

await ctx.reply({
  content: 'Choose an option:',
  embeds: [myEmbed],
  components: [actionRow],
  ephemeral: true
})

MessageEditOptions

Options for editing messages.
type MessageEditOptions = {
  content?: string
  embeds?: RawEmbed[]
  components?: JsonValue[]
  allowedMentions?: RawAllowedMentions
  flags?: number
}
Similar to MessageReplyOptions but without reply-specific fields.

Example

await ctx.edit({
  content: 'Updated message',
  embeds: [updatedEmbed],
  components: []
})

Builder Classes

All builder classes follow a common pattern:
  1. Chainable setter methods (return this)
  2. toJSON() method to convert to ComponentJson
  3. Type-safe parameters

Example Builder Pattern

const component = builder()
  .setProperty1(value1)  // Returns this
  .setProperty2(value2)  // Returns this
  .setProperty3(value3)  // Returns this
  .toJSON()              // Returns ComponentJson

Notes

  • Always call .toJSON() on builders before passing to messages
  • Component types are Discord-defined numeric constants
  • Maximum 5 action rows per message
  • Maximum 5 buttons or 1 select menu per action row
  • Use ComponentType constants instead of magic numbers
  • Builders provide type safety and validation

Build docs developers (and LLMs) love