Skip to content

Commit 73d238e

Browse files
committed
Merge branch 'master' into feat/support-message-bounce-moderation-message-payload
# Conflicts: # package.json # yarn.lock
2 parents 577fa96 + 414745d commit 73d238e

File tree

20 files changed

+721
-151
lines changed

20 files changed

+721
-151
lines changed

docusaurus/docs/React/components/contexts/channel-list-context.mdx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ import { useChannelListContext } from 'stream-chat-react';
2424
export const CustomComponent = () => {
2525
const { channels, setChannels } = useChannelListContext();
2626
// component logic ...
27-
return(
28-
{/* rendered elements */}
29-
);
30-
}
27+
return {
28+
/* rendered elements */
29+
};
30+
};
3131
```
3232

3333
## Value
@@ -37,7 +37,7 @@ export const CustomComponent = () => {
3737
State representing the array of loaded channels. Channels query is executed by default only within the [`ChannelList` component](../core-components/channel-list.mdx) in the SDK.
3838

3939
| Type |
40-
|-------------|
40+
| ----------- |
4141
| `Channel[]` |
4242

4343
### setChannels
@@ -109,5 +109,5 @@ const Sidebar = () => {
109109
```
110110
111111
| Type |
112-
|---------------------------------------|
112+
| ------------------------------------- |
113113
| `Dispatch<SetStateAction<Channel[]>>` |

docusaurus/docs/React/components/core-components/channel-list.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ list from incrementing the list.
187187

188188
### Avatar
189189

190-
Custom UI component to display the user's avatar.
190+
Custom UI component to display the channel avatar. The default avatar component for `ChannelList` is `Avatar`.
191191

192192
| Type | Default |
193193
| --------- | ---------------------------------------------------------- |

docusaurus/docs/React/components/utility-components/avatar.mdx

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,64 @@ id: avatar
33
title: Avatar
44
---
55

6-
The `Avatar` component displays an image, with fallback to the first letter of the optional name prop.
6+
Semantically we can speak about two types of avatars in the SDK. One type is the avatar that represents the channel and the other representing another user. The SDK exports the follwing avatar components:
77

8-
## Basic Usage
8+
- `Avatar` - displays single image or name initials in case image is not available
9+
- `GroupAvatar` - displays images or name initials as a fallback in a 2x2 grid
10+
- `ChannelAvatar` - renders `GroupAvatar` in case a channel has more than two members and `Avatar` otherwise
911

10-
A typical use case for the `Avatar` component would be to import and use in your custom components that will completely override a header component, preview component, or similar.
12+
By default, all the SDK components use `Avatar` to display channel resp. user avatar. However, it makes sense to override the default in `ChannelList` resp. `ChannelPreview` and `ChannelHeader` as those avatars may represent a group of users .
13+
14+
## Customizing avatar component
15+
16+
Passing your custom avatar component to `Channel` prop `Avatar` overrides the avatar for all the `Channel` component's children.
1117

1218
Here's an example of using the `Avatar` component within a custom preview component:
1319

1420
```tsx
15-
import { Avatar } from 'stream-chat-react';
16-
17-
const YourCustomChannelPreview = (props) => {
18-
return (
19-
<div>
20-
<Avatar name={props.displayTitle} image={props.displayImage} />
21-
<div> Other channel info needed in the preview </div>
22-
</div>
23-
);
21+
import { Channel } from 'stream-chat-react';
22+
import type { AvatarProps } from 'stream-chat-react';
23+
24+
const Avatar = (props: AvatarProps) => {
25+
return <div>Custom avatar UI</div>;
2426
};
2527

26-
<ChannelList Preview={YourCustomChannelPreview} />;
28+
<Channel Avatar={Avatar} />;
2729
```
2830

29-
## UI Customization
31+
## Customizing channel avatar
3032

3133
You can also take advantage of the `Avatar` prop on the `ChannelHeader` and `ChannelList` components to override just that aspect of these components specifically, see the example below.
3234

33-
An example of overriding just the `Avatar` component in the default `ChannelPreviewMessenger` component.
35+
An example of overriding just the `Avatar` component in the default `ChannelPreview` component.
3436

