@liveblocks/react-lexical

@liveblocks/react-lexical provides you with a React plugin that adds collaboration to any Lexical text editor, powered by Yjs. It also adds realtime cursors, document persistence on the cloud, comments, and mentions. Read our get started guides to learn more.

Setup

To set up your collaborative Lexical editor, you must use LiveblocksPlugin and liveblocksConfig.

LiveblocksPlugin

Liveblocks plugin for Lexical that adds collaboration to your editor.

LiveblocksPlugin should always be nested inside LexicalComposer, and each Lexical default component you’re using should be placed inside the plugin.

Resolved threads

Annotations associated with resolved threads are hidden by default on the editor.

Learn more in our get started guides.

liveblocksConfig

Function that takes a Lexical editor config and modifies it to add the necessary nodes and theme to make LiveblocksPlugin works correctly.

The config created by liveblocksConfig should be passed to initialConfig in LexicalComposer.

Note that liveblocksConfig sets editorState to null because LiveblocksPlugin is responsible for initializing it on the server.

Default components

Toolbar

Displays a toolbar, allowing you to change the styles of selected text. You can add content before or after, or the toolbar’s options can be customized. A floating toolbar also exists.

Toolbar

By default, one of the toolbar buttons can create comment threads—to enable this add FloatingComposer and display threads with AnchoredThreads or FloatingThreads. Should be nested inside LiveblocksPlugin.

Extending the defaults

You can insert content before the first button and after the last button using before and after. Components such as Toolbar.Button and Toolbar.Toggle can be used to create new buttons.

For more complex customization, instead read creating a custom floating toolbar.

Creating a custom toolbar

By passing elements as children, it’s possible to create a fully custom toolbar.

Each part of our default toolbar is available as blocks which can be slotted together. This is how the default toolbar is constructed:

You can mix these default components with any custom ones of your own. Below the Toolbar.SectionHistory component is added alongside some custom buttons created with Toolbar.Button, Toolbar.Toggle, and Icon.

To learn more about the different components, read more below.

Props

  • editorLexicalEditorRequired

    The Lexical editor.

  • childrenReactNode

    The content of the toolbar, overriding the default content. Use the before and after props if you want to keep and extend the default content. Any ReactNode or Toolbar.* components work inside.

  • beforeReactNode

    The content to display at the start of the toolbar. Any ReactNode or Toolbar.* components work inside.

  • afterReactNode

    The content to display at the end of the toolbar. Any ReactNode or Toolbar.* components work inside.

Toolbar.Button

A button for triggering actions. The name is displayed in a tooltip. Props such as onClick will be passed to the underlying button element.

Optionally takes an icon which will visually replace the name. Also optionally accepts a shortcut, which is displayed in the tooltip. Comment key names are converted to symbols. Here are various examples.

Props
  • namestringRequired

    The name of this button displayed in its tooltip. Will also be displayed in the button if no icon or children are passed.

  • iconReactNode

    An optional icon displayed in this button.

  • shortcutstring

    An optional keyboard shortcut displayed in this button’s tooltip. Common shortcuts such will be replaced by their symbols, for example CMD → ⌘.

Toolbar.Toggle

A toggle button for values that can be active or inactive. Best used with text editor commands. The name is displayed in a tooltip. Props will be passed to the underlying button element.

The snippet above shows how to toggle bold styling. The toggle button can also be toggled with useState.

Toolbar.Toggle optionally takes an icon which will visually replace the name. Also optionally accepts a shortcut, which is displayed in the tooltip. Comment key names are converted to symbols. Here are various examples.

Props
  • namestringRequired

    The name of this button displayed in its tooltip. Will also be displayed in the button if no icon or children are passed.

  • activebooleanRequired

    Whether the button is toggled.

  • iconReactNode

    An optional icon displayed in this button.

  • shortcutstring

    An optional keyboard shortcut displayed in this button’s tooltip. Common shortcuts such will be replaced by their symbols, for example CMD → ⌘.

Toolbar.BlockSelector

Adds a dropdown selector for switching between different block types, such as text, heading 1, blockquote. Props will be passed to the inner button element. Can also be placed inside FloatingToolbar.

Use custom item options

If you’d like to change the items shown in the dropdown menu, you can pass a custom items array. Below a code block item (Lexical extension) is added after the default options.

Customize item styles

By passing a label property, you can overwrite the styles of the dropdown items. The toolbar button will still display the name, but in the dropdown, the label will be used instead of the name and icon. Below, a new item is added and its label is customized.

You can also customize the default items. Below each item is styled to represent the effect each block applies to the document.

Props
  • itemsarray | function

    The items displayed in this block selector. When provided as an array, the default items are overridden. To avoid this, a function can be provided instead and it will receive the default items.

Toolbar.Separator

Adds a visual, and accessible, separator used to separate sections in the toolbar. Props will be passed to the inner div element. Can also be placed inside FloatingToolbar.

Toolbar.SectionHistory

Adds a section containing undo and redo buttons. Can also be placed inside FloatingToolbar.

