Threaded Comments

Display all the Threads in a given location, add new Threads, and reply inline with a flexible, embeddable UI component. Threaded Comments is ideal for showing conversations on a page, or creating a comment section.


When to use #

The <ThreadedComments /> component renders a composer and a list of comments. Every new comment created from that composer will appear in the same list. You can react and reply to each comment inline.

This component is great for an all-in-one threaded commenting experience. If you don't want multiple threads, take a look at the single Thread component instead.


How to use #

import { ThreadedComments } from "@cord-sdk/react";

export function Example() {
  return (
    <ThreadedComments
      location={'my-awesome-location'}
      messageOrder={'newest_on_top'}
      composerPosition={'top'}
      topLevelComposerExpanded={'false'}
      onThreadClick={(threadId, threadSummary) =>
        console.log("user clicked on thread:", threadId, threadSummary)
      }
    />
  );
}
Copy

Source code #

Threaded Comments is built on top of our lower-level components and APIs, such as the Message component and our Thread API. The complete source code is available here under a permissive license. You can use it to learn from as an example, or even copy-paste into your own app to remix and build a custom experience.

Github's logoView Source Code


Anatomy #

This diagram shows how Threaded Comments is built using other, smaller, Cord components. Use this to help style your integration, or to break apart and create something new.

Anatomy of the Cord Threaded Comments component

Properties #


location #

required
string

Threads with this location will be shown by the component. Any new threads will also be created with this location.


partialMatch #

optional
boolean
If false, only threads that exactly match the provided location are shown. If true, threads in any partially matching location are also shown.
The default value is false.

messageOrder #

optional
enum

Takes one of two possible values: newest_on_top or newest_on_bottom.

If set to newest_on_top, the comment that was created the most recently will render first, with the rest of the comments following below in reverse chronological order.

If set to newest_on_bottom, the comment that was created the most recently will render last, which means that all comments will be sorted in chronological order.

The default value is newest_on_bottom.


composerPosition #

optional
enum

Takes one of two possible values: top or bottom.

If set to top, the composer will be rendered above the list of threads.

If set to bottom, the composer will be rendered below the list of threads.

If set to none, the composer will not appear at all.

The default value is bottom.


topLevelComposerExpanded #

optional
boolean

If true, the top level composer will always appear expanded. This means that it will always show the button list (such as the mention button and emoji button) right below the editor.

If false, the top level composer will start from a single-line state, but will expand when a user clicks in the editor or starts typing. It will return to a single-line state when it loses focus and there is no input in the editor.

The default value is false.


replyComposerExpanded #

optional
boolean
Applies the exact same behavior as the composerExpanded property above, but to the composers for replying to a thread.

showReplies #

optional
enum

Takes one of the following values: initiallyCollapsed, initiallyExpanded oralwaysCollapsed.

If set to initiallyCollapsed, thread replies will initially show a facepile and the number of replies, if any. On click, the replies will become visible, together with a composer.

If set to initiallyExpanded, all replies will initially be visible. Both hiding them and replying will be available.

If set to alwaysCollapsed, a facepile and the number of replies for a thread will be shown, if there are any, but viewing the replies and replying will be disabled.

The default value is initiallyCollapsed.


highlightThreadId #

optional
string
Passing a thread id will highlight that thread in the ThreadedComments if it exists. If you want to modify how the highlight looks, you can write CSS targeting .cord-threaded-comments.cord-highlighted.

displayResolved #

optional
enum

This prop tells ThreadedComments how to display resolved threads. It takes one of the following values: interleaved, tabbed, resolvedOnly or unresolvedOnly.

If set to interleaved, both resolved and unresolved threads will appear together, sorted by the order specified in the messageOrder property.

If set to tabbed, two tabs will appear on the top part of the component, with "Open" and "Resolved" labels respectively. Clicking on each of them will filter for the relevant threads. Note that when resolved threads are visible, the composer will not be shown since it doesn't make sense to create a new, but already resolved thread.

If set to resolvedOnly, only resolved threads will be shown.

If set to unresolvedOnly, only unresolved threads will be shown.

