Kombai Logo

Building Quick Action Menus with MUI Floating Action Button for Mobile Layouts

As a front-end developer working with React applications, creating intuitive mobile interfaces often presents unique challenges. One of the most effective UI patterns for mobile layouts is the Floating Action Button (FAB) combined with a quick action menu. I've implemented this pattern countless times across various projects, and it's become an essential tool in my mobile UI toolkit.

In this article, I'll guide you through creating a responsive, accessible, and visually appealing quick action menu using Material UI's Floating Action Button component. You'll learn not just the basics, but also advanced techniques for customization, animation, and proper integration within your React applications.

Learning Objectives

By the end of this tutorial, you'll be able to:

  1. Implement a basic Floating Action Button with Material UI
  2. Create an expandable quick action menu for mobile interfaces
  3. Add smooth animations and transitions to your FAB menu
  4. Customize the appearance and behavior of your FAB components
  5. Handle accessibility concerns for better user experience
  6. Implement advanced patterns like speed dial and conditional rendering
  7. Optimize your FAB menu for performance across devices

Understanding the Floating Action Button Component

The Floating Action Button (FAB) is a circular button that represents the primary action in an application. It's designed to float above the UI, typically in the bottom right corner, making it easily accessible for thumb navigation on mobile devices.

Core FAB Component and Its Properties

Material UI's FAB component is built on top of the ButtonBase component and comes with several variants and customization options. The component is imported from the @mui/material package.

The FAB component accepts numerous props that allow you to customize its appearance and behavior. Here's a comprehensive table of the most important props:

PropTypeDefaultDescription
colorstring'default'The color of the component. Options include 'primary', 'secondary', 'error', 'info', 'success', 'warning', or 'inherit'.
disabledbooleanfalseIf true, the button will be disabled.
disableFocusRipplebooleanfalseIf true, the keyboard focus ripple will be disabled.
disableRipplebooleanfalseIf true, the ripple effect will be disabled.
sizestring'large'The size of the component. Options include 'small', 'medium', and 'large'.
variantstring'circular'The variant to use. Options include 'circular' and 'extended'.
sxobjectThe system prop that allows defining system overrides as well as additional CSS styles.

FAB Variants and Sizes

Material UI's FAB component comes in different variants and sizes to accommodate various design needs. Let's explore these options:

Variants

  1. Circular: The default variant, which renders a circular button.
  2. Extended: A pill-shaped button that can include both an icon and text.

Sizes

The FAB component offers three different sizes:

  1. Small: Compact size, suitable for less prominent actions
  2. Medium: Standard size
  3. Large: Default size, more prominent and easier to tap on mobile

Styling and Customization

The FAB component can be styled in multiple ways, including:

  1. Using the sx prop: For inline styling with access to the theme
  2. Theme customization: For global styling of all FAB components
  3. Styled Components API: For creating reusable styled versions

Here's an example of styling a FAB using the sx prop:

For theme customization, you can override the default styles in your theme:

Accessibility Considerations

When implementing FABs, accessibility should be a primary concern. Here are some best practices:

  1. Always include an aria-label: Since FABs often only contain icons, providing an accessible label is crucial.
  2. Ensure sufficient color contrast: The FAB should stand out against its background.
  3. Provide keyboard navigation: FABs should be focusable and operable via keyboard.
  4. Consider touch target size: FABs should be large enough for easy tapping on mobile (at least 48x48px).

Creating a Basic FAB Implementation

Let's start by creating a simple FAB component that we'll later expand into a full quick action menu. This basic implementation will serve as the foundation for our more advanced features.

Setting Up the Project

First, let's set up a new React project and install the necessary dependencies:

Creating a Basic FAB Component

Now, let's create a basic FAB component that we'll place in the bottom right corner of our application:

In this implementation, we're using the fixed position to ensure the FAB stays in the same position regardless of scrolling. The bottom and right properties position it in the bottom right corner with a 16px margin.

Integrating the FAB into Your App

Let's integrate our BasicFab component into the main App component:

This gives us a basic FAB that appears in the bottom right corner of the screen. Now, let's enhance it to create a quick action menu.

Building a FAB Quick Action Menu

