MD3
Expressive
MATERIAL DESIGN 3 EXPRESSIVE

Floating Action Button (FAB) Menu

The FAB menu opens from a Floating Action Button to display multiple related actions with smooth MD3 staggered animations.

Floating Action Button menus help group related actions under a single, prominent floating button. On tap, the FAB transforms and reveals a list of specific actions.

Introduction

The MD3 Expressive FAB Menu (or Speed Dial) is an advanced variant of the FAB. It allows a single primary action button to expand into a suite of related actions, saving screen space while keeping multiple options easily accessible. It features high-end staggered entrance animations and a fluid transformation of the main toggle button.

Anatomy

  • Main FAB (Toggle): The primary button that the user interacts with to open the menu. Often changes its icon (e.g., from "Add" to "Close") when expanded.
  • Menu Items: A vertical list of secondary action buttons that appear above or below the main FAB.
  • Labels: Descriptive text for each menu item, typically displayed next to the secondary icons.
  • Scrim (Optional): A subtle background dimming that appears when the menu is open to focus attention.

Variants

Sizes

The main toggle FAB supports the three standard MD3 Expressive sizes:

  • Baseline (Default)
  • Medium
  • Large
Loading demo...

Color Styles

FAB Menus can be styled using Primary, Secondary, or Tertiary container roles, which are applied consistently to the toggle and all menu items.

Loading demo...

Features

Staggered Animations

When the menu opens, the items appear one after another with a slight delay, creating a fluid, "waterfall" effect that is a hallmark of Material Design 3 Expressive.

Alignment

Items can be aligned to the start or end of the toggle FAB, allowing for flexible positioning in different corners of the screen.

Loading demo...

Usage

Basic Usage

import { FABMenu, Icon } from "@bug-on/m3-expressive";

export function Example() {
  const [isOpen, setIsOpen] = useState(false);

  const actions = [
    { id: 'image', label: 'Image', icon: <Icon name="image" />, onClick: () => {} },
    { id: 'video', label: 'Video', icon: <Icon name="videocam" />, onClick: () => {} },
    { id: 'file', label: 'File', icon: <Icon name="description" />, onClick: () => {} },
  ];

  return (
    <FABMenu
      expanded={isOpen}
      onToggle={setIsOpen}
      items={actions}
      aria-label="Create new content"
    />
  );
}

Best Practices

Do

  • Use a FAB Menu for 3 to 6 related actions.
  • Ensure the main toggle icon clearly communicates that it can be expanded (e.g., an "Add" or "Menu" icon).
  • Provide clear labels for all secondary actions.
  • Use consistent color styles for all elements in the menu.

Don't

  • Don't use a FAB Menu for actions that are completely unrelated.
  • Avoid putting more than 6 actions in a single FAB Menu; it can become difficult to use and visually cluttered.
  • Don't use a FAB Menu if the actions are critical and should be always visible (use a Toolbar instead).

Accessibility

  • Keyboard: Press Esc to close the menu. Use Arrow keys or Tab to navigate through items.
  • Roles: Correctly implements role="menu" and role="menuitem".
  • States: Uses aria-expanded on the main toggle to signal the state to screen readers.
  • Labels: Every menu item requires a label for both visual clarity and accessibility.

API Reference

FABMenu

PropTypeDefaultDescription
expandedbooleanRequired. Controlled open state.
onToggle(open: boolean) => voidRequired. Open state change callback.
itemsFABMenuItemData[]Required. Array of action items.
colorVariantstring"primaryContainer"MD3 color roles.
size"sm" | "md" | "lg""sm"FAB size variant controlling container dimensions per MD3 Extended FAB specification.
alignment"start" | "end""end"Staggered layout alignment.

FABMenuItemData

PropertyTypeDefaultDescription
idstringRequired. Unique ID.
labelstringRequired. Action label.
iconReactNodeRequired. Item icon.
onClick() => voidAction callback.
disabledbooleanfalseDisables the item.
asChildbooleanfalseRenders the menu item as a child element (e.g. Next.js Link).