Skip to content

Commit d251338

Browse files
fix: rename ChannelListMessenger to ChannelListUI (#3036)
## Renamed Components | Old Name | New Name | Notes | | ---------------------- | --------------- | ------------------------------------------------------------------------------------------------------- | | `ChannelListMessenger` | `ChannelListUI` | File renamed `ChannelListMessenger.tsx` → `ChannelListUI.tsx`; export renamed in `ChannelList/index.ts` | ## Renamed Types / Interfaces | Old Name | New Name | Notes | | --------------------------- | -------------------- | ------------------------------------ | | `ChannelListMessengerProps` | `ChannelListUIProps` | Props type for the renamed component | ## Renamed CSS Classes | Old Name | New Name | | ---------------------------------------- | ------------------------------------ | | `str-chat__channel-list-messenger` | `str-chat__channel-list-inner` | | `str-chat__channel-list-messenger__main` | `str-chat__channel-list-inner__main` | ## Removed Props ### `ChannelListProps` (on `<ChannelList>`) | Removed Prop | Type | Migration | | ----------------------- | ------------------------------------------------- | -------------------------------------------------------------- | | `Avatar` | `React.ComponentType<ChannelAvatarProps>` | Use `Avatar` slot slot in `ComponentContext` instead | | `List` | `React.ComponentType<ChannelListMessengerProps>` | Use `ChannelListUI` slot in `ComponentContext` instead | | `LoadingErrorIndicator` | `React.ComponentType<LoadingErrorIndicatorProps>` | Use `LoadingErrorIndicator` slot in `ComponentContext` instead | | `LoadingIndicator` | `React.ComponentType` | Use `LoadingIndicator` slot in `ComponentContext` instead | | `Preview` | `React.ComponentType<ChannelListItemUIProps>` | Use `ChannelListItemUI` slot in `ComponentContext` instead | ### `ChannelListItemProps` (on `<ChannelListItem>`) | Removed Prop | Type | Migration | | ------------ | ----------------------------------------- | -------------------------------------------------------------- | | `Avatar` | `React.ComponentType<ChannelAvatarProps>` | Now sourced from `ComponentContext` inside `ChannelListItemUI` | ### `ChannelListUIProps` (previously `ChannelListMessengerProps`) | Removed Prop | Type | Migration | | ----------------------- | ------------------------------------------------- | ---------------------------------------------------------- | | `LoadingErrorIndicator` | `React.ComponentType<LoadingErrorIndicatorProps>` | Now sourced from `ComponentContext` inside `ChannelListUI` | | `LoadingIndicator` | `React.ComponentType` | Now sourced from `ComponentContext` inside `ChannelListUI` | ## New `ComponentContext` Slots | Slot | Type | Description | | --------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------- | | `ChannelListUI` | `React.ComponentType<ChannelListUIProps>` | Custom UI component for the channel list container (replaces `List` prop on `<ChannelList>`) | ## Other Breaking Changes - **Removed CSS class suffix:** The root `<ChannelList>` element no longer applies the `str-chat__channel-list-react` class. Previously the default was `str-chat__channel-list str-chat__channel-list-react`, now it is just `str-chat__channel-list`. BREAKING CHANGE: The `ChannelListMessenger` component has been renamed to `ChannelListUI` (props type `ChannelListMessengerProps` -> `ChannelListUIProps`). The corresponding CSS classes `str-chat__channel-list-messenger` and `str-chat__channel-list-messenger__main` have been renamed to `str-chat__channel-list-inner` and `str-chat__channel-list-inner__main` respectively. The `Avatar`, `List`, `LoadingErrorIndicator`, `LoadingIndicator`, and `Preview` props have been removed from the `ChannelList` component. The `Avatar` prop has also been removed from `ChannelListItem`, and the `LoadingErrorIndicator` and `LoadingIndicator` props have been removed from `ChannelListUI`. All of these component overrides should now be provided through `ComponentContext` instead of being passed as props directly. A new `ChannelListUI` slot has been added to `ComponentContext`, replacing the former `List` prop on `ChannelList`. Additionally, the `str-chat__channel-list-react` CSS class is no longer applied to the root `ChannelList` element.
1 parent 61c3f7a commit d251338

14 files changed

Lines changed: 95 additions & 138 deletions

File tree

examples/vite/src/ChatLayout/Panels.tsx

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,20 @@ export const ChannelsPanels = ({
6363
})}
6464
ref={channelsLayoutRef}
6565
>
66-
<ChannelList
67-
Avatar={ChannelAvatar}
68-
customActiveChannel={initialChannelId}
69-
filters={filters}
70-
options={options}
71-
sort={sort}
72-
showChannelSearch
73-
/>
66+
<WithComponents
67+
overrides={{
68+
// @ts-expect-error TODO: adjust the sizing
69+
Avatar: ChannelAvatar,
70+
}}
71+
>
72+
<ChannelList
73+
customActiveChannel={initialChannelId}
74+
filters={filters}
75+
options={options}
76+
sort={sort}
77+
showChannelSearch
78+
/>
79+
</WithComponents>
7480
<SidebarResizeHandle layoutRef={channelsLayoutRef} />
7581
<WithComponents overrides={{ TypingIndicator }}>
7682
<Channel>

