Skip to Content
DocumentationComponentsMulti-Action Button

Multi-action button

A multi-action button is a combination of a dropdown and button. It lets users choose from multiple parallel actions to reduce visual complexity.

Loading...

Overview

Resources

Loading...

Loading...

Loading...

Loading...

Install

yarn add @camp/multi-action-button

Upgrading to Next Gen

The Multi-Action Button has been consolidated from @activecampaign/camp-components-multi-action-button into @camp/multi-action-button. This is a direct 1-to-1 move with no API changes.

  • 🧩 Same API: All props remain identical — no breaking changes

Previous implementation

import MultiActionButton from '@activecampaign/camp-components-multi-action-button'; <MultiActionButton appearance="primary" options={[ { label: 'Option 1', value: 'option-1' }, { label: 'Option 2', value: 'option-2' }, { label: 'Option 3', value: 'option-3' }, ]} triggerLabel="More actions" optionToString={(option) => option.label} onButtonClick={() => {}} onOptionClick={(option) => {}} > Primary Action </MultiActionButton>;

New implementation

import MultiActionButton from '@camp/multi-action-button'; <MultiActionButton appearance="primary" options={[ { label: 'Option 1', value: 'option-1' }, { label: 'Option 2', value: 'option-2' }, { label: 'Option 3', value: 'option-3' }, ]} triggerLabel="More actions" optionToString={(option) => option.label} onButtonClick={() => {}} onOptionClick={(option) => {}} > Primary Action </MultiActionButton>;

Migration steps

  1. Update the import path from @activecampaign/camp-components-multi-action-button to @camp/multi-action-button
  2. No prop changes are required — the API is identical
  3. Your existing option shapes (e.g. { text: 'Copy' }) still work — just keep your optionToString aligned with the shape you pass

Variations

Multi-action buttons provide a primary action and a menu of related actions. They are commonly used in tables. Multi-action buttons largely follow the styling of the Camp button component, and have both primary and secondary appearances.

All Variants

An overview of all button appearances and sizes, including secondary, primary, small, and disabled states.

import MultiActionButton from '@camp/multi-action-button'; const options = [ { label: 'Option 1', value: 'option-1' }, { label: 'Option 2', value: 'option-2' }, { label: 'Option 3', value: 'option-3' }, ]; // Secondary Medium (default) <MultiActionButton options={options} triggerLabel="More actions" optionToString={(option) => option.label} onButtonClick={() => {}} onOptionClick={(option) => {}} > Secondary Medium </MultiActionButton> // Primary Medium <MultiActionButton appearance="primary" options={options} triggerLabel="More actions" optionToString={(option) => option.label} onButtonClick={() => {}} onOptionClick={(option) => {}} > Primary Medium </MultiActionButton> // Small size <MultiActionButton appearance="secondary" size="small" options={options} triggerLabel="More actions" optionToString={(option) => option.label} onButtonClick={() => {}} onOptionClick={(option) => {}} > Secondary Small </MultiActionButton>

Primary Button

The primary appearance of the multi-action button is used sparingly. It’s typically used in a page header bar to indicate multiple page-level actions a user can take.

import MultiActionButton from '@camp/multi-action-button'; <MultiActionButton appearance="primary" options={[ { label: 'Option 1', value: 'option-1' }, { label: 'Option 2', value: 'option-2' }, { label: 'Option 3', value: 'option-3' }, ]} triggerLabel="More actions" optionToString={(option) => option.label} onButtonClick={() => {}} onOptionClick={(option) => {}} > Primary Action </MultiActionButton>;

Secondary Button

The secondary multi-action button appearance is the default appearance. It is named to align with Camp’s secondary button. Use it within a table to provide a menu of table row actions to the user.

import MultiActionButton from '@camp/multi-action-button'; <MultiActionButton options={[ { label: 'Option 1', value: 'option-1' }, { label: 'Option 2', value: 'option-2' }, { label: 'Option 3', value: 'option-3' }, ]} triggerLabel="More actions" optionToString={(option) => option.label} onButtonClick={() => {}} onOptionClick={(option) => {}} > Secondary Action </MultiActionButton>;

Disabled

Both primary and secondary variants support a disabled state that prevents interaction.