Toolbar.SectionInline

Adds a section containing inline formatting actions such as bold, italic, underline. Can also be placed inside FloatingToolbar.

Toolbar.SectionCollaboration

Adds a section containing an add comment button. Can also be placed inside FloatingToolbar.

FloatingToolbar

Displays a floating toolbar near the current Lexical selection, allowing you to change styles. You can add content before or after, or the toolbar’s options can be customized. A static toolbar also exists.

FloatingToolbar

By default, one of the toolbar buttons can create comment threads—to enable this add FloatingComposer and display threads with AnchoredThreads or FloatingThreads. Should be nested inside LiveblocksPlugin.

Changing float position

Using position and offset you can reposition the toolbar relative to the current selection. position can be set to "top" or "bottom", and offset defines the vertical distance in pixels from the selection.

Extending the defaults

You can insert custom content before the first button and after the last button using before and after. Components such as Toolbar.Button and Toolbar.Toggle can be used to create new buttons.

For more complex customization, instead read creating a custom floating toolbar.

Creating a custom floating toolbar

By passing elements as children, it’s possible to create a fully custom floating toolbar.

Each part of our default toolbar is available as blocks which can be slotted together. This is how the default floating toolbar is constructed:

You can mix these default components with any custom ones of your own. Below the Toolbar.SectionHistory component is added alongside some custom buttons created with Toolbar.Button, Toolbar.Toggle, and Icon.

To learn more about the different components, read more under Toolbar.

Props

  • editorLexicalEditorRequired

    The Lexical editor.

  • position"top" | "bottom"

    The vertical position of the floating toolbar.

  • offsetnumber

    The vertical offset of the floating toolbar from the selection.

  • childrenReactNode

    The content of the toolbar, overriding the default content. Use the before and after props if you want to keep and extend the default content. Any ReactNode or Toolbar.* components work inside.

  • beforeReactNode

    The content to display at the start of the toolbar. Any ReactNode or Toolbar.* components work inside.

  • afterReactNode

    The content to display at the end of the toolbar. Any ReactNode or Toolbar.* components work inside.

FloatingComposer

Displays a Composer near the current Lexical selection, allowing you to create threads.

FloatingComposer

Submitting a comment will attach an annotation thread at the current selection. Should be nested inside LiveblocksPlugin.

Display created threads with AnchoredThreads or FloatingThreads.

Opening the composer

To open the FloatingComposer, you need to dispatch the OPEN_FLOATING_COMPOSER_COMMAND Lexical command.

Customization

The FloatingComposer component acts as a wrapper around a Composer, near the current selection. You can treat the component like you would a form, using classes, listeners, and more.

To apply styling to the composer, you can pass a custom Composer property to components and modify this in any way.

You can return any custom ReactNode here, including anything from a simple wrapper around Composer, up to a full custom Composer component built using our Composer primitives.

You can also customize submission behavior by passing a custom onComposerSubmit function to the Composer.Form component.

Props

  • metadataThreadMetadata

    The metadata of the thread to create.

  • commentMetadataCommentMetadata

    The metadata of the comment to create.

  • onComposerSubmitfunction

    The event handler called when the composer is submitted.

  • defaultValueCommentBody

    The composer’s initial value.

  • collapsedboolean

    Whether the composer is collapsed. Setting a value will make the composer controlled.

  • onCollapsedChangefunction

    The event handler called when the collapsed state of the composer changes.

  • defaultCollapsedboolean

    Whether the composer is initially collapsed. Setting a value will make the composer uncontrolled.

  • disabledboolean

    Whether the composer is disabled.

  • autoFocusboolean

    Whether to focus the composer on mount.

  • overridesPartial<GlobalOverrides & ComposerOverrides>

    Override the component’s strings.

  • componentsPartial<FloatingComposerComponents>

    Override the component’s components.

  • components.Composer(props: ComposerProps) => ReactNode

    Override the Composer component.

FloatingThreads

Displays floating Thread components below text highlights in the editor.

FloatingThreads

Takes a list of threads retrieved from useThreads and renders them to the page. Each thread is opened by clicking on its corresponding text highlight.

Should be nested inside LiveblocksPlugin.

Resolved threads

The FloatingThreads component automatically excludes resolved threads from display. Any resolved threads passed in the threads list will not be shown.

Recommended usage

FloatingThreads and AnchoredThreads have been designed to work together to provide the optimal experience on mobile and desktop. We generally recommend using both components, hiding one on smaller screens, as we are below with Tailwind classes. Most apps also don’t need to display resolved threads, so we can filter those out with a useThreads option.

We can place this component inside ClientSideSuspense to prevent it rendering until threads have loaded.

Customization

The FloatingThreads component acts as a wrapper around each individual Thread. You can treat the component like you would a div, using classes, listeners, and more.

To apply styling to each Thread, you can pass a custom Thread property to components and modify this in any way. This is the best way to modify a thread’s width.

