API Reference - @liveblocks/react-lexical
@liveblocks/react-lexical
provides you with a React
plugin that adds collaboration to any Lexical text
editor. 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.
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.

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
andafter
props if you want to keep and extend the default content. AnyReactNode
orToolbar.*
components work inside. - beforeReactNode
The content to display at the start of the toolbar. Any
ReactNode
orToolbar.*
components work inside. - afterReactNode
The content to display at the end of the toolbar. Any
ReactNode
orToolbar.*
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
orchildren
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
orchildren
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.

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
andafter
props if you want to keep and extend the default content. AnyReactNode
orToolbar.*
components work inside. - beforeReactNode
The content to display at the start of the toolbar. Any
ReactNode
orToolbar.*
components work inside. - afterReactNode
The content to display at the end of the toolbar. Any
ReactNode
orToolbar.*
components work inside.
FloatingComposer
Displays a Composer
near the current Lexical selection, allowing you to
create threads.

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
components 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.
- 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.

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
.
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
, up to a full custom Thread
component built 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.

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
.
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
, up to a full custom Thread
component built 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
.
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
.
- threadIdstrinngRequired
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
.
- editorLexicalEditorRequired
The Lexical editor.
- formatTextFormatTypeRequired
The Lexical text format to check for in the current selection.
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.
- 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
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 byLiveblocksPlugin
.synchronized
: The editor state is sync with Liveblocks servers.