import MultiActionButton from '@camp/multi-action-button'; <MultiActionButton appearance="secondary" disabled options={[ { label: 'Option 1', value: 'option-1' }, { label: 'Option 2', value: 'option-2' }, ]} triggerLabel="More actions" optionToString={(option) => option.label} onButtonClick={() => {}} onOptionClick={(option) => {}} > Disabled Action </MultiActionButton>;

Loading Indicator

The loading indicator replaces the button text to show a pending operation.

import MultiActionButton from '@camp/multi-action-button'; <MultiActionButton loadingIndicator options={[ { label: 'Option 1', value: 'option-1' }, { label: 'Option 2', value: 'option-2' }, ]} triggerLabel="More actions" optionToString={(option) => option.label} onButtonClick={() => {}} onOptionClick={(option) => {}} > Loading </MultiActionButton>;

When the trigger button is clicked, a popover menu displays the additional action options.

import MultiActionButton from '@camp/multi-action-button'; <MultiActionButton options={[ { label: 'Option 1', value: 'option-1' }, { label: 'Option 2', value: 'option-2' }, { label: 'Option 3', value: 'option-3' }, ]} triggerLabel="More actions" optionToString={(option) => option.label} onButtonClick={() => {}} onOptionClick={(option) => {}} > Primary Action </MultiActionButton>;

Usage

Best Practices

  • Be consistent with button placement. In button groupings and modals, the primary button should be the furthest to the right.
  • While our buttons do have a disabled state, disabling a button should be avoided as much as possible due to lack of keyboard focus and low contrast. Instead of disabling the button, consider showing a banner or helper text to communicate to the user the needed information.
  • Use the triggerLabel prop to provide an accessible label for the options trigger button (e.g. “More actions” or “More options”).
  • Use optionToString to tell the component how to convert option objects into display strings.

Options

The options prop accepts an array of any shape — the component does not enforce a specific object structure like { label, value }. Display text is always derived from your optionToString function, and the full option object is passed back to onOptionClick. The { label, value } shape used in examples matches the component’s Storybook stories, but any shape works as long as optionToString knows how to read it.

The only fields the component reads directly from an option are:

  • disabled — disables the menu item and blocks its click handler
  • render — an optional per-option custom renderer that overrides defaultOptionRenderer
// Any option shape works — just align optionToString with your data const options = [ { text: 'Copy', id: 'copy' }, { text: 'Delete', id: 'delete', disabled: true }, ]; <MultiActionButton options={options} triggerLabel="More actions" optionToString={(option) => option.text} onOptionClick={(option) => handleAction(option.id)} onButtonClick={handlePrimary} > Save </MultiActionButton>;

Sizes

Buttons come in two sizes, the default medium size and a small size. Which size of the button to use is based on both the importance of the action as well as the context of where it is placed.

  • Medium buttons are used for all primary page actions
  • Small buttons are best suited for supplementary page actions
  • Small buttons can also be used in the headers of other components where height is limited
  • If in groups, button sizes should not be mixed

Content Guidelines

Button labels should be clearly and concisely written (no more than 3 words), in sentence case and with no punctuation at the end. Avoid unnecessary or ambiguous words, but include articles like “a” and “the,” as they provide clarity especially in translating. Use inclusive language that doesn’t discriminate from those who use assistive technology.

✅ DO

  • Create a campaign
  • Import a template
  • Add a contact
  • Add

🚫 DON’T

  • Create New Campaign
  • Import template
  • Click here
  • More

Accessibility

Keyboard Support

  • Move focus to a button using the tab key, and tab again to move to the dropdown arrow button (use shift + tab to move backwards)
  • When the button or dropdown button has keyboard focus, use the space or enter key to perform action
  • When the popover menu is open, use or to navigate the additional options
  • space or enter can also be used to select an option from the list in the popover
  • Press escape to close the popover menu
  • Arrow keys cycle through menu options — pressing on the last option moves focus to the first, and pressing on the first moves focus to the last

ARIA Support

  • The trigger button uses aria-haspopup="true" to indicate it opens a menu
  • The trigger button uses aria-expanded to communicate whether the menu is open or closed
  • Use the triggerLabel prop to set an accessible aria-label on the trigger button

Similar Components

Button

Button

Triggers an action when clicked.

Icon Button

Icon Button

A button that displays an icon instead of text.

Last updated on