Building a Rich Text Format Toolbar with MUI Toggle Button
As a front-end developer, creating intuitive text formatting tools is a common requirement in applications that deal with content creation. Material UI's ToggleButton component provides an excellent foundation for building text formatting toolbars similar to those you'd find in document editors or content management systems.
In this article, I'll walk you through building a text formatting toolbar focused on the bold formatting feature using MUI's ToggleButton. We'll start with the basics and progressively enhance our implementation to cover advanced use cases, customizations, and best practices.
What You'll Learn
By the end of this tutorial, you'll know how to:
- Implement a text formatting toolbar using MUI's ToggleButton
- Handle state management for text formatting options
- Apply formatting to selected text in various contexts
- Customize the appearance and behavior of the toolbar
- Integrate the toolbar with content editing components
- Optimize performance and ensure accessibility
Understanding MUI ToggleButton Component
Before diving into implementation, let's understand what makes the ToggleButton component perfect for text formatting tools.
What is a ToggleButton?
The ToggleButton component is a button that can be toggled on or off, making it ideal for binary states like enabling/disabling text formatting options. Unlike regular buttons that trigger actions, toggle buttons represent states. This aligns perfectly with formatting controls like bold, italic, or underline, which are either active or inactive for selected text.
MUI's ToggleButton component extends the basic toggle button pattern with Material Design aesthetics and additional features for group management, which is perfect for formatting toolbars where multiple options need to work together.
Key Features of MUI ToggleButton
The ToggleButton component offers several features that make it suitable for text formatting:
- Toggle State Management: It manages selected/unselected states internally, simplifying your code.
- Visual Feedback: It provides clear visual cues for the current state.
- Grouping Capability: ToggleButtonGroup allows for exclusive or non-exclusive selection modes.
- Accessibility: Built-in keyboard navigation and ARIA attributes ensure good accessibility.
- Customization: Extensive styling options through theme overrides, the
sxprop, or styled components.
MUI ToggleButton Deep Dive
Let's explore the ToggleButton component in detail to understand all its capabilities and configuration options.
Component Props
The ToggleButton component accepts several props that control its behavior and appearance.
| Prop | Type | Default | Description |
|---|---|---|---|
| value | any | required | The value to associate with the button when selected |
| selected | bool | false | If true, the button is rendered in a selected state |
| onChange | func | - | Callback fired when the state changes |
| disabled | bool | false | If true, the component is disabled |
| disableFocusRipple | bool | false | If true, the keyboard focus ripple is disabled |
| disableRipple | bool | false | If true, the ripple effect is disabled |
| fullWidth | bool | false | If true, the button will take up the full width of its container |
| size | 'small' | 'medium' | 'large' | 'medium' | The size of the component |
| color | 'standard' | 'primary' | 'secondary' | 'success' | 'error' | 'info' | 'warning' | 'standard' | The color of the component |
When using ToggleButton for text formatting, the value prop is particularly important as it identifies which formatting option the button represents (e.g., 'bold', 'italic'). The selected prop indicates whether that formatting is currently active.
ToggleButtonGroup
For a formatting toolbar, we'll typically use the ToggleButtonGroup component to manage multiple ToggleButtons. This component has its own set of important props:
| Prop | Type | Default | Description |
|---|---|---|---|
| value | any | - | The currently selected value(s) within the group |
| exclusive | bool | false | If true, only allow one button to be selected at a time |
| onChange | func | - | Callback fired when the value changes |
| orientation | 'horizontal' | 'vertical' | 'horizontal' | The component orientation |
| size | 'small' | 'medium' | 'large' | 'medium' | The size of the component |
| color | 'standard' | 'primary' | 'secondary' | 'success' | 'error' | 'info' | 'warning' | 'standard' | The color of the component |
For text formatting, we typically set exclusive to false since multiple formatting options (like bold and italic) can be applied simultaneously to the same text.
Controlled vs Uncontrolled Usage
ToggleButton and ToggleButtonGroup can be used in both controlled and uncontrolled modes:
Controlled Mode: In controlled mode, you manage the state externally and pass it to the component through props. This gives you more control and allows for complex interactions.
Uncontrolled Mode: In uncontrolled mode, the component manages its own state internally.
For a text formatting toolbar, controlled mode is generally preferred because you'll need to synchronize the button states with the actual formatting of the text.
Customization Options
ToggleButton offers several customization options:
- Styling with the
sxprop:
- Theme Overrides:
- Styled Components API:
Accessibility Considerations
ToggleButton comes with good accessibility features out of the box, but there are some best practices to follow:
- Provide meaningful labels: Use
aria-labelfor icon-only buttons. - Group related buttons: Use ToggleButtonGroup with
aria-labelto indicate the purpose of the group. - Maintain focus management: Ensure keyboard navigation works correctly.
Building a Text Formatting Toolbar
Now let's build our text formatting toolbar step by step, focusing on implementing the bold formatting feature.
Setting Up the Project
First, let's set up a new React project and install the necessary dependencies.
Creating the Basic Toolbar Structure
Let's start by creating a basic toolbar with a bold formatting button.
In this basic implementation, we've:
- Created a ToggleButtonGroup to hold our formatting options
- Added a single ToggleButton for bold formatting
- Set up state management to track which formatting options are active
- Wrapped the toolbar in a Paper component for visual elevation
The formats state is an array that keeps track of which formatting options are currently active. When the bold button is clicked, the handleFormat function updates this state.
Adding a Text Editor Area
To make our toolbar functional, we need a text area to apply the formatting to. Let's add a simple text area below our toolbar.
This implementation adds:
- A TextField component for editing text
- State management for the text content
- A ref to access the text field's DOM element
- Logic to apply bold formatting to selected text
In this simple example, we're representing bold text by wrapping it with asterisks (**). In a real-world application, you might use HTML tags, rich text formats, or a dedicated rich text editor library.
Implementing Proper Text Formatting
The previous example is very simplistic. Let's improve it by implementing a more realistic rich text editing approach using the document.execCommand API, which works with contentEditable elements.
This implementation:
- Uses a contentEditable element instead of a TextField
- Applies real bold formatting using
document.execCommand('bold') - Detects current formatting using
document.queryCommandState('bold') - Updates the ToggleButton state to reflect the formatting of the current selection
- Adds event listeners to check formatting when the selection changes
Note that while document.execCommand is widely supported, it's considered deprecated. For production applications, consider using a dedicated rich text editor library like Draft.js, Slate, or Quill.
Enhancing the Toolbar with More Formatting Options
Let's expand our toolbar to include more formatting options like italic and underline.
This enhanced version:
- Adds buttons for italic and underline formatting
- Checks for all three formatting types when updating the state
- Determines which format was changed and applies only that formatting
- Shows pre-formatted text in the editor to demonstrate the formatting options
Creating a Complete Text Formatting Toolbar
Now, let's create a more complete text formatting toolbar with additional features:
This comprehensive text editor includes:
- Text formatting options (bold, italic, underline)
- Text alignment controls (left, center, right, justify)
- Font size selection
- Placeholder buttons for text and background color
- Undo and redo functionality
- Tooltips for better usability
- Responsive layout with dividers between groups
Note that some features like color pickers would need additional implementation in a real-world application.
Optimizing Performance
For better performance, let's optimize our text editor by:
- Debouncing the formatting checks
- Memoizing components
- Using callback refs to avoid unnecessary re-renders
These optimizations help prevent unnecessary re-renders and improve responsiveness:
- Debouncing the formatting check to avoid excessive updates
- Using callback refs instead of useRef with useEffect
- Memoizing the toolbar component to prevent re-renders when unrelated state changes
- Using useCallback for event handlers
Note that you'll need to install lodash for the debounce function:
Integration with Form Libraries
In real-world applications, you might need to integrate your rich text editor with form libraries like Formik or React Hook Form. Here's an example using React Hook Form:
This implementation:
- Integrates with React Hook Form using the Controller component
- Syncs the contentEditable div's HTML with the form state
- Handles form submission with the formatted content
- Preserves all the formatting functionality from previous examples
You'll need to install React Hook Form:
Best Practices and Common Issues
When building text formatting toolbars with MUI ToggleButton, keep these best practices in mind:
Best Practices
-
Maintain State Synchronization: Always keep the toggle button state in sync with the actual formatting of the text. Check formatting when selection changes.
-
Provide Visual Feedback: Use clear icons and consistent visual cues to indicate which formatting options are active.
-
Handle Focus Management: Ensure the editor is focused when formatting is applied, but preserve the text selection.
-
Optimize Performance: Debounce frequent operations like checking formatting on selection changes.
-
Support Keyboard Shortcuts: Implement common keyboard shortcuts (Ctrl+B for bold, etc.) for better usability.
-
Ensure Accessibility: Use proper ARIA labels and ensure keyboard navigation works correctly.
-
Consider Mobile Usage: Make buttons large enough for touch interaction and consider responsive layouts for smaller screens.
Common Issues and Solutions
- Issue: Toggle buttons don't reflect the current formatting. Solution: Implement selection change listeners and update button states accordingly.
- Issue: Formatting is lost when submitting forms. Solution: Capture HTML content before submission and store it properly.
- Issue: Inconsistent formatting behavior across browsers. Solution: Consider using a dedicated rich text editor library for production applications.
- Issue: Text selection is lost when clicking formatting buttons. Solution: Save and restore selection when applying formatting.
Advanced Capabilities
Let's explore some advanced capabilities you can add to your text formatting toolbar:
Custom Formatting Options
You can extend the toolbar with custom formatting options like text highlight or strikethrough:
Nested Formatting Options
You can also implement nested formatting options using MUI's Menu component:
Custom Styling for ToggleButtons
You can create custom-styled toggle buttons to match your application's design:
Wrapping Up
In this article, we've explored how to build a rich text formatting toolbar using MUI's ToggleButton component. We started with the basics of implementing a simple bold formatting button and progressively enhanced our implementation to include multiple formatting options, state management, optimization techniques, and advanced capabilities.
MUI's ToggleButton provides an excellent foundation for building intuitive text formatting tools with its built-in state management, clear visual feedback, and extensive customization options. By following the best practices and addressing common issues outlined in this guide, you can create a robust and user-friendly text formatting experience in your React applications.