3537
```tsx
36-
const CustomAvatar = (props) => {
37-
return <Avatar image={props.image} />;
38+
import { ChannelList } from 'stream-chat-react';
39+
import type { ChannelAvatarProps } from 'stream-chat-react';
40+
41+
const CustomChannelAvatar = (props: ChannelAvatarProps) => {
42+
return <div>Custom Channel Avatar</div>;
3843
};
3944

40-
<ChannelList Preview={(props) => <ChannelPreviewMessenger {...props} Avatar={CustomAvatar} />} />;
45+
<ChannelList Avatar={CustomChannelAvatar} />;
4146
```
4247

43-
## Props
48+
To override the channel avatar in `ChannelHeader` we need to provide it prop `Avatar`:
49+
50+
```tsx
51+
import { ChannelHeader } from 'stream-chat-react';
52+
import type { ChannelAvatarProps } from 'stream-chat-react';
53+
54+
const CustomChannelAvatar = (props: ChannelAvatarProps) => {
55+
return <div>Custom Channel Avatar</div>;
56+
};
57+
58+
<ChannelHeader Avatar={CustomChannelAvatar} />;
59+
```
60+
61+
Also, we can take the advantage of existing SDK's `ChannelAvatar` and pass it to both `ChannelHeader` and `ChannelList` as described above.
62+
63+
## Avatar Props
4464

4565
### className
4666

@@ -89,3 +109,15 @@ The entire user object for the chat user represented by the Avatar component. Th
89109
| Type |
90110
| ------ |
91111
| Object |
112+
113+
## ChannelAvatar Props
114+
115+
Besides the `Avatar` props listed above, the `ChannelAvatar` component accepts the following props.
116+
117+
### groupChannelDisplayInfo
118+
119+
Mapping of image URLs to names which initials will be used as fallbacks in case image assets fail to load.
120+
121+
| Type |
122+
| ------------------------------------- |
123+
| `{ image?: string; name?: string }[]` |

