ThreadListItem
ThreadListItem renders one row of ThreadList. It has two parts:
ThreadListItemgives the row its thread, whichuseThreadListItemContext()returns, and rendersThreadListItemUI.ThreadListItemUIis the row's look: a button that opens the thread.
Thread UI describes what a row shows and which stores it reads.
Best practices
- Replace
ThreadListItemUIto change how a row looks, and keepThreadListItem. ReplaceThreadListItemonly to change what a row receives. - Read the row's thread with
useThreadListItemContext()and its state withuseStateStore(thread.state, selector). The row already has the thread, so don't query it again. - Open the thread with
openThread(thread)fromuseWorkspaceNavigation(), and mark the open one withisThreadActive(thread.id), as the default row does. - Keep the row light: the list is virtualized, so rows mount and unmount as the user scrolls.
- To change what screen readers announce for a row, wrap the default
ThreadListItemUIand passaccessibleLabelConfig.
What the default row shows
ThreadListItemUI renders a button with the option role. It shows the avatar of the latest reply's author, the channel's name, a preview of the parent message, the avatars of up to three participants, the reply count, the time of the latest reply and the user's unread count.
Clicking it opens the thread; ⌘/ctrl-click asks the layout to open it beside the open one. An unseen thread, one that got replies while it wasn't in the list, is highlighted for two seconds when a reload brings it in.
UI customization
This row keeps the default look and adds the number of participants to its accessible name:
import type {
ThreadListItemLabelConfig,
ThreadListItemUIProps,
} from "stream-chat-react";
import {
DEFAULT_THREAD_LIST_ITEM_LABEL_ORDER,
ThreadList,
ThreadListItemUI,
WithComponents,
} from "stream-chat-react";
const accessibleLabelConfig: ThreadListItemLabelConfig = {
order: [...DEFAULT_THREAD_LIST_ITEM_LABEL_ORDER, "participants"],
parts: {
participants: ({ participantCount }) =>
participantCount ? `${participantCount} participants` : undefined,
},
};
const LabelledThreadListItemUI = (props: ThreadListItemUIProps) => (
<ThreadListItemUI {...props} accessibleLabelConfig={accessibleLabelConfig} />
);
const overrides = { ThreadListItemUI: LabelledThreadListItemUI };
export const ThreadsSidebar = () => (
<WithComponents overrides={overrides}>
<ThreadList />
</WithComponents>
);A part that isn't listed in order never renders. defaultThreadListItemLabelParts holds the default parts, and composeThreadListItemAccessibleLabel(data, config) builds the label for a row of your own. For a row with a different look, see Thread UI.
Props
ThreadListItem
| Prop | Type | Default | Description |
|---|---|---|---|
thread |
Thread |
required | The row's thread. ThreadList passes each thread of client.threads.paginator. |
threadListItemUIProps |
ThreadListItemUIProps |
none | Props passed to ThreadListItemUI. ThreadList passes resetHighlighting for a thread that just arrived. |
ThreadListItemUI
ThreadListItemUI also takes every button prop. They're applied after the SDK's own, so they replace them. onClick is the exception: it runs after the SDK's handler, which opens the thread.
| Prop | Type | Default | Description |
|---|---|---|---|
accessibleLabelConfig |
ThreadListItemLabelConfig |
the default parts, in DEFAULT_THREAD_LIST_ITEM_LABEL_ORDER |
How the row's aria-label is composed: parts to add or replace, their order, the separator, or build for the whole label. |
resetHighlighting |
() => void |
none | Set for a row that just arrived. The row is highlighted while it's set, and calls it after two seconds. |
Related hooks
| Hook | Returns |
|---|---|
useThreadListItemContext() |
the row's thread, or undefined outside a ThreadListItem |
useWorkspaceNavigation() |
openThread and isThreadActive |
useStateStore(thread.state, selector) |
a selection of the thread's state: parent message, reply count, participants, read state |
See useThreadListItemContext and, for the fields of thread.state, Thread and thread manager.