Skip to content

Commit 2050708

Browse files
fix(emoji-mart): new reactions (#1947)
BREAKING CHANGE: `reactionOptions` signature has changed, see [release guide](https://github.com/GetStream/stream-chat-react/blob/7a19e386aa3adcc5741a7f0d92bc816a1a424094/docusaurus/docs/React/release-guides/new-reactions.mdx) for more information
1 parent bd32b26 commit 2050708

File tree

23 files changed

+737
-353
lines changed

23 files changed

+737
-353
lines changed
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import React from 'react';
22

3-
const GHComponentLink = ({text, path}) => {
4-
return <a target='_blank' href={`https://github.com/GetStream/stream-chat-react/blob/master/src/components${path}`}>{text}</a>
5-
}
3+
const GHComponentLink = ({ text, path, branch = 'master' }) => {
4+
return (
5+
<a
6+
target='_blank'
7+
href={`https://github.com/GetStream/stream-chat-react/blob/${branch}/src/components${path}`}
8+
>
9+
{text}
10+
</a>
11+
);
12+
};
613

714
export default GHComponentLink;

docusaurus/docs/React/components/message-components/reactions.mdx

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ title: Reactions
66

77
import GHComponentLink from '../../_docusaurus-components/GHComponentLink';
88

9+
:::caution
10+
If you're moving from older versions to `11.0.0` then make sure to read ["New reactions" release guide](../../release-guides/new-reactions.mdx) to help you transition to the new implementation.
11+
:::
12+
913
The Stream Chat API provides built-in support for adding reactions to messages. The component library provides three default
1014
components to enable reaction selection and display:
1115

@@ -55,7 +59,7 @@ Be default, the `ReactionSelector` component provides the following reaction opt
5559
- `haha`
5660
- `wow`
5761
- `sad`
58-
- `angry`
62+
- `angry` - removed in `11.0.0`
5963

6064
The `defaultMinimalEmojis` data set that populates the default reaction options can be found in the
6165
[emojiData](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Channel/emojiData.ts) file in the
@@ -131,7 +135,7 @@ const CustomReactionsList = (props) => {
131135

132136
## ReactionSelector Props
133137

134-
### additionalEmojiProps
138+
### additionalEmojiProps (removed in `11.0.0`)
135139

136140
Additional props to be passed to the [NimbleEmoji](https://github.com/missive/emoji-mart/blob/master/src/components/emoji/nimble-emoji.js) component from `emoji-mart`.
137141

@@ -191,9 +195,10 @@ An object that keeps track of the count of each type of reaction on a message (o
191195

192196
A list of the currently supported reactions on a message.
193197

194-
| Type | Default |
195-
| ----- | --------------------------------------------------------------------------- |
196-
| array | <GHComponentLink text='defaultMinimalEmojis' path='/Channel/emojiData.ts'/> |
198+
| Version | Type | Default |
199+
| ------- | ----- | -------------------------------------------------------------------------------------------------------------- |
200+
| >=4.0.0 | array | <GHComponentLink text='defaultMinimalEmojis' path='/Channel/emojiData.ts'/> |
201+
| ^11.0.0 | array | <GHComponentLink text='defaultReactionOptions' branch="feat/reactions" path='/Reactions/reactionOptions.tsx'/> |
197202

198203
### reverse
199204

@@ -205,7 +210,7 @@ If true, adds a CSS class that reverses the horizontal positioning of the select
205210

206211
## ReactionsList Props
207212

208-
### additionalEmojiProps
213+
### additionalEmojiProps (removed in `11.0.0`)
209214

210215
Additional props to be passed to the [NimbleEmoji](https://github.com/missive/emoji-mart/blob/master/src/components/emoji/nimble-emoji.js) component from `emoji-mart`.
211216

@@ -241,9 +246,10 @@ An object that keeps track of the count of each type of reaction on a message (o
241246

242247
A list of the currently supported reactions on a message.
243248

244-
| Type | Default |
245-
| ----- | --------------------------------------------------------------------------- |
246-
| array | <GHComponentLink text='defaultMinimalEmojis' path='/Channel/emojiData.ts'/> |
249+
| Version | Type | Default |
250+
| ------- | ----- | -------------------------------------------------------------------------------------------------------------- |
251+
| >=4.0.0 | array | <GHComponentLink text='defaultMinimalEmojis' path='/Channel/emojiData.ts'/> |
252+
| ^11.0.0 | array | <GHComponentLink text='defaultReactionOptions' branch="feat/reactions" path='/Reactions/reactionOptions.tsx'/> |
247253

248254
### reactions
249255

@@ -263,7 +269,7 @@ If true, adds a CSS class that reverses the horizontal positioning of the select
263269

264270
## SimpleReactionsList Props
265271

266-
### additionalEmojiProps
272+
### additionalEmojiProps (removed in `11.0.0`)
267273

268274
Additional props to be passed to the [NimbleEmoji](https://github.com/missive/emoji-mart/blob/master/src/components/emoji/nimble-emoji.js) component from `emoji-mart`.
269275

@@ -299,9 +305,10 @@ An object that keeps track of the count of each type of reaction on a message (o
299305

300306
A list of the currently supported reactions on a message.
301307

302-
| Type | Default |
303-
| ----- | --------------------------------------------------------------------------- |
304-
| array | <GHComponentLink text='defaultMinimalEmojis' path='/Channel/emojiData.ts'/> |
308+
| Version | Type | Default |
309+
| ------- | ----- | -------------------------------------------------------------------------------------------------------------- |
310+
| >=4.0.0 | array | <GHComponentLink text='defaultMinimalEmojis' path='/Channel/emojiData.ts'/> |
311+
| ^11.0.0 | array | <GHComponentLink text='defaultReactionOptions' branch="feat/reactions" path='/Reactions/reactionOptions.tsx'/> |
305312

306313
### reactions
307314

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
---
2+
id: new-reactions
3+
sidebar_position: 2
4+
title: New reactions (11.0.0)
5+
keywords: [migration guide, upgrade, reactions, breaking changes, v11]
6+
---
7+
8+
import GHComponentLink from '../_docusaurus-components/GHComponentLink';
9+
10+
## Introducing new reactions (with breaking changes)
11+
12+
When it came to developer experience regarding customization of the reaction components our team noticed that our integrators generally strugled to make more advanced adjustments to reactions without having to rebuild the whole [component set](../components/message-components/reactions.mdx). The whole process has been quite unintuitive and that's why this update aims at making adjusting your reactions much easier.
13+
14+
### Main reasons for a revamp
15+
16+
- inability to reuse default (Stream supplied reactions) with your custom ones
17+
- strong reliance on [`EmojiMart`](https://github.com/missive/emoji-mart) and inability to use completely custom reactions out of the box
18+
- certain `additionalEmojiProps` did not work with Stream-supplied reactions
19+
20+
```tsx
21+
// not exported directly (hidden, leading to poor DX)
22+
import { defaultMinimalEmojis } from 'stream-chat-react/dist/components/Channel/emojiData';
23+
24+
export const customReactions = [
25+
{
26+
// relies on EmojiMart-supplied sprite sheet, "native" option does not work for Stream-supplied reactions
27+
// you'd need to look up supported id's in stream-emoji.json under "emojis" key
28+
id: 'bulb',
29+
},
30+
// unsupported
31+
{
32+
id: 'rick_roll',
33+
},
34+
// this wouldn't work
35+
...defaultMinimalEmojis,
36+
];
37+
```
38+
39+
## New default setup and how it works
40+
41+
SDK by default comes with five pre-defined reaction types (`haha`, `like`, `love`, `sad` and `wow`) which are newly rendered by <GHComponentLink text='StreamEmoji' branch="feat/reactions" path='/Reactions/StreamEmoji.tsx'/> component which utilises sprite sheet system and renders images for each reaction to make sure it works flawlessly on every system. Default reaction options are defined in <GHComponentLink text='defaultReactionOptions' branch="feat/reactions" path='/Reactions/reactionOptions.tsx'/> and these options are reused for both [`ReactionSelector`](../components/message-components/reactions.mdx) and [`ReactionsList`](../components/message-components/reactions.mdx) (as well as [`SimpleReactionsList`](../components/message-components/reactions.mdx)). These options come by default from the ComponentContext but local component property will be prioritised if defined. This is how it works under the hood:
42+
43+
```ts
44+
contextReactionOptions = defaultReactionOptions;
45+
// ...
46+
const reactionOptions = propsReactionOptions ?? contextReactionOptions;
47+
```
48+
49+
:::note
50+
Beware that sixth reaction type `angry` has been removed in this update, if you need to re-enable it, follow [this guide](#re-enabling-angry-reaction).
51+
:::
52+
53+
## Custom reaction types and components
54+
55+
It's possible to supply your own reaction types and components to represent such reactions - let's implement reaction of type `rick_roll` to render a Rick Roll GIF and define override for default type `love`:
56+
57+
```tsx
58+
import { Channel } from 'stream-chat-react';
59+
60+
const RickRollReaction = () => (
61+
<img src='https://media.tenor.com/x8v1oNUOmg4AAAAM/rickroll-roll.gif' style={{ height: 20 }} />
62+
);
63+
64+
const customReactionOptions = [
65+
{
66+
Component: RickRollReaction,
67+
type: 'rick_roll',
68+
name: 'Rick Roll',
69+
},
70+
{
71+
Component: () => <>❤️</>
72+
type: 'love',
73+
name: "Heart"
74+
}
75+
];
76+
```
77+
78+
And then you can pass these newly created options to [`Channel`](../components/core-components/channel) component which will be then propagated to `ReactionSelector` and `ReactionsList`:
79+
80+
```tsx
81+
<Channel reactionOptions={customReactionOptions}>{/*...*/}</Channel>
82+
```
83+
84+
## EmojiMart integration
85+
86+
If you're used to work with [EmojiMart emojis](https://github.com/missive/emoji-mart#-emoji-component) then integrating with new reaction system shouldn't be a big trouble as you can define how your components look and reach for context if you need to:
87+
88+
```tsx
89+
// arbitrary EmojiMartContext (does not come with the SDK)
90+
import { useEmojiMartContext } from '../contexts';
91+
92+
const CustomLikeComponent = () => {
93+
const { selectedSkinTones, selectedSet } = useEmojiMartContext();
94+
95+
// to use EmojiMart web components you'll need to go through initiation steps, see EmojiMart documentation
96+
return <em-emoji id='+1' set={selectedSet} skin={selectedSkinTones['+1']} />;
97+
};
98+
99+
const reactionOptions = [
100+
{
101+
type: 'like',
102+
component: CustomLikeComponent,
103+
name: 'EmojiMart like',
104+
},
105+
];
106+
107+
// pass reaction options to component context (Channel) or to ReactionSelector and ReactionsList
108+
```
109+
110+
## Use of different reaction components for the same reaction types for `ReactionSelector` and `ReactionsList` components
111+
112+
If you need more fine-grain tuning and want to - for example - enable only a certain subset of clickable reactions but want to display the full set then you'd do something like this:
113+
114+
```tsx
115+
const JoyReaction = () => <>😂</>;
116+
const CatReaction = () => <>🐈</>;
117+
const ThumbsUpReaction = () => <>👍</>;
118+
const SmileReaction = () => <>🙂</>;
119+
120+
// subset of clickable options available to the user
121+
const selectedReactionOptions = [
122+
{ type: 'haha', Component: JoyReaction },
123+
{ type: 'cat', Component: CatReaction },
124+
];
125+
126+
// set of all available options to be rendered
127+
const completeReactionOptions = [
128+
{ type: 'haha', Component: JoyReaction },
129+
{ type: 'cat', Component: CatReaction },
130+
{ type: '+1', Component: ThumbsUpReaction },
131+
{ type: 'smile', Component: SmileReaction },
132+
];
133+
```
134+
135+
Or if you just want bigger icons for `ReactionsList` while `ReactionSelector` uses regular:
136+
137+
```tsx
138+
// arbitrary import (does not come with the SDK)
139+
import { ReactionComponent } from './CustomReactions';
140+
141+
const selectorReactionOptions = [
142+
{
143+
type: 'like',
144+
component: ReactionComponent.Like,
145+
name: 'Like',
146+
},
147+
];
148+
149+
const listReactionOptions = [
150+
{
151+
type: 'like',
152+
// in this example it's just different size of the emoji
153+
component: ReactionComponent.LikeMedium,
154+
name: 'Like medium',
155+
},
156+
];
157+
```
158+
159+
You can then apply these new options to `ReactionSelector` and `ReactionsList` directly:
160+
161+
```tsx
162+
import { ReactionSelector, ReactionsList, Channel } from 'stream-chat-react';
163+
164+
// ReactionSelector component requires forwarded reference
165+
const CustomReactionSelector = forwardRef((props, ref) => (
166+
<ReactionSelector {...props} ref={ref} reactionOptions={selectorReactionOptions} />
167+
));
168+
169+
const CustomReactionsList = (props) => (
170+
<ReactionsList {...props} reactionOptions={listReactionOptions} />
171+
);
172+
```
173+
174+
And then pass them down to component context (`Channel`) component:
175+
176+
```tsx
177+
<Channel ReactionSelector={CustomReactionSelector} ReactionsList={CustomReactionsList}>
178+
{/*...*/}
179+
</Channel>
180+
```
181+
182+
## Use of `SpriteImage` component
183+
184+
:::note
185+
We suggest using individual images per reaction type as multiple smaller requests is more bandwidth-friendly. Use this component only if you have no other choice.
186+
:::
187+
188+
If you have a sprite sheet of emojis and there's no other way for you to implement your reactions, you can utilise <GHComponentLink text='SpriteImage' branch="feat/reactions" path='/Reactions/SpriteImage.tsx'/> utility component which comes with the SDK:
189+
190+
```tsx
191+
import { SpriteImage } from 'stream-chat-react';
192+
193+
const SPRITE_URL = 'https://getstream.imgix.net/images/emoji-sprite.png';
194+
195+
const reactionOptions = [
196+
{
197+
type: 'joy',
198+
component: () => (
199+
<SpriteImage columns={2} rows={3} spriteUrl={SPRITE_URL} position={[0, 1]} fallback='😂' />
200+
), // renders fallback initially and then image when it successfully loads
201+
name: 'ROFL',
202+
},
203+
];
204+
205+
// pass reaction options to component context (Channel) or to ReactionSelector and ReactionsList
206+
```
207+
208+
## Transition from previous version of custom reactions
209+
210+
### Default setup
211+
212+
The transition is super easy:
213+
214+
```tsx
215+
import { defaultReactionOptions } from 'stream-chat-react';
216+
217+
// old custom options
218+
const reactionOptions = [{ id: 'bulb' /* ...extra properties... */ }, { id: '+1' }, { id: 'joy' }];
219+
220+
// would newly become
221+
const newReactionOptions = [
222+
{ type: 'bulb', Component: () => <>💡</>, name: 'Bulb reaction' },
223+
{ type: '+1', Component: () => <>👍</> },
224+
{ type: 'joy', Component: () => <>🤣</>, name: 'ROFL' },
225+
// reuse default ones if you want to
226+
...defaultReactionOptions,
227+
];
228+
```
229+
230+
All of the extra options previously applied to `EmojiMart` emojis can now be directly applied to your custom components either manually or through your custom context. For more information see [EmojiMart integration](#emojimart-integration).
231+
232+
### Re-enabling `angry` reaction
233+
234+
For better compatibility with other SDKs we decided to consolidate default available types and remove `angry` type which was previously available only in the React SDK. Here's how you'd go about re-enabling it:
235+
236+
```tsx
237+
import { StreamEmoji, defaultReactionOptions } from 'stream-chat-react';
238+
239+
const reactionOptions = [
240+
...defaultReactionOptions,
241+
{ type: 'angry', Component: () => <StreamEmoji fallback='😠' type='angry' />, name: 'Angry' },
242+
];
243+
244+
// pass reaction options to component context (Channel) or to ReactionSelector and ReactionsList
245+
```

0 commit comments

Comments
 (0)