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
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]
})
Create an interactive button component.
const button: () => ButtonBuilder
Methods
Set button color style (use ButtonStyles enum)
setCustomId
(customId: string) => this
Set custom ID for identifying button clicks
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)
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!')
}
})
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
Minimum number of selections required
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
Set input style (1 = short, 2 = paragraph)
setPlaceholder
(placeholder: string) => this
Set placeholder text
const InputTextStyles = {
Short: 1, // Single line
Paragraph: 2 // Multi-line
}
thumbnail()
Add a thumbnail image.
const thumbnail: (url: string) => ThumbnailBuilder
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
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