API Reference@liveblocks/react-ui

@liveblocks/react-ui provides you with React components to build collaborative experiences. Read our Comments and Notifications get started guides to learn more.

Comments

Default components

Thread

Displays a thread of comments. Each thread has a composer for creating replies.

<Thread thread={thread} />
Thread

Map through threads to render a list of the room’s threads and comments. Threads can be retrieved with useThreads.

import { Thread } from "@liveblocks/react-ui";import { useThreads } from "@liveblocks/react/suspense";
function Component() { const { threads } = useThreads();
return ( <> {threads.map((thread) => ( <Thread key={thread.id} thread={thread} /> ))} </> );}
Resolved and unresolved threads

A thread can be marked as resolved or unresolved via its resolved property. The Thread component automatically handles this through its resolved toggle button displayed by default.

You can additionally use thread.resolved to filter the displayed threads for example. Or if you want to create your own Thread component using the primitives, you can use useMarkThreadAsResolved and useMarkThreadAsUnresolved to update the property.

Props
  • threadThreadDataRequired

    The thread to display.

  • showComposerboolean | "collapsed"Default is "collapsed"

    How to show or hide the composer to reply to the thread.

  • showActionsboolean | "hover"Default is "hover"

    How to show or hide the actions.

  • showReactionsbooleanDefault is true

    Whether to show reactions.

  • showAttachmentsbooleanDefault is true

    Whether to show attachments.

  • showComposerFormattingControlsbooleanDefault is true

    Whether to show the composer’s formatting controls.

  • showResolveActionbooleanDefault is true

    Whether to show the action to resolve the thread.

  • indentCommentContentbooleanDefault is true

    Whether to indent the comments’ content.

  • showDeletedCommentsbooleanDefault is false

    Whether to show deleted comments.

  • onComposerSubmitfunction

    The event handler called when the composer is submitted.

  • onResolvedChangefunction

    The event handler called when changing the resolved status.

  • onThreadDeletefunction

    The event handler called when the thread is deleted. A thread is deleted when all its comments are deleted.

  • onCommentEditfunction

    The event handler called when a comment is edited.

  • onCommentDeletefunction

    The event handler called when a comment is deleted.

  • onAuthorClickfunction

    The event handler called when clicking on a comment’s author.

  • onMentionClickfunction

    The event handler called when clicking on a mention.

  • onAttachmentClickfunction

    The event handler called when clicking on a comment’s attachment.

  • overridesPartial<GlobalOverrides & ThreadOverrides & CommentOverrides & ComposerOverrides>

    Override the component’s strings.

Composer

Displays a composer for creating threads or comments.

<Composer />
Composer

By default, submitting the composer will create a new thread.

import { Composer } from "@liveblocks/react-ui";
// Creates a new threadfunction Component() { return <Composer />;}
Adding thread metadata

If you’d like to attach custom metadata to the newly created thread, you can add a metadata prop.

import { Composer } from "@liveblocks/react-ui";
// Creates a new thread with custom metadatafunction Component() { return ( <Composer metadata={{ // Custom metadata here, e.g. colors, coordinates color: "purple", x: 80, y: 120, }} /> );}
Typed metadata

You can use TypeScript to type your custom metadata by editing your config file. Metadata properties can be string, number, or boolean.