A quick action menu allows users to access frequently used actions without navigating through multiple screens. Let's build a menu that expands when the main FAB is clicked, revealing additional action buttons.

Creating the Expandable FAB Menu

We'll implement an expandable menu that shows additional FABs when the main FAB is clicked:

Let's break down this implementation:

  1. We use a useState hook to track whether the menu is open or closed.
  2. The handleToggle function toggles the menu state when the main FAB is clicked.
  3. We define an array of action items, each with an icon, name, and color.
  4. When the menu is open, we render each action button inside a Zoom component for a staggered animation effect.
  5. The main FAB rotates 45 degrees when the menu is open, turning the plus icon into an X to indicate that clicking it will close the menu.

Adding Transitions and Animations

To make our FAB menu more visually appealing, we've used the Zoom component from Material UI for animations. We've also added a rotation transition to the main FAB.

The transitionDelay property ensures that the action buttons appear in sequence, creating a staggered animation effect. Each button appears 100ms after the previous one, making the expansion feel more natural.

Handling Backdrop and Click Outside

To improve the user experience, let's add a backdrop that appears when the menu is open. Clicking anywhere on the backdrop will close the menu:

The Backdrop component creates a semi-transparent overlay that covers the entire screen when the menu is open. Clicking on this backdrop triggers the handleClose function, which closes the menu.

We've also added appropriate zIndex values to ensure that the menu appears above the backdrop, and the backdrop appears above the rest of the content.

Implementing a Speed Dial Component

Material UI provides a specialized component called SpeedDial that's specifically designed for creating FAB menus. Let's implement our quick action menu using this component:

Basic Speed Dial Implementation

The SpeedDial component handles much of the functionality we implemented manually earlier, including:

  1. Opening and closing the menu
  2. Animating the action buttons
  3. Transforming the main FAB icon

Speed Dial Directions

The SpeedDial component supports different directions for expanding the menu, which is particularly useful for different screen layouts:

In this example, we've added a dropdown to select the direction of the menu expansion. The direction prop of the SpeedDial component determines which way the actions will appear when the menu opens.

Speed Dial Props and Customization

The SpeedDial component and its related components (SpeedDialIcon and SpeedDialAction) offer numerous props for customization:

ComponentPropTypeDescription
SpeedDialariaLabelstringRequired. The aria-label of the SpeedDial for accessibility.
SpeedDialdirectionstringThe direction the actions open. Options: 'up', 'down', 'left', 'right'.
SpeedDialhiddenbooleanIf true, the SpeedDial will be hidden.
SpeedDialiconnodeThe icon to display in the SpeedDial. Usually a SpeedDialIcon component.
SpeedDialonClosefunctionCallback fired when the component requests to be closed.
SpeedDialonOpenfunctionCallback fired when the component requests to be open.
SpeedDialopenbooleanIf true, the component is shown.
SpeedDialopenIconnodeThe icon to display in the SpeedDial when it's open.
SpeedDialFabPropsobjectProps applied to the Fab component.
SpeedDialActioniconnodeThe icon to display in the SpeedDialAction.
SpeedDialActiontooltipTitlenodeThe text to display in the tooltip.
SpeedDialActiontooltipOpenbooleanIf true, the tooltip is always open.
SpeedDialActionFabPropsobjectProps applied to the Fab component.
SpeedDialIconiconnodeThe icon to display in the closed state.
SpeedDialIconopenIconnodeThe icon to display in the open state.

Let's customize our SpeedDial component with some of these props:

In this example, we've customized:

  1. The main FAB with custom icons for both open and closed states
  2. The appearance of the main FAB using the FabProps prop
  3. The appearance of the action FABs using the FabProps prop on each SpeedDialAction

Creating a Context-Aware FAB Menu

Now, let's build a more sophisticated FAB menu that changes its actions based on the current context of the application. This is particularly useful for mobile applications where screen real estate is limited.

Implementing Context-Aware Actions

In this implementation:

  1. We create a context to track the current page or view.
  2. We define different sets of actions for different pages.
  3. The FAB menu dynamically changes its actions based on the current page.
  4. Each action has an associated function that gets called when the action button is clicked.

This approach allows the FAB menu to adapt to the user's current context, providing the most relevant actions for each screen.

Advanced Patterns and Best Practices

