Skip to content

Commit

Permalink
docs(react-sdk): Reaction component (#721)
Browse files Browse the repository at this point in the history
  • Loading branch information
arnautov-anton authored Jun 28, 2023
1 parent afd22b7 commit 0a80c5e
Show file tree
Hide file tree
Showing 13 changed files with 109 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Participant sorting
title: Participant Sorting
description: Overview of the Sorting API used to sort call participants.
---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,67 @@ id: reaction
title: Reaction
---

:::warning
Reaction component is used to display emojis in real-time for a specified amount of time. You can utilise this functionality, for example, to notify other participants that you want to speak by "raising hand". Our default sorting algorithm will push participants with raised hand to the top of the list for better visibility. Learn more about reaction events and their customization in the [Reactions & Custom Events guide](../../../guides/reactions-and-custom-events) and see how sorting works in the [Participant Sorting guide](../../../guides/sorting-api).

TODO: write about https://github.com/GetStream/stream-video-js/blob/main/packages/react-sdk/src/components/Reaction/Reaction.tsx
The SDK comes with the `defaultEmojiReactionMap` which consists of three reactions:

:::
- `:like:` (renders 👍)
- `:raise-hand:` (renders ✋)
- `:fireworks:`: (renders 🎉)

You can extend `Reaction` component with your custom map if you need to through `emojiReactionMap` property.

![Reaction component preview](../../assets/03-ui-components/reaction.png)

## General usage

Our `DefaultParticipantViewUI` already comes with the `Reaction` component built in but if you're building your custom `ParticipantViewUI` here's how you'd incorporate the `Reaction` component into your UI:

```tsx
import {
Reaction,
useParticipantViewContext,
defaultEmojiReactionMap,
} from '@stream-io/video-react-sdk';

const customEmojiReactionMap = {
...defaultEmojiReactionMap,
':lol:': '😂',
};

export const CustomParticipantViewUI = () => {
const { participant } = useParticipantViewContext();
return (
<>
<Reaction
participant={participant}
hideAfterTimeoutInMs={5000}
emojiReactionMap={customEmojiReactionMap}
/>
{/* your other custom UI elements */}
</>
);
};
```

## Final steps

Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the [ParticipantView customizations guide](../../../ui-cookbook/participant-view-customizations).

## Props

### `participant`

| Type |
| --------------------------------------------------------------------------------------------------------------- |
| [`StreamVideoParticipant`](https://github.com/GetStream/stream-video-js/blob/main/packages/client/src/types.ts) |

The participant whose reaction the component should display.

### `hideAfterTimeoutInMs`

| Type |
| ----------------------- |
| `number` \| `undefined` |

Timeout in miliseconds after which the component resets [participant reaction state](../../../guides/reactions-and-custom-events/#clearing-reactions).
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ const ParticipantDetails = () => {

export const CustomParticipantViewUI = () => {
return (
<div>
<>
<ParticipantDetails />
{/* other UI components... */}
</div>
{/* your other custom UI elements */}
</>
);
};
```

## Final steps

Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the aforementioned [participant view customizations guide](../participant-view-customizations).
Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the aforementioned [ParticipantView customizations guide](../participant-view-customizations).

```tsx
import { useParticipants } from '@stream-io/video-react-sdk';
Expand All @@ -78,12 +78,12 @@ import { CustomParticipantViewUI } from '../ParticipantViewUI';
import { CustomVideoPlaceholder } from '../VideoPlaceholder';

export const CustomCallLayout = () => {
const otherParticipants = useParticipants();
const participants = useParticipants();

return (
<div>
{/* other UI components */}
{otherParticipants.map((participant) => (
{/* your other custom UI elements */}
{participants.map((participant) => (
<div key={participant.sessionId}>
<ParticipantView
participant={participant}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ We've mentioned that `VideoPlaceholder` component is rendered _over the video el

## Final steps

Now we can pass this custom `VideoPlaceholder` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the aforementioned [participant view customizations guide](../../ui-cookbook/participant-view-customizations).
Now we can pass this custom `VideoPlaceholder` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the aforementioned [ParticipantView customizations guide](../../ui-cookbook/participant-view-customizations).
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ const CustomParticipantViewUI = () => {
return (
<>
<ConnectionQualityIndicator />
{/* other UI components... */}
{/* your other custom UI elements */}
</>
);
};
```

## Final steps

Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the aforementioned [participant view customizations guide](../../ui-cookbook/participant-view-customizations).
Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the aforementioned [ParticipantView customizations guide](../../ui-cookbook/participant-view-customizations).
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,17 @@ const PoorConnectionNotification = () => {

export const CustomParticipantViewUI = () => {
return (
<div>
<>
<PoorConnectionNotification />
{/* other UI components... */}
</div>
{/* your other custom UI elements */}
</>
);
};
```

## Final steps

Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the [participant view customizations guide](../participant-view-customizations).
Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the [ParticipantView customizations guide](../participant-view-customizations).

```tsx
import { useParticipants } from '@stream-io/video-react-sdk';
Expand All @@ -52,7 +52,7 @@ export const CustomCallLayout = () => {

return (
<div>
{/* other UI components */}
{/* your other custom UI elements */}
{otherParticipants.map((participant) => (
<div key={participant.sessionId}>
<ParticipantView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,4 @@ const CustomParticipantViewUI = () => {

## Final steps

Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the [participant view customizations guide](../../ui-cookbook/participant-view-customizations).
Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the [ParticipantView customizations guide](../../ui-cookbook/participant-view-customizations).
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@ const CustomParticipantViewUI = () => {

## Final steps

Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the [participant view customizations guide](../../ui-cookbook/participant-view-customizations).
Now we can pass this custom `ParticipantViewUI` component down to our call layout components or directly to `ParticipantView` component in our custom call layout as described in the [ParticipantView customizations guide](../../ui-cookbook/participant-view-customizations).
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { OwnCapability, StreamReaction } from '@stream-io/video-client';
import { Restricted, useCall } from '@stream-io/video-react-bindings';

import { CompositeButton, IconButton } from '../Button';
import { defaultEmojiReactions } from '../Reaction';
import { defaultEmojiReactionMap } from '../Reaction';

export const defaultReactions: StreamReaction[] = [
{
Expand Down Expand Up @@ -66,7 +66,7 @@ export const DefaultReactionsMenu = ({
call?.sendReaction(reaction);
}}
>
{reaction.emoji_code && defaultEmojiReactions[reaction.emoji_code]}
{reaction.emoji_code && defaultEmojiReactionMap[reaction.emoji_code]}
</button>
))}
</div>
Expand Down
51 changes: 25 additions & 26 deletions packages/react-sdk/src/components/Reaction/Reaction.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,46 @@
import { useEffect, useState } from 'react';
import { Call, StreamReaction } from '@stream-io/video-client';
import clsx from 'clsx';
import { useEffect } from 'react';
import { StreamVideoParticipant } from '@stream-io/video-client';
import { useCall } from '@stream-io/video-react-bindings';

export type ReactionProps = {
reaction: StreamReaction;
sessionId: string;
call: Call;
participant: StreamVideoParticipant;
hideAfterTimeoutInMs?: number;
emojiReactionMap?: Record<string, string>;
};

export const defaultEmojiReactions: Record<string, string> = {
export const defaultEmojiReactionMap: Record<string, string> = {
':like:': '👍',
':raise-hand:': '✋',
':fireworks:': '🎉',
};

export const Reaction = (props: ReactionProps) => {
const { reaction, sessionId, call, hideAfterTimeoutInMs = 5500 } = props;
const [isShowing, setIsShowing] = useState(false);
export const Reaction = ({
participant: { reaction, sessionId },
hideAfterTimeoutInMs = 5500,
emojiReactionMap = defaultEmojiReactionMap,
}: ReactionProps) => {
const call = useCall();

useEffect(() => {
let timeoutId: NodeJS.Timeout;
if (reaction) {
setIsShowing(true);
timeoutId = setTimeout(() => {
setIsShowing(false);
call.resetReaction(sessionId);
}, hideAfterTimeoutInMs);
}
if (!call || !reaction) return;

const timeoutId = setTimeout(() => {
call.resetReaction(sessionId);
}, hideAfterTimeoutInMs);

return () => {
clearTimeout(timeoutId);
};
}, [call, hideAfterTimeoutInMs, reaction, sessionId]);

const { emoji_code } = reaction;
if (!reaction) return null;

const { emoji_code: emojiCode } = reaction;

return (
<div
className={clsx(
'str-video__reaction',
isShowing && 'str-video__reaction--visible',
)}
>
<div className="str-video__reaction">
<span className="str-video__reaction__emoji">
{emoji_code && defaultEmojiReactions[emoji_code]}
{emojiCode && emojiReactionMap[emojiCode]}
</span>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,9 @@ export const DefaultParticipantViewUI = ({
menuPlacement = 'bottom-end',
showMenuButton = true,
}: DefaultParticipantViewUIProps) => {
const call = useCall()!;
const { participant, participantViewElement, videoMode, videoElement } =
useParticipantViewContext();
const { reaction, sessionId, publishedTracks } = participant;
const { publishedTracks } = participant;

const hasScreenShare = publishedTracks.includes(
SfuModels.TrackType.SCREEN_SHARE,
Expand Down Expand Up @@ -104,9 +103,7 @@ export const DefaultParticipantViewUI = ({
/>
</MenuToggle>
)}
{reaction && (
<Reaction reaction={reaction} sessionId={sessionId} call={call} />
)}
<Reaction participant={participant} />
<ParticipantDetails indicatorsVisible={indicatorsVisible} />
</>
);
Expand Down
6 changes: 0 additions & 6 deletions packages/styling/src/Reaction/Reaction-layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@
position: absolute;
right: 0.875rem;
bottom: 0.875rem;
opacity: 0;
transition: opacity 0.2s ease-out;

&.str-video__reaction--visible {
opacity: 1;
}

.str-video__reaction__emoji {
display: flex;
Expand Down

0 comments on commit 0a80c5e

Please sign in to comment.