Cursor Overlay

Loading...
Files
components/demo.tsx
'use client';

import React from 'react';

import { Plate } from '@udecode/plate-common/react';

import { editorPlugins } from '@/components/editor/plugins/editor-plugins';
import { useCreateEditor } from '@/components/editor/use-create-editor';
import { Editor, EditorContainer } from '@/components/plate-ui/editor';

import { DEMO_VALUES } from './values/demo-values';

export default function Demo({ id }: { id: string }) {
  const editor = useCreateEditor({
    plugins: [...editorPlugins],
    value: DEMO_VALUES[id],
  });

  return (
    <Plate editor={editor}>
      <EditorContainer variant="demo">
        <Editor />
      </EditorContainer>
    </Plate>
  );
}

The Cursor Overlay feature provides visual feedback for selections and cursor positions, particularly useful for maintaining context when the editor loses focus or during drag operations.

Features

  • Maintains selection highlight when another element is focused
  • Dynamic selection (e.g. during AI streaming)
  • Shows cursor position during drag operations
  • Customizable styling for cursors and selections
  • Essential for external UI interactions (e.g. link toolbar, AI combobox)

Installation

npm install @udecode/plate-selection

Usage

import { CursorOverlayPlugin } from '@udecode/plate-selection/react';
import { CursorOverlay } from '@/components/plate-ui/cursor-overlay';
const plugins = [
  // ...otherPlugins,
  CursorOverlayPlugin.configure({
    render: { afterEditable: () => <CursorOverlay /> },
  }),
];

Editor Container

The editor requires a container component above PlateContent to ensure correct cursor overlay positioning:

export const EditorContainer = (props: React.HTMLAttributes<HTMLDivElement>) => {
  const editor = useEditorRef();
  const containerRef = useEditorContainerRef();
 
  return <div id={editor.uid} ref={containerRef} {...props} />;
};

This component is available in Editor.

Preserving Selection Focus

To maintain the editor's selection state when focusing UI elements, add the data-plate-focus="true" attribute to those elements:

<ToolbarButton data-plate-focus="true">
  {/* toolbar content */}
</ToolbarButton>

Plugins

CursorOverlayPlugin

Plugin that manages cursor and selection overlays.

Options

Collapse all

    Object containing cursor states. Default: {}

API

editor.api.cursorOverlay.addCursor

Adds a cursor overlay with the specified key and state.

Parameters

Collapse all

    Unique identifier for the cursor (e.g., 'blur', 'drag', 'custom').

    The cursor state including selection and optional styling data.

editor.api.cursorOverlay.removeCursor

Removes a cursor overlay by its key.

Parameters

Collapse all

    The key of the cursor to remove.

Hooks

useCursorOverlay

A hook that manages cursor and selection overlay states, providing real-time cursor positions and selection rectangles.

Parameters

Collapse all

Returns

Collapse all

    Array of cursor states with their corresponding selection rectangles and styling data.

    Function to manually trigger a recalculation of cursor positions.