Let's explore some advanced patterns and best practices for implementing FAB menus in mobile layouts.

Conditional Rendering Based on Screen Size

For responsive designs, you might want to show the FAB menu only on mobile screens and use different UI patterns on larger screens:

This component uses Material UI's useMediaQuery hook to check if the current screen size is below the "medium" breakpoint. If it's not a mobile device, the component returns null, effectively not rendering the FAB menu.

Scroll-Aware FAB

Another useful pattern is to hide or show the FAB based on the scroll direction. This keeps the FAB out of the way when users are scrolling down to read content, but makes it available when they're scrolling up:

This component:

  1. Tracks the scroll position using the useEffect hook.
  2. Shows the FAB when the user is scrolling up or near the top of the page.
  3. Hides the FAB when the user is scrolling down.
  4. Uses Material UI's Zoom component for a smooth transition effect.

Performance Optimization

When implementing FAB menus, especially with animations and context-awareness, performance can become a concern. Here are some optimization techniques:

This optimized implementation:

  1. Uses memo to prevent unnecessary re-renders of the SpeedDialAction components.
  2. Uses useCallback to memoize event handlers, preventing new function instances on each render.
  3. Pre-defines the actions array outside of the render cycle to prevent recreation on each render.

These optimizations are particularly important for complex FAB menus with many actions or when the parent component renders frequently.

Integrating with Navigation and Forms

FAB menus often need to interact with navigation or form functionality. Let's explore some common integration patterns.

FAB for Form Submission

In this example:

  1. We create a simple form with name and email fields.
  2. The FAB acts as the submit button for the form.
  3. We use the requestSubmit() method to trigger form submission programmatically.
  4. A Snackbar displays a success message when the form is submitted.

This pattern is particularly useful for mobile forms where the primary action (submit) should be easily accessible without scrolling to the bottom of the form.

FAB for Navigation

This component:

  1. Uses a FAB menu for navigation between different pages or views.
  2. Each action in the menu represents a different page.
  3. Clicking on an action changes the current page and updates the UI accordingly.

This pattern is useful for single-page applications or mobile apps where navigation should be easily accessible from any point in the application.

Accessibility Enhancements

Accessibility is crucial for ensuring that all users can interact with your FAB menu. Let's implement some accessibility enhancements:

This implementation includes several accessibility enhancements:

  1. Proper ARIA attributes: We use role="menu", aria-orientation, aria-labelledby, aria-haspopup, aria-expanded, and aria-controls to provide semantic information to screen readers.
  2. Keyboard navigation: We implement keyboard navigation within the menu using arrow keys.
  3. Focus management: We maintain focus within the menu when it's open and return focus to the main FAB when it closes.
  4. Tooltips: We use tooltips to provide additional information about each action.
  5. Escape key handling: We close the menu when the Escape key is pressed.

These enhancements ensure that users who rely on keyboard navigation or screen readers can effectively use the FAB menu.

Troubleshooting Common Issues

When implementing FAB menus, you might encounter some common issues. Here are solutions to these problems:

Z-Index and Stacking Context

In this example, we ensure that the FAB appears above the modal by setting a higher z-index. Material UI's Modal component has a default z-index of 1300, so we set the FAB's z-index to 1500 to make it appear on top.

Touch Target Size

This component demonstrates different FAB sizes and their suitability for touch interfaces. It also shows how to create a custom FAB with a larger touch target area without increasing the visible size of the button.

Animation Performance

This implementation includes performance optimizations for animations:

  1. We use transform: translateZ(0) to enable hardware acceleration.
  2. We use willChange: 'transform, opacity' to hint to the browser that these properties will change, allowing it to optimize in advance.
  3. We keep animations simple and focused on transform and opacity, which are the most performant properties to animate.

These optimizations help ensure smooth animations, especially on mobile devices with limited processing power.

Wrapping Up

In this comprehensive guide, we've explored how to create effective quick action menus using Material UI's Floating Action Button component. We've covered everything from basic implementations to advanced patterns, accessibility enhancements, and performance optimizations.

The FAB is a powerful UI element for mobile layouts, providing quick access to important actions without cluttering the interface. By following the patterns and best practices outlined in this guide, you can create intuitive, accessible, an