You can return any custom ReactNode here, including anything from a simple wrapper around Thread. You can also use Thread's components prop to customize individual comments, or build a fully custom Thread component using our Comment primitives.

Props

  • threadsThreadData[]Required

    The threads to display.

  • componentsPartial<AnchoredThreadsComponents>

    Override the component’s components.

  • components.Thread(props: ThreadProps) => ReactNode

    Override the Thread component.

AnchoredThreads

Displays a list of Thread components vertically alongside the editor.

AnchoredThreads

Takes a list of threads retrieved from useThreads and renders them to the page. Each thread is displayed at the same vertical coordinates as its corresponding text highlight. If multiple highlights are in the same location, each thread is placed in order below the previous thread.

Should be nested inside LiveblocksPlugin.

Resolved threads

The AnchoredThreads component automatically excludes resolved threads from display. Any resolved threads passed in the threads list will not be shown.

Recommended usage

FloatingThreads and AnchoredThreads have been designed to work together to provide the optimal experience on mobile and desktop. We generally recommend using both components, hiding one on smaller screens, as we are below with Tailwind classes. Most apps also don’t need to display resolved threads, so we can filter those out with a useThreads option.

We can place this component inside ClientSideSuspense to prevent it rendering until threads have loaded.

Customization

The AnchoredThreads component acts as a wrapper around each Thread. It has no width, so setting this is required, and each thread will take on the width of the wrapper. You can treat the component like you would a div, using classes, listeners, and more.

To apply styling to each Thread, you can pass a custom Thread property to components and modify this in any way.

You can return any custom ReactNode here, including anything from a simple wrapper around Thread. You can also use Thread's components prop to customize individual comments, or build a fully custom Thread component using our Comment primitives.

Modifying thread floating positions

Using CSS variables you can modify the gap between threads, and the horizontal offset that’s added when a thread is selected.

Props

  • threadsThreadData[]Required

    The threads to display.

  • componentsPartial<AnchoredThreadsComponents>

    Override the component’s components.

  • components.Thread(props: ThreadProps) => ReactNode

    Override the Thread component.

HistoryVersionPreview

The HistoryVersionPreview component allows you to display a preview of a specific version of your Lexical editor's content. It also contains a button and logic for restoring. It must be used inside the <LiveblocksPlugin> context. To render a list of versions, see VersionHistory. Learn how to set this up in our version history guide.

A version can have no authors when it contains only server-side changes. In that case, HistoryVersionPreview displays “Unattributed edits”. You can customize this text with HISTORY_VERSION_PREVIEW_AUTHORS_LIST.

Usage

Props

  • versionHistoryVersionRequired

    The version of the editor content to preview.

  • onVersionRestore(version: HistoryVersion) => void

    Callback function called when the user chooses to restore this version.

The HistoryVersionPreview component renders a read-only view of the specified version of the editor content. It also provides a button for users to restore the displayed version.

Hooks

useIsEditorReady

Used to check if the editor content has been loaded or not, helpful for displaying a loading skeleton.

Here’s how it can be used in the context of your editor.

useIsThreadActive

Accepts a thread id and returns whether the thread annotation for this thread is selected or not in the Lexical editor. This hook must be used in a component nested inside LiveblocksPlugin.

Arguments
  • threadIdstringRequired

    The ID of the thread.

This hook can be useful to style threads based on whether their associated thread annotations are selected or not in the editor.

Utilities

isTextFormatActive

Checks if a text format (bold, italic, etc.) is active in the current selection. Takes a Lexical editor, and returns a boolean.

Arguments
  • editorLexicalEditorRequired

    The Lexical editor.

  • formatTextFormatTypeRequired

    The Lexical text format to check for in the current selection.

Creating toggle buttons

The isTextFormatActive helper is particularly useful for creating buttons with Toolbar.Toggle.

isBlockNodeActive

Checks if a block node is active in the current selection. If the selection contains multiple block nodes, it will only return true if all of them are of the same type.

Arguments
  • editorLexicalEditorRequired

    The Lexical editor.

  • isActive(node: LexicalNode) => booleanRequired

    Function that passes the current node, helping you check if the current block node is active. Helpful in combination with $is___Node functions.

Creating custom block selector items

The isBlockNodeActive helper is particularly useful for adding custom Toolbar.BlockSelector items.

Stylesheets

React Lexical comes with default styles, and these can be imported into the root of your app or directly into a CSS file with @import. Note that you must also install and import a stylesheet from @liveblocks/react-ui to use these styles.

Customizing your styles

Adding dark mode and customizing your styles is part of @liveblocks/react-ui, learn how to do this under styling and customization.

Deprecated

useEditorStatus

Deprecated

This is no longer supported. Starting with 2.12.0, we recommend using useSyncStatus instead for tracking sync status, because it will reflect sync status of all parts of Liveblocks, not just Storage.

Returns the current editor status.

The possible values are:

  • not-loaded: Initial editor state when entering the room.
  • loading: Once the editor state has been requested by LiveblocksPlugin.
  • synchronized: The editor state is sync with Liveblocks servers.