src/components/ChannelList/ChannelList.tsx

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,11 @@ import {
1919
usePrepareShapeHandlers,
2020
} from './hooks/useChannelListShape';
2121
import { useStateStore } from '../../store';
22-
import type { ChannelListMessengerProps } from './ChannelListMessenger';
23-
import { ChannelListMessenger } from './ChannelListMessenger';
24-
import type { ChannelAvatarProps } from '../Avatar';
25-
import { Avatar as DefaultAvatar } from '../Avatar';
26-
import type { ChannelListItemUIProps } from '../ChannelListItem/ChannelListItem';
22+
import { ChannelListUI as DefaultChannelListUI } from './ChannelListUI';
2723
import { ChannelListItem } from '../ChannelListItem/ChannelListItem';
2824
import { Search as DefaultSearch } from '../Search';
2925
import type { EmptyStateIndicatorProps } from '../EmptyStateIndicator';
3026
import { EmptyStateIndicator as DefaultEmptyStateIndicator } from '../EmptyStateIndicator';
31-
import { LoadingChannels } from '../Loading/LoadingChannels';
3227
import type { LoadMorePaginatorProps } from '../LoadMore/LoadMorePaginator';
3328
import { LoadMorePaginator } from '../LoadMore/LoadMorePaginator';
3429
import { NotificationList as DefaultNotificationList } from '../Notifications';
@@ -39,11 +34,9 @@ import {
3934
useChatContext,
4035
useComponentContext,
4136
} from '../../context';
42-
import { NullComponent } from '../UtilityComponents';
4337
import { moveChannelUpwards } from './utils';
4438
import type { TranslationContextValue } from '../../context/TranslationContext';
4539
import type { PaginatorProps } from '../../types/types';
46-
import type { LoadingErrorIndicatorProps } from '../Loading';
4740
import { ChannelListHeader } from './ChannelListHeader';
4841
import { useStableId } from '../UtilityComponents/useStableId';
4942

