Skip to content

Toolbar Plugin (components/Editor/plugins/ToolbarPlugin.tsx)

Overview

A Lexical editor plugin that provides a rich text formatting toolbar, featuring text styling controls, undo/redo functionality, and real-time format state tracking.

Features

  • Text formatting controls
  • Undo/redo functionality
  • Format state tracking
  • Real-time updates
  • Selection handling
  • Command registration
  • Visual feedback
  • Modular design

Implementation

Component Structure

function Divider() {
  return <div className={`${styles.toolbar} ${styles.divider}`}/>;
}

export function ToolbarPlugin() {
  const [editor] = useLexicalComposerContext();
  const toolbarRef = useRef(null);
  const [canUndo, setCanUndo] = useState(false);
  const [canRedo, setCanRedo] = useState(false);
  const [isBold, setIsBold] = useState(false);
  const [isItalic, setIsItalic] = useState(false);
  const [isUnderline, setIsUnderline] = useState(false);
  const [isStrikethrough, setIsStrikethrough] = useState(false);

  const $updateToolbar = useCallback(() => {
    const selection = $getSelection();
    if ($isRangeSelection(selection)) {
      setIsBold(selection.hasFormat('bold'));
      setIsItalic(selection.hasFormat('italic'));
      setIsUnderline(selection.hasFormat('underline'));
      setIsStrikethrough(selection.hasFormat('strikethrough'));
    }
  }, []);
}

Command Registration

useEffect(() => {
  const unregisterListener = mergeRegister(
    editor.registerCommand(
      SELECTION_CHANGE_COMMAND,
      (_payload, newEditor) => {
        $updateToolbar();
        return false;
      },
      LowPriority
    ),
    editor.registerCommand(
      CAN_UNDO_COMMAND,
      (payload) => {
        setCanUndo(payload);
        return false;
      },
      LowPriority
    ),
    editor.registerCommand(
      CAN_REDO_COMMAND,
      (payload) => {
        setCanRedo(payload);
        return false;
      },
      LowPriority
    )
  );

  return () => {
    unregisterListener();
  };
}, [$updateToolbar, editor]);

Dependencies

import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { mergeRegister } from '@lexical/utils'
import {
  $getSelection,
  $isRangeSelection,
  CAN_REDO_COMMAND,
  CAN_UNDO_COMMAND,
  FORMAT_ELEMENT_COMMAND,
  FORMAT_TEXT_COMMAND,
  REDO_COMMAND,
  SELECTION_CHANGE_COMMAND,
  UNDO_COMMAND,
} from 'lexical'
import { useCallback, useEffect, useRef, useState } from 'react'

Components Using This

State Management

  • Tracks undo/redo state
  • Manages format states
  • Handles selection changes
  • Controls toolbar visibility
  • Maintains command states
  • Updates format indicators
  • Manages event listeners

Integration Points

  • Lexical editor context
  • Command registration
  • Selection handling
  • Format management
  • Event listeners
  • Style modules
  • Command dispatch

Usage Example

<LexicalComposer initialConfig={editorConfig}>
  <div className="editor-container">
    <ToolbarPlugin />
    <RichTextPlugin
      contentEditable={<ContentEditable />}
      placeholder={<Placeholder />}
      ErrorBoundary={LexicalErrorBoundary}
    />
  </div>
</LexicalComposer>

Notes

  • Implements format tracking
  • Handles command registration
  • Manages selection states
  • Provides visual feedback
  • Supports keyboard shortcuts
  • Maintains clean unregistration
  • Uses CSS modules
  • Licensed under MIT