Cursor Overlay

Visual feedback for selections and cursor positions when editor loses focus.

Loading...

Features

  • Maintains selection highlight when another element is focused.
  • Dynamic selection display (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).

Kit Usage

Installation

The fastest way to add cursor overlay functionality is with the CursorOverlayKit, which includes the pre-configured CursorOverlayPlugin and the CursorOverlay UI component.

Add Kit

import { createPlateEditor } from 'platejs/react';
import { CursorOverlayKit } from '@/components/editor/plugins/cursor-overlay-kit';
 
const editor = createPlateEditor({
  plugins: [
    // ...otherPlugins,
    ...CursorOverlayKit,
  ],
});

Manual Usage

Installation

pnpm add @platejs/selection

Add Plugin

import { CursorOverlayPlugin } from '@platejs/selection/react';
import { createPlateEditor } from 'platejs/react';
 
const editor = createPlateEditor({
  plugins: [
    // ...otherPlugins,
    CursorOverlayPlugin,
  ],
});

Configure Plugin

Configure the cursor overlay with a component to render overlays:

import { CursorOverlayPlugin } from '@platejs/selection/react';
import { CursorOverlay } from '@/components/ui/cursor-overlay';
 
CursorOverlayPlugin.configure({
  render: {
    afterEditable: () => <CursorOverlay />,
  },
});
  • render.afterEditable: Assigns CursorOverlay to render after the editable content.

Editor Container Setup

The cursor overlay requires a container component to ensure correct positioning. If you're using the Editor component, this is handled automatically through EditorContainer.

For custom setups, ensure your editor is wrapped with a container that has the editor's unique ID:

import { PlateContainer } from 'platejs/react';
 
export function EditorContainer(props: React.HTMLAttributes<HTMLDivElement>) {
  return <PlateContainer {...props} />;
}

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>

This prevents the cursor overlay from disappearing when interacting with toolbar buttons or other UI elements.

Plugins

CursorOverlayPlugin

Plugin that manages cursor and selection overlays for visual feedback.

Options

  • cursors Record<string, CursorState<CursorData>>

    Object containing cursor states with their unique identifiers.

    • Default: {}

API

api.cursorOverlay.addCursor

Adds a cursor overlay with the specified key and state.

Parameters

Collapse all
  • key string

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

  • cursor CursorState<CursorData>

    The cursor state including selection and optional styling data.

api.cursorOverlay.removeCursor

Removes a cursor overlay by its key.

Parameters

Collapse all
  • key string

    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.

Optionsobject

Collapse all
  • minSelectionWidth optional number

    Minimum width in pixels for a selection rectangle. Useful for making cursor carets more visible.

    • Default: 1
  • refreshOnResize optional boolean

    Whether to recalculate cursor positions when the container is resized.

    • Default: true

Returnsobject

Collapse all
  • cursors CursorOverlayState<TCursorData>[]

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

  • refresh () => void

    Function to manually trigger a recalculation of cursor positions.