@@ -63,8 +56,6 @@ export type ChannelListProps = {
6356
* to false, which will prevent channels not in the list from incrementing the list. The default is true.
6457
*/
6558
allowNewMessagesFromUnfilteredChannels?: boolean;
66-
/** UI component to display an avatar, defaults to [Avatar](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Avatar/Avatar.tsx) component and accepts the same props as: [ChannelAvatar](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Avatar/ChannelAvatar.tsx) */
67-
Avatar?: React.ComponentType<ChannelAvatarProps>;
6859
/** Optional function to filter channels prior to loading in the DOM. Do not use any complex or async logic that would delay the loading of the ChannelList. We recommend using a pure function with array methods like filter/sort/reduce. */
6960
channelRenderFilterFn?: (channels: Array<Channel>) => Array<Channel>;
7061
// FIXME: how is this even legal (WHY IS IT STRING?!)
@@ -83,12 +74,6 @@ export type ChannelListProps = {
8374
userLanguage: TranslationContextValue['userLanguage'],
8475
isMessageAIGenerated?: ChatContextValue['isMessageAIGenerated'],
8576
) => ReactNode;
86-
/** Custom UI component to display the container for the queried channels, defaults to and accepts same props as: [ChannelListMessenger](https://github.com/GetStream/stream-chat-react/blob/master/src/components/ChannelList/ChannelListMessenger.tsx) */
87-
List?: React.ComponentType<ChannelListMessengerProps>;
88-
/** Custom UI component to display the loading error indicator, defaults to component that renders null */
89-
LoadingErrorIndicator?: React.ComponentType<LoadingErrorIndicatorProps>;
90-
/** Custom UI component to display the loading state, defaults to and accepts same props as: [LoadingChannels](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Loading/LoadingChannels.tsx) */
91-
LoadingIndicator?: React.ComponentType;
9277
/** When true, channels won't dynamically sort by most recent message */
9378
lockChannelOrder?: boolean;
9479
/** Function to override the default behavior when a user is added to a channel, corresponds to [notification.added\_to\_channel](https://getstream.io/chat/docs/javascript/event_object/?language=javascript) event */
@@ -140,8 +125,6 @@ export type ChannelListProps = {
140125
options?: ChannelOptions;
141126
/** Custom UI component to handle channel pagination logic, defaults to and accepts same props as: [LoadMorePaginator](https://github.com/GetStream/stream-chat-react/blob/master/src/components/LoadMore/LoadMorePaginator.tsx) */
142127
Paginator?: React.ComponentType<PaginatorProps | LoadMorePaginatorProps>;
143-
/** Custom UI component to display the channel preview in the list, defaults to and accepts same props as: [ChannelPreviewMessenger](https://github.com/GetStream/stream-chat-react/blob/master/src/components/ChannelPreview/ChannelPreviewMessenger.tsx) */
144-
Preview?: React.ComponentType<ChannelListItemUIProps>;
145128
/**
146129
* Custom interval during which the recovery channel list queries will be prevented.
147130
* This is to avoid firing unnecessary queries during internet connection fluctuation.
@@ -169,16 +152,12 @@ export type ChannelListProps = {
169152
const UnMemoizedChannelList = (props: ChannelListProps) => {
170153
const {
171154
allowNewMessagesFromUnfilteredChannels = true,
172-
Avatar = DefaultAvatar,
173155
channelRenderFilterFn,
174156
customActiveChannel,
175157
customQueryChannels,
176158
EmptyStateIndicator = DefaultEmptyStateIndicator,
177159
filters = {},
178160
getLatestMessagePreview,
179-
List = ChannelListMessenger,
180-
LoadingErrorIndicator = NullComponent,
181-
LoadingIndicator = LoadingChannels,
182161
lockChannelOrder = false,
183162
onAddedToChannel,
184163
onChannelDeleted,
@@ -191,7 +170,6 @@ const UnMemoizedChannelList = (props: ChannelListProps) => {
191170
onRemovedFromChannel,
192171
options,
193172
Paginator = LoadMorePaginator,
194-
Preview,
195173
recoveryThrottleIntervalMs,
196174
renderChannels,
197175
sendChannelsToList = false,
@@ -215,8 +193,12 @@ const UnMemoizedChannelList = (props: ChannelListProps) => {
215193
theme,
216194
useImageFlagEmojisOnWindows,
217195
} = useChatContext('ChannelList');
218-
const { NotificationList = DefaultNotificationList, Search = DefaultSearch } =
219-
useComponentContext(); // FIXME: use component context to retrieve ChannelListItemUI components too
196+
const {
197+
ChannelListUI = DefaultChannelListUI,
198+
NotificationList = DefaultNotificationList,
199+
Search = DefaultSearch,
200+
} = useComponentContext();
201+
220202
const channelListRef = useRef<HTMLDivElement | null>(null);
221203
const [channelUpdateCount, setChannelUpdateCount] = useState(0);
222204

@@ -334,12 +316,10 @@ const UnMemoizedChannelList = (props: ChannelListProps) => {
334316
const renderChannel = (item: Channel) => {
335317
const previewProps = {
336318
activeChannel: channel,
337-
Avatar,
338319
channel: item,
339320
// forces the update of preview component on channel update
340321
channelUpdateCount,
341322
getLatestMessagePreview,
342-
Preview,
343323
setActiveChannel,
344324
watchers,
345325
};
@@ -351,7 +331,7 @@ const UnMemoizedChannelList = (props: ChannelListProps) => {
351331
const className = clsx(
352332
customClasses?.chat ?? 'str-chat',
353333
theme,
354-
customClasses?.channelList ?? `${baseClass} ${baseClass}-react`,
334+
customClasses?.channelList ?? `${baseClass}`,
355335
{
356336
'str-chat--windows-flags':
357337
useImageFlagEmojisOnWindows && navigator.userAgent.match(/Win/),
@@ -369,15 +349,13 @@ const UnMemoizedChannelList = (props: ChannelListProps) => {
369349
<ChannelListHeader />
370350
{showChannelSearch && <Search />}
371351
{showChannelList && (
372-
<List
352+
<ChannelListUI
373353
error={channelsQueryState.error}
374354
loadedChannels={sendChannelsToList ? loadedChannels : undefined}
375355
loading={
376356
!!channelsQueryState.queryInProgress &&
377357
['reload', 'uninitialized'].includes(channelsQueryState.queryInProgress)
378358
}
379-
LoadingErrorIndicator={LoadingErrorIndicator}
380-
LoadingIndicator={LoadingIndicator}
381359
setChannels={setChannels}
382360
>
383361
{!loadedChannels?.length ? (
@@ -393,7 +371,7 @@ const UnMemoizedChannelList = (props: ChannelListProps) => {
393371
: loadedChannels.map((channel) => renderChannel(channel))}
394372
</Paginator>
395373
)}
396-
</List>
374+
</ChannelListUI>
397375
)}
398376
<NotificationList panel='channel-list' />
399377
</div>

src/components/ChannelList/ChannelListMessenger.tsx

Lines changed: 0 additions & 69 deletions
This file was deleted.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React from 'react';
2+
import type { PropsWithChildren } from 'react';
3+
import type { APIErrorResponse, Channel, ErrorFromResponse } from 'stream-chat';
4+
5+
import { LoadingChannels } from '../Loading/LoadingChannels';
6+
import { NullComponent } from '../UtilityComponents';
7+
import { useComponentContext, useTranslationContext } from '../../context';
8+
9+
export type ChannelListUIProps = {
10+
/** Whether the channel query request returned an errored response */
11+
error: ErrorFromResponse<APIErrorResponse> | null;
12+
/** The channels currently loaded in the list, only defined if `sendChannelsToList` on `ChannelList` is true */
13+
loadedChannels?: Channel[];
14+
/** Whether the channels are currently loading */
15+
loading?: boolean;
16+
/** Local state hook that resets the currently loaded channels */
17+
setChannels?: React.Dispatch<React.SetStateAction<Channel[]>>;
18+
};
19+
20+
/**
21+
* A preview list of channels, allowing you to select the channel you want to open
22+
*/
23+
export const ChannelListUI = (props: PropsWithChildren<ChannelListUIProps>) => {
24+
const { children, error = null, loading = false } = props;
25+
const { LoadingErrorIndicator = NullComponent, LoadingIndicator = LoadingChannels } =
26+
useComponentContext('ChannelListUI');
27+
const { t } = useTranslationContext('ChannelListUI');
28+
29+
if (error) {
30+
return <LoadingErrorIndicator error={error} />;
31+
}
32+
33+
return (
34+
<div className='str-chat__channel-list-inner'>
35+
<div
36+
aria-label={t('aria/Channel list')}
37+
className='str-chat__channel-list-inner__main'
38+
role='listbox'
39+
>
40+
{loading ? <LoadingIndicator /> : children}
41+
</div>
42+
</div>
43+
);
44+
};

src/components/ChannelList/__tests__/ChannelList.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import {
4646
useChatContext,
4747
WithComponents,
4848
} from '../../../context';
49-
import { ChannelListMessenger } from '../ChannelListMessenger';
49+
import { ChannelListUI } from '../ChannelListUI';
5050

5151
expect.extend(toHaveNoViolations);
5252

@@ -391,7 +391,7 @@ describe('ChannelList', () => {
391391

392392
const ChannelListMessengerPropsInterceptor = (props) => {
393393
channelListMessengerLoadingHistory.push(props.loading);
394-
return <ChannelListMessenger {...props} />;
394+
return <ChannelListUI {...props} />;
395395
};
396396

397397
await render(

src/components/ChannelList/__tests__/ChannelListMessenger.test.js renamed to src/components/ChannelList/__tests__/ChannelListUI.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22
import { cleanup, render } from '@testing-library/react';
33
import '@testing-library/jest-dom';
44

5-
import { ChannelListMessenger } from '../ChannelListMessenger';
5+
import { ChannelListUI } from '../ChannelListUI';
66
import { TranslationProvider } from '../../../context';
77
import { mockTranslationContext } from '../../../mock-builders';
88

@@ -12,15 +12,15 @@ console.warn = () => null;
1212

1313
const Component = ({ error = false, loading = false }) => (
1414
<TranslationProvider value={mockTranslationContext}>
15-
<ChannelListMessenger
15+
<ChannelListUI
1616
error={error}
1717
loading={loading}
1818
LoadingErrorIndicator={() => <div>Loading Error Indicator</div>}
1919
LoadingIndicator={() => <div>Loading Indicator</div>}
2020
>
2121
<div>children 1</div>
2222
<div>children 2</div>
23-
</ChannelListMessenger>
23+
</ChannelListUI>
2424
</TranslationProvider>
2525
);
2626

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
export * from './ChannelList';
2-
export * from './ChannelListMessenger';
2+
export * from './ChannelListUI';
33
export * from './hooks';
44
export * from './utils';

src/components/ChannelList/styling/ChannelList.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,12 @@
123123
@include utils.scrollable-y;
124124
@include utils.component-layer-overrides('channel-list');
125125

126-
.str-chat__channel-list-messenger {
126+
.str-chat__channel-list-inner {
127127
height: 100%;
128128
overflow: hidden;
129129
padding-bottom: var(--str-chat__spacing-2_5);
130130

131-
.str-chat__channel-list-messenger__main {
131+
.str-chat__channel-list-inner__main {
132132
height: 100%;
133133
overflow-y: auto;
134134

src/components/ChannelListItem/ChannelListItem.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { getLatestMessagePreview as defaultGetLatestMessagePreview } from './uti
1010
import { useTranslationContext } from '../../context/TranslationContext';
1111
import { useMessageDeliveryStatus } from './hooks/useMessageDeliveryStatus';
1212
import type { MessageDeliveryStatus } from './hooks/useMessageDeliveryStatus';
13-
import type { ChannelAvatarProps } from '../Avatar/ChannelAvatar';
1413
import type { GroupChannelDisplayInfo } from './utils';
1514
import {
1615
type ChatContextValue,
@@ -47,8 +46,6 @@ export type ChannelListItemProps = {
4746
active?: boolean;
4847
/** Current selected channel object */
4948
activeChannel?: Channel;
50-
/** UI component to display an avatar, defaults to [Avatar](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Avatar/Avatar.tsx) component and accepts the same props as: [ChannelAvatar](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Avatar/ChannelAvatar.tsx) */
51-
Avatar?: React.ComponentType<ChannelAvatarProps>;
5249
/** Forces the update of preview component on channel update */
5350
channelUpdateCount?: number;
5451
/** Custom class for the channel preview root */

src/components/ChannelListItem/ChannelListItemTimestamp.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ export function ChannelListItemTimestamp({ lastMessage }: ChannelListItemTimesta
3030
if (!when) return null;
3131

3232
return (
33-
<time className='str-chat__channel-list-item-timestamp' dateTime={normalizedTimestamp}>
33+
<time
34+
className='str-chat__channel-list-item-timestamp'
35+
dateTime={normalizedTimestamp}
36+
>
3437
{when}
3538
</time>
3639
);

0 commit comments

Comments
 (0)