examples/typescript/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type LocalAttachmentType = Record<string, unknown>;
2727
type LocalChannelType = Record<string, unknown>;
2828
type LocalCommandType = string;
2929
type LocalEventType = Record<string, unknown>;
30+
type LocalMemberType = Record<string, unknown>;
3031
type LocalMessageType = Record<string, unknown>;
3132
type LocalPollOptionType = Record<string, unknown>;
3233
type LocalPollType = Record<string, unknown>;
@@ -38,6 +39,7 @@ type StreamChatGenerics = {
3839
channelType: LocalChannelType;
3940
commandType: LocalCommandType;
4041
eventType: LocalEventType;
42+
memberType: LocalMemberType;
4143
messageType: LocalMessageType;
4244
pollOptionType: LocalPollOptionType;
4345
pollType: LocalPollType;

examples/vite/src/App.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ChannelFilters, ChannelOptions, ChannelSort } from 'stream-chat';
22
import {
33
Channel,
4+
ChannelAvatar,
45
ChannelHeader,
56
ChannelList,
67
Chat,
@@ -41,6 +42,7 @@ type LocalAttachmentType = Record<string, unknown>;
4142
type LocalChannelType = Record<string, unknown>;
4243
type LocalCommandType = string;
4344
type LocalEventType = Record<string, unknown>;
45+
type LocalMemberType = Record<string, unknown>;
4446
type LocalMessageType = Record<string, unknown>;
4547
type LocalPollOptionType = Record<string, unknown>;
4648
type LocalPollType = Record<string, unknown>;
@@ -52,6 +54,7 @@ type StreamChatGenerics = {
5254
channelType: LocalChannelType;
5355
commandType: LocalCommandType;
5456
eventType: LocalEventType;
57+
memberType: LocalMemberType;
5558
messageType: LocalMessageType;
5659
pollOptionType: LocalPollOptionType;
5760
pollType: LocalPollType;
@@ -73,10 +76,17 @@ const App = () => {
7376
<ChatView>
7477
<ChatView.Selector />
7578
<ChatView.Channels>
76-
<ChannelList filters={filters} options={options} sort={sort} />
79+
<ChannelList
80+
Avatar={ChannelAvatar}
81+
filters={filters}
82+
options={options}
83+
sort={sort}
84+
showChannelSearch
85+
additionalChannelSearchProps={{ searchForChannels: true }}
86+
/>
7787
<Channel>
7888
<Window>
79-
<ChannelHeader />
89+
<ChannelHeader Avatar={ChannelAvatar} />
8090
<MessageList returnAllReadData />
8191
<MessageInput focus />
8292
</Window>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
"@semantic-release/changelog": "^6.0.2",
187187
"@semantic-release/git": "^10.0.1",
188188
"@stream-io/rollup-plugin-node-builtins": "^2.1.5",
189-
"@stream-io/stream-chat-css": "^5.2.0",
189+
"@stream-io/stream-chat-css": "^5.4.0",
190190
"@testing-library/jest-dom": "^6.1.4",
191191
"@testing-library/react": "^13.1.1",
192192
"@testing-library/react-hooks": "^8.0.0",

src/components/Avatar/Avatar.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ import type { DefaultStreamChatGenerics } from '../../types/types';
1111
export type AvatarProps<
1212
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
1313
> = {
14-
/** Custom class that will be merged with the default class */
14+
/** Custom root element class that will be merged with the default class */
1515
className?: string;
1616
/** Image URL or default is an image of the first initial of the name if there is one */
1717
image?: string | null;
1818
/** Name of the image, used for title tag fallback */
1919
name?: string;
20-
/** click event handler */
20+
/** click event handler attached to the component root element */
2121
onClick?: (event: React.BaseSyntheticEvent) => void;
22-
/** mouseOver event handler */
22+
/** mouseOver event handler attached to the component root element */
2323
onMouseOver?: (event: React.BaseSyntheticEvent) => void;
2424
/** The entire user object for the chat user displayed in the component */
2525
user?: UserResponse<StreamChatGenerics>;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from 'react';
2+
import { Avatar, AvatarProps, GroupAvatar, GroupAvatarProps } from './index';
3+
import type { DefaultStreamChatGenerics } from '../../types';
4+
5+
export type ChannelAvatarProps<
6+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
7+
> = Partial<GroupAvatarProps> & AvatarProps<StreamChatGenerics>;
8+
9+
export const ChannelAvatar = <
10+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
11+
>({
12+
groupChannelDisplayInfo,
13+
image,
14+
name,
15+
user,
16+
...sharedProps
17+
}: ChannelAvatarProps<StreamChatGenerics>) => {
18+
if (groupChannelDisplayInfo) {
19+
return <GroupAvatar groupChannelDisplayInfo={groupChannelDisplayInfo} {...sharedProps} />;
20+
}
21+
return <Avatar image={image} name={name} user={user} {...sharedProps} />;
22+
};
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import clsx from 'clsx';
2+
import React from 'react';
3+
import { Avatar, AvatarProps } from './Avatar';
4+
import { GroupChannelDisplayInfo } from '../ChannelPreview';
5+
6+
export type GroupAvatarProps = Pick<AvatarProps, 'className' | 'onClick' | 'onMouseOver'> & {
7+
/** Mapping of image URLs to names which initials will be used as fallbacks in case image assets fail to load. */
8+
groupChannelDisplayInfo: GroupChannelDisplayInfo;
9+
};
10+
11+
export const GroupAvatar = ({
12+
className,
13+
groupChannelDisplayInfo,
14+
onClick,
15+
onMouseOver,
16+
}: GroupAvatarProps) => (
17+
<div
18+
className={clsx(
19+
`str-chat__avatar-group`,
20+
{ 'str-chat__avatar-group--three-part': groupChannelDisplayInfo.length === 3 },
21+
className,
22+
)}
23+
data-testid='group-avatar'
24+
onClick={onClick}
25+
onMouseOver={onMouseOver}
26+
role='button'
27+
>
28+
{groupChannelDisplayInfo.slice(0, 4).map(({ image, name }, i) => (
29+
<Avatar
30+
className={clsx({
31+
'str-chat__avatar--single': groupChannelDisplayInfo.length === 3 && i === 0,
32+
})}
33+
image={image}
34+
key={`${name}-${image}-${i}`}
35+
name={name}
36+
/>
37+
))}
38+
</div>
39+
);

src/components/Avatar/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export * from './Avatar';
2+
export * from './ChannelAvatar';
3+
export * from './GroupAvatar';

0 commit comments

Comments
 (0)