liveblocks.config.ts
declare global {  interface Liveblocks {    // Set your custom metadata types    ThreadMetadata: {      // Example types, e.g. colors, coordinates      color: string;      x: number;      y: number;    };
// Other types // ... }}
Replying to a thread

If you provide a threadId, then submitting the composer will add a new reply to the thread.

import { Composer } from "@liveblocks/react-ui";
// Adds a new comment to a threadfunction Component({ threadId }) { return <Composer threadId={threadId} />;}
Modifying a comment

If you provide both a threadId and a commentId, then submitting the composer will edit the comment.

import { Composer } from "@liveblocks/react-ui";
// Edits an existing commentfunction Component({ threadId, commentId }) { return <Composer threadId={threadId} commentId={commentId} />;}
Custom behavior

If you’d like to customize submission behavior, you can use event.preventDefault() in onComposerSubmit to disable the default behavior and call comment and thread mutation methods manually.

import { Composer } from "@liveblocks/react-ui";import { useEditComment, useAddReaction } from "@liveblocks/react/suspense";
// Custom submission behavior (edits a comment and adds a reaction)function Component({ threadId, commentId }) { const editComment = useEditComment(); const addReaction = useAddReaction();
return ( <Composer onComposerSubmit={({ body, attachments }, event) => { event.preventDefault();
// Example mutations editComment({ threadId, commentId, body, attachments }); addReaction({ threadId, commentId, emoji: "✅" });
// Other custom behavior // ... }} /> );}

Learn more about mutation hooks under @liveblocks/react.

Props
  • threadIdstring

    The ID of the thread to reply to or to edit a comment in.

  • commentIdstring

    The ID of the comment to edit.

  • metadataThreadMetadata

    The metadata of the thread to create.

  • onComposerSubmitfunction

    The event handler called when the composer is submitted.

  • defaultValueCommentBody

    The composer’s initial value.

  • defaultAttachmentsCommentAttachment[]

    The composer’s initial attachments.

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

  • showAttachmentsbooleanDefault is true

    Whether to show and allow adding attachments.

  • showFormattingControlsbooleanDefault is true

    Whether to show formatting controls (e.g. a floating toolbar with formatting toggles when selecting text)

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

Comment

Displays a single comment.

<Comment comment={comment} />
Comment

Map through thread.comments to render each comment in a thread. Threads can be retrieved with useThreads.

import { Comment } from "@liveblocks/react-ui";import { ThreadData } from "@liveblocks/client";
// Renders a list of comments attach to the specified `thread`function Component({ thread }: { thread: ThreadData }) { return ( <> {thread.comments.map((comment) => ( <Comment key={comment.id} comment={comment} /> ))} </> );}
Custom thread components

Comment can be used in combination with Composer to create a custom thread component. The composer in this example is used to reply to the existing thread.

import { Comment, Composer } from "@liveblocks/react-ui";import { ThreadData } from "@liveblocks/client";import { useThreads } from "@liveblocks/react/suspense";
// Renders a list of comments and a composer for adding new commentsfunction CustomThread({ thread }: { thread: ThreadData }) { return ( <> {thread.comments.map((comment) => ( <Comment key={comment.id} comment={comment} /> ))} <Composer threadId={thread.id} /> </> );}
// Renders a list of custom thread componentsfunction Component() { const { threads } = useThreads();
return ( <> {threads.map((thread) => ( <CustomThread key={thread.id} /> ))} </> );}
Props
  • commentCommentDataRequired

    The comment to display.

  • showActionsboolean | "hover"Default is "hover"

    How to show or hide the actions.

  • showReactionsbooleanDefault is true

    Whether to show reactions.

  • showAttachmentsbooleanDefault is true

    Whether to show attachments.

  • showComposerFormattingControlsbooleanDefault is true

    Whether to show the composer’s formatting controls when editing the comment.

  • indentContentbooleanDefault is true

    Whether to indent the comment’s content.

  • showDeletedbooleanDefault is false

    Whether to show the comment if it was deleted. If set to false, it will render deleted comments as null.

  • onCommentEditfunction

    The event handler called when the comment is edited.

  • onCommentDeletefunction

    The event handler called when the comment is deleted.

  • onAuthorClickfunction

    The event handler called when clicking on the author.

  • onMentionClickfunction

    The event handler called when clicking on a mention.

  • onAttachmentClickfunction

    The event handler called when clicking on a comment’s attachment.

  • overridesPartial<GlobalOverrides & CommentOverrides & ComposerOverrides>

    Override the component’s strings.

Primitives

Primitives are unstyled, headless components that can be used to create fully custom commenting experiences.

Composition

All primitives are composable; they forward their props and refs, merge their classes and styles, and chain their event handlers.

Inspired by Radix (and powered by its Slot utility), most of the primitives also support an asChild prop to replace the rendered element by any provided child, and both set of props will be merged.

import { Button } from "@/my-design-system";
// Use the default <button> element<Composer.Submit disabled>Send</Composer.Submit>;
// Use an existing custom <Button> component<Composer.Submit disabled asChild> <Button variant="primary">Send</Button></Composer.Submit>;

Learn more about this concept on Radix’s composition guide.

Composer

Used to render a composer for creating, or editing, threads and comments.

<Composer.Form>  <Composer.AttachmentsDropArea />  <Composer.Editor    components={{      Mention: () => <Composer.Mention />,      MentionSuggestions: () => (        <Composer.Suggestions>          <Composer.SuggestionsList>            <Composer.SuggestionsListItem />          </Composer.SuggestionsList>        </Composer.Suggestions>      ),      Link: () => <Composer.Link />,    }}  />  <Composer.AttachFiles />  <Composer.Submit /></Composer.Form>

Combine with useCreateThread to render a composer that creates threads.

import {  Composer,  CommentBodyLinkProps,  CommentBodyMentionProps,  ComposerEditorMentionSuggestionsProps,  ComposerSubmitComment,} from "@liveblocks/react-ui/primitives";import { useCreateThread, useUser } from "@liveblocks/react/suspense";import { FormEvent } from "react";
// Render a custom composer that creates a thread on submitfunction MyComposer() { const createThread = useCreateThread();
function handleComposerSubmit( { body, attachments }: ComposerSubmitComment, event: FormEvent<HTMLFormElement> ) { event.preventdefault();
// Create a new thread const thread = createThread({ body, attachments, metadata: {}, }); }
return ( <Composer.Form onComposerSubmit={handleComposerSubmit}> <Composer.Editor components={{ Mention, MentionSuggestions, Link, }} /> <Composer.Submit>Create thread</Composer.Submit> </Composer.Form> );}
// Render a mention in the composer's editor, e.g. "@Emil Joyce"function Mention({ userId }: CommentBodyMentionProps) { return <Comment.Mention>@{userId}</Comment.Mention>;}
// Render a list of mention suggestions, used after typing "@" in the editorfunction MentionSuggestions({ userIds, selectedUserId,}: ComposerEditorMentionSuggestionsProps) { return ( <Composer.Suggestions> <Composer.SuggestionsList> {userIds.map((userId) => ( <MentionSuggestion key={userId} userId={userId} /> ))} </Composer.SuggestionsList> </Composer.Suggestions> );}
// Render a single mention suggestion from a `userId`function MentionSuggestion({ userId }: { userId: string }) { const { user } = useUser(userId);
return ( <Composer.SuggestionsListItem value={user.id}> <img src={user.avatar} alt={user.name} /> {user.name} </Composer.SuggestionsListItem> );}
// Render a link in the composer's editor, e.g. "https://liveblocks.io"function Link({ href, children }: CommentBodyLinkProps) { return <Comment.Link href={href}>{children}</Comment.Link>;}
Composer.Form

Surrounds the composer’s content and handles submissions. By default, no action occurs when the composer is submitted. You must create your own mutations within onComposerSubmit for creating threads, creating comments, editing comments, etc.

<Composer.Form  onComposerSubmit={({ body, attachments }) => {    // Mutate your comments    // ...  }}>  {/* ... */}</Composer.Form>
  • defaultAttachmentsCommentAttachment[]

    The composer’s initial attachments.

  • pasteFilesAsAttachmentsbooleanDefault is false

    Whether to create attachments when pasting files into the editor.

  • preventUnsavedChangesbooleanDefault is true

    When preventUnsavedChanges is set on your Liveblocks client on LiveblocksProvider, then closing a browser tab will be prevented when there are unsaved changes. By default, that will include draft text or attachments that are being uploaded via this composer, but not submitted yet. If you want to prevent unsaved changes with Liveblocks, but not for this composer, you can opt-out this composer instance by setting this prop to false.

  • onComposerSubmitfunction

    The event handler called when the form is submitted.

  • disabledbooleanDefault is false

    Whether the composer is disabled.

  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Composer.Editor

Displays the composer’s editor.

<Composer.Editor placeholder="Write a comment…" />
  • defaultValueCommentBody

    The editor’s initial value.

  • placeholderstring

    The text to display when the editor is empty.

  • disabledboolean

    Whether the editor is disabled.

  • autoFocusboolean

    Whether to focus the editor on mount.

  • dir"ltr" | "rtl"

    The reading direction of the editor and related elements.

  • componentsPartial<ComposerEditorComponents>

    The components displayed within the editor.

AttributeValue
data-focusedPresent when the component is focused.
data-disabledPresent when the component is disabled.
components

The components displayed within the editor.

  • MentionComponentType<ComposerEditorMentionProps>

    The component used to display mentions. Defaults to the mention’s userId prefixed by an @.

  • MentionSuggestionsComponentType<ComposerEditorMentionSuggestionProps>

    The component used to display mention suggestions. Defaults to a list of the suggestions’ userId.

  • LinkComponentType<ComposerEditorLinkProps>

    The component used to display links. Defaults to the link’s children property.

  • FloatingToolbarComponentType<ComposerEditorFloatingToolbarProps>

    The component used to display a floating toolbar attached to the selection.

Mention

The component used to display mentions.

<Composer.Editor  components={{    Mention: ({ userId, isSelected }) => (      <Composer.Mention>@{userId}</Composer.Mention>    ),  }}/>
  • userIdstring

    The mention’s user ID.

  • isSelectedboolean

    Whether the mention is selected.

MentionSuggestions

The component used to display mention suggestions.

  • userIdsstring[]

    The list of suggested user IDs.

  • selectedUserIdstring

    he currently selected user ID.

<Composer.Editor  components={{    MentionSuggestions: () => (      <Composer.Suggestions>        <Composer.SuggestionsList>          <Composer.SuggestionsListItem />        </Composer.SuggestionsList>      </Composer.Suggestions>    ),  }}/>
Link

The component used to display links.

<Composer.Editor  components={{    Link: ({ href, children }) => <Composer.Link>{children}</Composer.Link>,  }}/>
  • hrefstring

    The link’s absolute URL.

  • childrenReactNode

    The link’s content.

FloatingToolbar

Displays a floating toolbar attached to the selection within Composer.Editor.

<Composer.Editor  components={{    FloatingToolbar: () => (      <Composer.FloatingToolbar>        <Composer.MarkToggle mark="bold">Bold</Composer.MarkToggle>        <Composer.MarkToggle mark="italic">Italic</Composer.MarkToggle>      </Composer.FloatingToolbar>    ),  }}/>
Composer.Mention

Displays mentions within Composer.Editor.

<Composer.Mention>@{userId}</Composer.Mention>
  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

AttributeValue
data-selectedPresent when the mention is selected.
Composer.Suggestions

Contains suggestions within Composer.Editor.

<Composer.Suggestions>{/* ... */}<Composer.Suggestions>
  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Composer.SuggestionsList

Displays a list of suggestions within Composer.Editor.

<Composer.SuggestionsList>  {userIds.map((userId) => (    <Composer.SuggestionsListItem key={userId} value={userId}>      @{userId}    </Composer.SuggestionsListItem>  ))}</Composer.SuggestionsList>
  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Composer.SuggestionsListItem

Displays a suggestion within Composer.SuggestionsList.

<Composer.SuggestionsListItem key={userId} value={userId}>  @{userId}</Composer.SuggestionsListItem>
  • valuestringRequired

    The suggestion’s value.

  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

AttributeValue
data-selectedPresent when the item is selected.
Composer.Link

Displays links within Composer.Editor.

<Composer.Link href={href}>{children}</Composer.Link>
  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Composer.Submit

A button to submit the composer.

<Composer.Submit>Send</Composer.Submit>
  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Composer.FloatingToolbar

Displays a floating toolbar attached to the selection within Composer.Editor.

<Composer.FloatingToolbar>  <Composer.MarkToggle mark="bold">Bold</Composer.MarkToggle>  <Composer.MarkToggle mark="italic">Italic</Composer.MarkToggle></Composer.FloatingToolbar>
  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Composer.MarkToggle

A toggle button which toggles a specific text mark.

<Composer.MarkToggle mark="bold">Bold</Composer.MarkToggle>
  • markComposerBodyMarkRequired

    The text mark to toggle.

  • onValueChangefunction

    The event handler called when the mark is toggled.

  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Composer.AttachFiles

A button which opens a file picker to create attachments.

<Composer.AttachFiles>Attach files</Composer.AttachFiles>
  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Composer.AttachmentsDropArea

A drop area which accepts files to create attachments.

<Composer.AttachmentsDropArea>Drop files here</Composer.AttachmentsDropArea>
  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Comment

Used to render a single comment.

<Comment.Body  components={{    Mention: <Comment.Mention />,    Link: <Comment.Link />,  }}/>

Map through thread.comments to render each comment in a thread. Threads can be retrieved with useThreads.

import {  Comment,  CommentBodyLinkProps,  CommentBodyMentionProps,} from "@liveblocks/react-ui/primitives";import { ThreadData } from "@liveblocks/client";
// Render custom comments in a thread. Pass a thread from `useThreads`.function MyComments({ thread }: { thread: ThreadData }) { return ( <> {thread.comments.map((comment) => ( <div key={comment.id}> <Comment.Body body={comment.body} components={{ Mention, Link, }} /> </div> ))} </> );}
// Render a mention in the comment, e.g. "@Emil Joyce"function Mention({ userId }: CommentBodyMentionProps) { return <Comment.Mention>@{userId}</Comment.Mention>;}
// Render a link in the comment, e.g. "https://liveblocks.io"function Link({ href, children }: CommentBodyLinkProps) { return <Comment.Link href={href}>{children}</Comment.Link>;}
Comment.Body

Displays a comment body.

<Comment.Body body={comment.body} />
  • bodyCommentBody

    The comment body to display. If not defined, the component will render null.

  • componentsPartial<CommentBodyComponents>

    The components displayed within the comment body.

  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

components

The components displayed within the comment body.

  • MentionComponentType<CommentBodyMentionProps>

    The component used to display mentions. Defaults to the mention’s userId prefixed by an @.

  • LinkComponentType<CommentBodyLinkProps>

    The component used to display links. Defaults to the link’s children property.

Mention

The component used to display mentions.

<Comment.Body  components={{    Mention: ({ userId }) => <Comment.Mention>@{userId}</Comment.Mention>,  }}/>
  • userIdstring

    The mention’s user ID.

Link

The component used to display links.

<Comment.Body  components={{    Link: ({ href, children }) => (      <Comment.Link href={href}>{children}</Comment.Link>    ),  }}/>
  • hrefstring

    The link’s absolute URL.

  • childrenReactNode

    The link’s content.

Comment.Mention

Displays mentions within Comment.Body.

<Comment.Mention>@{userId}</Comment.Mention>
  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Comment.Link

Displays links within Comment.Body.

<Comment.Link href={href}>{children}</Comment.Link>
  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Timestamp

Displays a formatted date, and automatically re-renders to support relative formatting. Defaults to relative formatting for recent dates (e.g. “5 minutes ago”) and a short absolute formatting for older ones (e.g. “25 Aug”).

<Timestamp date={new Date()} />

Use with comment.createdAt, comment.editedAt, or comment.deletedAt to display a human-readable time.

import { ThreadData, Timestamp } from "@liveblocks/react-ui";
function MyComments({ thread }: { thread: ThreadData }) { return ( <> {thread.comments.map((comment) => ( <div key={comment.id}> <Timestamp date={comment.createdAt} /> <Comment.Body body={comment.body} components={/* ... */} /> </div> ))} </> );}
  • dateDate | string | numberRequired

    The date to display.

  • childrenfunction

    A function to format the displayed date. Defaults to a relative date formatting function.

  • titlestring | function

    The title attribute’s value or a function to format it. Defaults to an absolute date formatting function.

  • intervalnumber | falseDefault is 30000

    The interval in milliseconds at which the component will re-render. Can be set to false to disable re-rendering.

  • localestring

    The locale used when formatting the date. Defaults to the browser’s locale.

  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

FileSize

Displays a formatted file size.

<FileSize size={100000} />

Use with attachment.size to display a human-readable file size.

import { CommentData, FileSize } from "@liveblocks/react-ui";
function MyComment({ comment }: { comment: CommentData }) { return ( <div> {/* ... */}
{comment.attachments.map((attachment) => ( <div key={attachment.id}> {attachment.name} <FileSize size={attachment.size} /> </div> ))} </div> );}
  • sizenumberRequired

    The file size to display.

  • childrenfunction

    A function to format the displayed file size. Defaults to a human-readable file size formatting function.

  • localestring

    The locale used when formatting the file size. Defaults to the browser’s locale.

  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

Hooks

useComposer

Returns states and methods related to the composer. Can only be used within the Composer.Form primitive. All values listed below.

import { useComposer } from "@liveblocks/react-ui/primitives";
const { isEmpty, attachments, submit /* ... */ } = useComposer();
Custom composer behavior

useComposer can be used in combination with Composer primitives to create a custom composer, and control its behavior. For example, createMention allows you to create a button which focuses the editor, adds @, and opens the mention suggestions dropdown.

import { Composer, useComposer } from "@liveblocks/react-ui/primitives";import { useCreateThread } from "@liveblocks/react/suspense";
function MyComposer() { const createThread = useCreateThread();
return ( <Composer.Form onComposerSubmit={({ body, attachments }) => { const thread = createThread({ body, attachments, metadata: {}, }); }} > <Editor /> </Composer.Form> );}
function Editor() { const { createMention } = useComposer();
return ( <> <Composer.Editor components={/* Your custom component parts */} /> <button onClick={createMention}>Add mention</button> </> );}
Handle attachments

When using primitives, Composer.AttachFiles and Composer.AttachmentsDropArea add attachments to the composer, but they’re not rendered without useComposer. The attachments array can be used to render the current attachments, and removeAttachment allows you to remove them.

import { Composer, useComposer } from "@liveblocks/react-ui/primitives";import { useCreateThread } from "@liveblocks/react/suspense";
function MyComposer() { const createThread = useCreateThread();
return ( <Composer.Form onComposerSubmit={({ body, attachments }) => { const thread = createThread({ body, attachments, metadata: {}, }); }}> <Composer.Editor components={/* Your custom component parts */} /> <MyComposerAttachments /> <Composer.AttachFiles>Attach Files</Composer.AttachFiles> <Composer.Submit>Submit</Composer.Submit> </Composer.Form> );}
function MyComposerAttachments() { const { attachments, removeAttachment } = useComposer();
return ( <div> {attachments.map((attachment) => ( <div key={attachment.id}> {attachment.name} ({attachment.status}) <button onClick={() => removeAttachment(attachment.id)}>Remove</button> </div> )} </div> );}
Values
  • isDisabledboolean

    Whether the composer is currently disabled.

  • isFocusedboolean

    Whether the editor is currently focused.

  • isEmptyboolean

    Whether the editor is currently empty.

  • canSubmitboolean

    Whether the composer can currently be submitted.

  • submitfunction

    Submit the editor programmatically.

  • clearfunction

    Clear the editor programmatically.

  • selectfunction

    Select the editor programmatically.

  • focusfunction

    Focus the editor programmatically.

  • blurfunction

    Blur the editor programmatically.

  • marksComposerBodyMarks

    Which text marks are currently active and which aren’t.

  • toggleMarkfunction

    Remove an attachment by its ID.

  • createMentionfunction

    Start creating a mention at the current selection.

  • insertTextfunction

    Insert text at the current selection.

  • attachFilesfunction

    Open a file picker programmatically to create attachments.

  • attachmentsComposerAttachment[]

    The composer’s current attachments.

  • removeAttachmentfunction

    Remove an attachment by its ID.

Other hooks

Other Comments hooks are part of @liveblocks/react, you can find them on the React API reference page.

Notifications

Default components

InboxNotification

Displays a single inbox notification.

<InboxNotification inboxNotification={inboxNotification} />
InboxNotification

Map through inboxNotifications with useInboxNotifications to render a list of the room’s notifications.

import { InboxNotification } from "@liveblocks/react-ui";import { useInboxNotifications } from "@liveblocks/react/suspense";
function Component() { const { inboxNotifications } = useInboxNotifications();
return ( <> {inboxNotifications.map((inboxNotification) => ( <InboxNotification key={inboxNotification.id} inboxNotification={inboxNotification} /> ))} </> );}
Rendering notification kinds differently

Different kinds of notifications are available, for example thread which is triggered when using Comments, or $myCustomNotification which would be a custom notification you’ve triggered manually. You can choose to render each notification differently.

<InboxNotification  inboxNotification={inboxNotification}  kinds={{    thread: (props) => (      <InboxNotification.Thread {...props} showRoomName={false} />    ),    $myCustomNotification: (props) => (      <InboxNotification.Custom        {...props}        title="New notification"        aside={<InboxNotification.Icon></InboxNotification.Icon>}      >        My custom notification      </InboxNotification.Custom>    ),  }}/>

Adding these two properties to kinds will overwrite the default component that’s displayed for those two notification types. Using InboxNotification.Thread and InboxNotification.Custom in this way allow you to easily create components that fit into the existing design system, whilst still adding lots of customization. However, it’s also valid to render any custom JSX.

<InboxNotification  inboxNotification={inboxNotification}  kinds={{    $myCustomNotification: (props) => <div>New notification</div>,  }}/>
Typing custom notifications

To type custom notifications, edit the ActivitiesData type in your config file.

liveblocks.config.ts
declare global {  interface Liveblocks {    // Custom activities data for custom notification kinds    ActivitiesData: {      // Example, a custom $alert kind      $alert: {        title: string;        message: string;      };    };
// Other kinds // ... }}

Your activities data is now correctly typed in inline functions.

<InboxNotification  inboxNotification={inboxNotification}  kinds={{    $alert: (props) => {      // `title` and `message` are correctly typed, as defined in your config      const { title, message } = props.inboxNotification.activities[0].data;
return ( <InboxNotification.Custom {...props} title={title} aside={<InboxNotification.Icon></InboxNotification.Icon>} > {message} </InboxNotification.Custom> ); }, }}/>

If you’d like to create a typed function elsewhere, you can use InboxNotificationCustomProps with a generic. In the example below we’re using the $alert notification kind as a generic, InboxNotificationCustomKindProps<"$alert">.

import {  InboxNotification,  InboxNotificationCustomKindProps,} from "@liveblocks/react-ui";
function AlertNotification(props: InboxNotificationCustomKindProps<"$alert">) { // `title` and `message` are correctly typed, as defined in your config const { title, message } = props.inboxNotification.activities[0].data;
return ( <InboxNotification.Custom {...props} title={title} aside={<InboxNotification.Icon></InboxNotification.Icon>} > {message} </InboxNotification.Custom> );}
function Notification({ inboxNotification }) { return ( <InboxNotification inboxNotification={inboxNotification} kinds={{ $alert: AlertNotification }} /> );}
Props
  • inboxNotificationInboxNotificationDataRequired

    The inbox notification to display.

  • hrefstring

    The URL which the inbox notification links to.

  • showActionsboolean | "hover"

    How to show or hide the actions.

  • kindsPartial<InboxNotificationKinds>

    Override specific kinds of inbox notifications.

  • overridesPartial<GlobalOverrides & InboxNotificationOverrides & CommentOverrides>

    Override the component’s strings.

  • componentsPartial<GlobalComponents>

    Override the component’s components.

kinds

Override specific kinds of inbox notifications.

  • threadComponentType<InboxNotificationThreadKindProps>

    The component used to display thread notifications. Defaults to InboxNotification.Thread.

  • $${string}ComponentType<InboxNotificationCustomKindProps>

    The component used to display a custom notification kind. Custom notification kinds must start with a $.

InboxNotification.Thread

Displays a thread inbox notification.

<InboxNotification  inboxNotification={inboxNotification}  kinds={{    thread: (props) => (      <InboxNotification.Thread {...props} showRoomName={false} />    ),  }}/>
  • inboxNotificationInboxNotificationThreadDataRequired

    The inbox notification to display.

  • showActionsboolean | "hover"

    How to show or hide the actions.

  • showRoomNamebooleanDefault is true

    Whether to show the room name in the title.

  • showReactionsbooleanDefault is true

    Whether to show reactions.

  • showAttachmentsbooleanDefault is true

    Whether to show attachments.

InboxNotification.Custom

Displays a custom notification kind.

<InboxNotification  inboxNotification={inboxNotification}  kinds={{    $myCustomNotificationKind: (props) => {      const activityData = props.inboxNotification.activities[0].data;
return( <InboxNotification.Custom title={<>User <strong>{activityData.file}</strong></>} aside={<InboxNotification.Icon></InboxNotification.Icon>} {...props} > {activityData.errorDescription} </InboxNotification> ) }, }}/>
  • inboxNotificationInboxNotificationCustomDataRequired

    The inbox notification to display.

  • titleReactNodeRequired

    The inbox notification’s title.

  • childrenReactNodeRequired

    The inbox notification’s content.

  • showActionsboolean | "hover"

    How to show or hide the actions.

  • asideReactNode

    The inbox notification’s aside content. Can be combined with InboxNotification.Icon or InboxNotification.Avatar to easily follow default styles.

  • asChildbooleanDefault is false

    Replace the rendered element by the one passed as a child.

InboxNotificationList

Displays inbox notifications as a list. Each InboxNotification component will be wrapped in a li element.

<InboxNotificationList>  <InboxNotification />  <InboxNotification />  <InboxNotification /></InboxNotificationList>
InboxNotificationList
Props
  • childrenReactNode

    The inbox notifications to display.

Hooks

All hooks for Notifications are in @liveblocks/react.

Version History

When enabled, version history will automatically create versions of your Lexical or Yjs document and allow you to restore to specific versions. These components aid in displaying a list of those versions.

Default components

HistoryVersionSummary

Displays a version summary which includes the author and date.

<HistoryVersionSummary  onClick={() => {    setSelectedVersionId(version.id);  }}  version={version}  selected={version.id === selectedVersionId}/>
Props
  • onClick() => void

    The function to call when the version summary is clicked.

  • versionVersion

    The version object containing information about the specific version.

  • selectedboolean

    Whether this version is currently selected.

HistoryVersionSummaryList

Displays a list of version summaries for a document’s history including authors and dates.

<HistoryVersionSummaryList>  {versions?.map((version) => (    <HistoryVersionSummary      onClick={() => {        setSelectedVersionId(version.id);      }}      key={version.id}      version={version}      selected={version.id === selectedVersionId}    />  ))}</HistoryVersionSummaryList>
Props
  • childrenReactNode

    The version summaries to display, typically an array of HistoryVersionSummary components.

Utilities

Components

LiveblocksUIConfig

Set configuration options for all @liveblocks/react-ui components, such as overrides.

<LiveblocksUIConfig overrides={{ locale: "fr", USER_UNKNOWN: "Anonyme" }} />
Props
  • overridesPartial<Overrides>

    Override the components’ strings.

  • componentsPartial<Components>

    Override the components’ components.

  • portalContainerHTMLElementDefault is document.body

    The container to render the portal into.

  • preventUnsavedComposerChangesbooleanDefault is true

    When preventUnsavedChanges is set on your Liveblocks client (or set on LiveblocksProvider), then closing a browser tab will be prevented when there are unsaved changes. By default, that will include draft texts or attachments that are (being) uploaded via comments/threads composers, but not submitted yet. If you want to prevent unsaved changes with Liveblocks, but not for composers, you can opt-out by setting this option to false.

Hooks

All hooks for Version History are in @liveblocks/react.

Styling and customization

Default styles

The default components come with default styles. These styles can be imported into the root of your app or directly into a CSS file with @import.

import "@liveblocks/react-ui/styles.css";

Dark mode

You can also import default dark mode styling. There are two versions to choose from, the first uses the system theme.

// Dark mode using the system theme with `prefers-color-scheme`import "@liveblocks/react-ui/styles/dark/media-query.css";

The second uses the dark class name, and two commonly used data attributes.

// Dark mode using `className="dark"`, `data-theme="dark"`, or `data-dark="true"`import "@liveblocks/react-ui/styles/dark/attributes.css";

CSS variables

The default components are built around a set of customizable CSS variables. Set these variables within .lb-root to globally style your components.

/* Styles all default Comments components */.lb-root {  --lb-accent: purple;  --lb-spacing: 1em;  --lb-radius: 0;}
  • --lb-radiusDefault is 0.5em

    The border radius scale. em values recommended.

  • --lb-spacingDefault is 1em

    The spacing scale. em values recommended.

  • --lb-accentDefault is #1177ff

    The accent color.

  • --lb-accent-foregroundDefault is #ffffff

    The foreground color used over the accent color.

  • --lb-destructiveDefault is #ff4455

    The destructive color.

  • --lb-destructive-foregroundDefault is #ffffff

    The foreground color used over the destructive color.

  • --lb-backgroundDefault is #ffffff

    The main background color.

  • --lb-foregroundDefault is #111111

    The main foreground color.

  • --lb-line-heightDefault is 1.5

    The line height of main elements (e.g. comment bodies).

  • --lb-icon-sizeDefault is 20px

    The size of icons.

  • --lb-icon-weightDefault is 1.5px

    The stroke weight of icons.

  • --lb-avatar-radiusDefault is 50%

    The border radius used for avatars.

  • --lb-button-radiusDefault is calc(0.75 * var(--lb-radius))

    The border radius used for buttons.

  • --lb-transition-durationDefault is 0.1s

    The duration used for transitioned elements.

  • --lb-transition-easingDefault is cubic-bezier(0.4, 0, 0.2, 1)

    The easing function used for transitioned elements.

  • --lb-elevation-shadowDefault is 0 0 0 1px rgb(0 0 0 / 4%), 0 2px 6px rgb(0 0 0 / 8%), 0 8px 26px rgb(0 0 0 / 12%)

    The box shadow added to elevated elements.

  • --lb-tooltip-shadowDefault is 0 2px 4px rgb(0 0 0 / 8%), 0 4px 12px rgb(0 0 0 / 12%)

    The box shadow added to tooltips.

  • --lb-accent-contrastDefault is 8%

    Affects the lightness of accent colors. % value required.

  • --lb-destructive-contrastDefault is 8%

    Affects the lightness of destructive colors. % value required.

  • --lb-foreground-contrastDefault is 6%

    Affects the lightness of foreground colors. % value required.

Class names

Each default component has a set of predefined class names, which can be helpful for custom styling, for example.

.lb-thread {