The default value is unresolvedOnly.


autofocus #

optional
boolean
If true, the top-level composer input field will render with the autofocus HTML attribute set.
The default value is false.

enableFacepileTooltip #

optional
boolean
When true, a tooltip with the user's displayName will appear on the Facepile with the profile pictures of the users who have replied to each thread. The default value is false

threadUrl #

optional
string
The URL of a thread is used to direct users to the correct place when clicking on a notification. The threadUrl defaults to window.location.href. Setting this property would override that default.
Note: The URL specified only applies to new threads and will not change the url of existing threads.
The default value is fine for almost all use cases.

threadName #

optional
string
Sets the name of the newly-created thread. The thread name is used in a small number of places where a short name or header is useful to distinguish the thread. It defaults to the current page's title.
Note: The title specified only applies to new threads and will not change the title of existing threads.
The default value is nearly always fine.

onMessageClick #

optional
function
Callback invoked when a user clicks on a message in the list.
The callback is passed an object containing the threadId and messageId of the message which was clicked as an argument.
For example, you could use this event to scroll your page to the relevant context of the clicked thread.

onLoading #

optional
function
Callback invoked when the component begins loading. Use onRender to determine when loading is complete.

onRender #

optional
function
Callback invoked when the component has finished rendering. Use onLoading to determine when a component begins loading.

onComposerFocus #

optional
function
Callback invoked when a user focuses the composer. The callback is passed an object containing the threadId linked to the composer.

onComposerBlur #

optional
function
Callback invoked when the composer loses focus. The callback is passed an object containing the threadId linked to the composer.

onComposerClose #

optional
function
Callback invoked when a user clicks on the close button in the composer. It is passed an object containing the threadId linked to the composer.
This callback will only be fired by the reply composers, as the top-level composer cannot be closed by users.

onSend #

optional
function
Callback invoked when a user sends a message from a composer. The callback is passed an object containing the threadId and messageId linked to the message sent.

onMessageMouseEnter #

optional
function
Callback invoked when the cursor enters a message.
For example, you could use this event to highlight the section of a webpage being discussed in the hovered message.

onMessageMouseLeave #

optional
function
Callback invoked when the cursor leaves a message.
For example, you could use this event to terminate the special behavior initiated with onMessageMouseEnter.

onMessageEditStart #

optional
function
Callback invoked when a user starts editing a message. Use onMessageEditEnd to determine when editing is complete.

onMessageEditEnd #

optional
function
Callback invoked when a user completes editing a message. Use onMessageEditStart to determine when editing begins.

CSS customization #

If you want to customize this component, you can target the classes below in your app's CSS. These are guaranteed to be stable.

This component itself makes use of the following components. Take a look at their documentation for what classes are available to target within those components.

The following classes are also available specific to this component:

Class nameDescription
.cord-threaded-comments-tab-container
Applied to the tabs that appear on the top of the component.
.cord-threaded-comments-tab
Applied to the individual "Open" and "Resolved" buttons within the aforementioned tabContainer.
.cord-threaded-comments-thread-list
Applied to the high-level list of threads. Although it is a list of threads, it is not actually a ThreadList component, hence the long name.
.cord-threaded-comments-thread
Applied to an individual thread. Although it represents a thread, it is not actually a Thread component, hence the long name.
.cord-threaded-comments-resolved-thread-header
Applied to the header which appears above the avatar and name of resolved threads.
.cord-threaded-comments-reopen-button
Applied to the "Reopen" button, which appears when hovering on the header of a resolved thread.
.cord-expand-replies
Applied to the button below the first message of each thread, to expand the replies to that thread.
.cord-replies-container
Applied to the container holding the Message components which are the replies to a thread. This may appear below the initial message of a thread.
.cord-hide-replies
Applied to the "hide replies" button.
.cord-show-more
Applied to the button to load more threads, as well as the button to load more messages in a thread.
.cord-viewer-avatar-with-composer
Applied to the container containing the combined viewer avatar and composer, which can appear inside each thread as the "reply" composer.

Ask Cordy