Skip to main content

Overview

Flora provides builder functions for creating Discord message components like buttons, select menus, action rows, and more.

Action Rows

actionRow()

Create a container for components. All interactive components must be inside an action row.
const actionRow: () => ActionRowBuilder

Methods

addComponents
(...components: ComponentLike[]) => this
Add one or more components to the row
setComponents
(components: ComponentLike[]) => this
Replace all components with a new array
toJSON
() => ComponentJson
Convert to JSON for Discord API

Example

const row = actionRow()
  .addComponents(
    button().setLabel('Click me').setCustomId('btn_1').setStyle(ButtonStyles.Primary),
    button().setLabel('Cancel').setCustomId('btn_2').setStyle(ButtonStyles.Secondary)
  )
  .toJSON()

await ctx.reply({ 
  content: 'Choose an option', 
  components: [row] 
})

Buttons

button()

Create an interactive button component.
const button: () => ButtonBuilder

Methods

setStyle
(style: number) => this
Set button color style (use ButtonStyles enum)
setCustomId
(customId: string) => this
Set custom ID for identifying button clicks
setLabel
(label: string) => this
Set button text
setUrl
(url: string) => this
Set URL for link buttons (sets style to 5 automatically)
setEmoji
(emoji: string | object) => this
Set button emoji
setDisabled
(disabled?: boolean) => this
Disable the button (default: true)

Button Styles

const ButtonStyles = {
  Primary: 1,    // Blue (blurple)
  Secondary: 2,  // Gray
  Success: 3,    // Green
  Danger: 4      // Red
}

Example

const confirmBtn = button()
  .setLabel('Confirm')
  .setCustomId('confirm_action')
  .setStyle(ButtonStyles.Success)
  .toJSON()

const cancelBtn = button()
  .setLabel('Cancel')
  .setCustomId('cancel_action')
  .setStyle(ButtonStyles.Danger)
  .toJSON()

const row = actionRow()
  .addComponents(confirmBtn, cancelBtn)
  .toJSON()

await ctx.reply({ 
  content: 'Are you sure?',
  components: [row]
})

// Handle button clicks
on('componentInteraction', async (ctx) => {
  const customId = (ctx.msg.data as any)?.custom_id
  if (customId === 'confirm_action') {
    await ctx.reply('Confirmed!')
  }
})

Select Menus

stringSelect()

Create a dropdown menu with custom options.
const stringSelect: (customId: string) => StringSelectMenuBuilder

Methods

setOptions
(options: SelectOption[]) => this
Set the dropdown options
addOptions
(...options: SelectOption[]) => this
Add options to existing ones
setPlaceholder
(placeholder: string) => this
Set placeholder text
setMinValues
(min: number) => this
Minimum number of selections required
setMaxValues
(max: number) => this
Maximum number of selections allowed

Example

const select = stringSelect('role_select')
  .setPlaceholder('Choose your role')
  .addOptions(
    { label: 'Developer', value: 'dev', emoji: '💻' },
    { label: 'Designer', value: 'design', emoji: '🎨' },
    { label: 'Manager', value: 'manager', emoji: '📊' }
  )
  .toJSON()

const row = actionRow().addComponents(select).toJSON()
await ctx.reply({ content: 'Select your role:', components: [row] })

userSelect()

Create a dropdown for selecting users.
const userSelect: (customId: string) => UserSelectMenuBuilder

roleSelect()

Create a dropdown for selecting roles.
const roleSelect: (customId: string) => RoleSelectMenuBuilder

channelSelect()

Create a dropdown for selecting channels.
const channelSelect: (customId: string) => ChannelSelectMenuBuilder

mentionableSelect()

Create a dropdown for selecting users or roles.
const mentionableSelect: (customId: string) => MentionableSelectMenuBuilder

Text Components

textDisplay()

Display static text in a message.
const textDisplay: (content: string) => TextDisplayBuilder

Example

const text = textDisplay('Welcome to the server!')
  .toJSON()

inputText()

Create a text input field (for modals).
const inputText: (customId: string) => InputTextBuilder

Methods

setStyle
(style: number) => this
Set input style (1 = short, 2 = paragraph)
setPlaceholder
(placeholder: string) => this
Set placeholder text
setMinLength
(min: number) => this
Minimum character length
setMaxLength
(max: number) => this
Maximum character length
setValue
(value: string) => this
Pre-fill with a value

Input Styles

const InputTextStyles = {
  Short: 1,      // Single line
  Paragraph: 2   // Multi-line
}

Media Components

thumbnail()

Add a thumbnail image.
const thumbnail: (url: string) => ThumbnailBuilder

mediaGallery()

Create a gallery of images/videos.
const mediaGallery: () => MediaGalleryBuilder

Methods

addItem
(url: string, options?: { description?: string; spoiler?: boolean }) => this
Add a media item to the gallery

Example

const gallery = mediaGallery()
  .addItem('https://example.com/image1.png', { description: 'First image' })
  .addItem('https://example.com/image2.png', { spoiler: true })
  .toJSON()

file()

Embed a file preview.
const file: (url: string) => FileBuilder

Layout Components

section()

Group components into a section.
const section: () => SectionBuilder

container()

Create a container with an accent color.
const container: () => ContainerBuilder

Methods

setAccentColor
(color: number) => this
Set the container’s accent color

separator()

Add a visual separator line.
const separator: (divider?: boolean) => SeparatorBuilder

label()

Add a label to a component.
const label: (labelText: string) => LabelBuilder

fileUpload()

Create a file upload component for collecting files from users.
const fileUpload: (customId: string) => FileUploadBuilder
Methods:
  • setCustomId(customId: string) - Set the custom ID for the file upload
  • setAllowedFileTypes(types: string[]) - Set allowed file types (e.g., ['image/*', '.pdf'])
  • setMaxFileSize(bytes: number) - Set maximum file size in bytes
  • setRequired(required: boolean) - Whether file upload is required
  • toJSON() - Convert to component JSON
Example:
const uploadField = fileUpload('user_avatar')
  .setAllowedFileTypes(['image/*'])
  .setMaxFileSize(5 * 1024 * 1024) // 5MB
  .setRequired(true)
  .toJSON()

Complete Example

const welcomeButtons = actionRow()
  .addComponents(
    button()
      .setLabel('Get Started')
      .setCustomId('start')
      .setStyle(ButtonStyles.Primary),
    button()
      .setLabel('Learn More')
      .setUrl('https://example.com/docs')
  )
  .toJSON()

const roleSelect = actionRow()
  .addComponents(
    stringSelect('choose_role')
      .setPlaceholder('Select your role')
      .addOptions(
        { label: 'Member', value: 'member' },
        { label: 'Contributor', value: 'contributor' }
      )
  )
  .toJSON()

await ctx.reply({
  content: 'Welcome!',
  components: [welcomeButtons, roleSelect]
})

Notes

  • All interactive components must be inside an actionRow()
  • Maximum 5 action rows per message
  • Maximum 5 buttons or 1 select menu per action row
  • Link buttons don’t emit componentInteraction events
  • Always call .toJSON() before passing components to messages

Build docs developers (and LLMs) love