From 0a80c5e1944f9dff6d330d83f9009070d8c8a8d7 Mon Sep 17 00:00:00 2001 From: Anton Arnautov <43254280+arnautov-anton@users.noreply.github.com> Date: Wed, 28 Jun 2023 17:24:45 +0200 Subject: [PATCH] docs(react-sdk): Reaction component (#721) --- .../docs/React/02-guides/10-sorting-api.mdx | 2 +- .../03-ui-components/utility/reaction.mdx | 65 +++++++++++++++++- .../React/06-ui-cookbook/03-custom-label.mdx | 14 ++-- .../06-ui-cookbook/07-video-placeholder.mdx | 2 +- .../10-connection-quality-indicator.mdx | 4 +- .../06-ui-cookbook/12-connection-unstable.mdx | 10 +-- .../React/10-advanced/10-fullscreen-mode.mdx | 2 +- .../10-advanced/12-picture-in-picture.mdx | 2 +- .../assets/03-ui-components/reaction.png | Bin 0 -> 37089 bytes .../CallControls/ReactionsButton.tsx | 4 +- .../src/components/Reaction/Reaction.tsx | 51 +++++++------- .../DefaultParticipantViewUI.tsx | 7 +- .../styling/src/Reaction/Reaction-layout.scss | 6 -- 13 files changed, 109 insertions(+), 60 deletions(-) create mode 100644 packages/react-sdk/docusaurus/docs/React/assets/03-ui-components/reaction.png diff --git a/packages/react-sdk/docusaurus/docs/React/02-guides/10-sorting-api.mdx b/packages/react-sdk/docusaurus/docs/React/02-guides/10-sorting-api.mdx index 86532a8a3d..bf51a1232c 100644 --- a/packages/react-sdk/docusaurus/docs/React/02-guides/10-sorting-api.mdx +++ b/packages/react-sdk/docusaurus/docs/React/02-guides/10-sorting-api.mdx @@ -1,5 +1,5 @@ --- -title: Participant sorting +title: Participant Sorting description: Overview of the Sorting API used to sort call participants. --- diff --git a/packages/react-sdk/docusaurus/docs/React/03-ui-components/utility/reaction.mdx b/packages/react-sdk/docusaurus/docs/React/03-ui-components/utility/reaction.mdx index f47f7992ed..cfe9436326 100644 --- a/packages/react-sdk/docusaurus/docs/React/03-ui-components/utility/reaction.mdx +++ b/packages/react-sdk/docusaurus/docs/React/03-ui-components/utility/reaction.mdx @@ -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 ( + <> + + {/* 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). diff --git a/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/03-custom-label.mdx b/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/03-custom-label.mdx index dfeb5c20db..2b7a9b0861 100644 --- a/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/03-custom-label.mdx +++ b/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/03-custom-label.mdx @@ -59,17 +59,17 @@ const ParticipantDetails = () => { export const CustomParticipantViewUI = () => { return ( -
+ <> - {/* 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](../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'; @@ -78,12 +78,12 @@ import { CustomParticipantViewUI } from '../ParticipantViewUI'; import { CustomVideoPlaceholder } from '../VideoPlaceholder'; export const CustomCallLayout = () => { - const otherParticipants = useParticipants(); + const participants = useParticipants(); return (
- {/* other UI components */} - {otherParticipants.map((participant) => ( + {/* your other custom UI elements */} + {participants.map((participant) => (
{ return ( <> - {/* other UI components... */} + {/* your other custom UI elements */} ); }; @@ -64,4 +64,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 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). diff --git a/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/12-connection-unstable.mdx b/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/12-connection-unstable.mdx index ffc1a27af2..8a910b85de 100644 --- a/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/12-connection-unstable.mdx +++ b/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/12-connection-unstable.mdx @@ -29,17 +29,17 @@ const PoorConnectionNotification = () => { export const CustomParticipantViewUI = () => { return ( -
+ <> - {/* 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 [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'; @@ -52,7 +52,7 @@ export const CustomCallLayout = () => { return (
- {/* other UI components */} + {/* your other custom UI elements */} {otherParticipants.map((participant) => (
{ ## 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). diff --git a/packages/react-sdk/docusaurus/docs/React/10-advanced/12-picture-in-picture.mdx b/packages/react-sdk/docusaurus/docs/React/10-advanced/12-picture-in-picture.mdx index a10bddedc4..d19f5903cc 100644 --- a/packages/react-sdk/docusaurus/docs/React/10-advanced/12-picture-in-picture.mdx +++ b/packages/react-sdk/docusaurus/docs/React/10-advanced/12-picture-in-picture.mdx @@ -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). diff --git a/packages/react-sdk/docusaurus/docs/React/assets/03-ui-components/reaction.png b/packages/react-sdk/docusaurus/docs/React/assets/03-ui-components/reaction.png new file mode 100644 index 0000000000000000000000000000000000000000..faf9217a04d6d2113b4cf0abe7cea62cbf56e053 GIT binary patch literal 37089 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

+9*)R~rO7*qQgc%p*pdlZWMcMhK?=tTsC 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 literal 0 HcmV?d00001 diff --git a/packages/react-sdk/src/components/CallControls/ReactionsButton.tsx b/packages/react-sdk/src/components/CallControls/ReactionsButton.tsx index 76cc78da4c..5c74a59a80 100644 --- a/packages/react-sdk/src/components/CallControls/ReactionsButton.tsx +++ b/packages/react-sdk/src/components/CallControls/ReactionsButton.tsx @@ -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[] = [ { @@ -66,7 +66,7 @@ export const DefaultReactionsMenu = ({ call?.sendReaction(reaction); }} > - {reaction.emoji_code && defaultEmojiReactions[reaction.emoji_code]} + {reaction.emoji_code && defaultEmojiReactionMap[reaction.emoji_code]} ))}

diff --git a/packages/react-sdk/src/components/Reaction/Reaction.tsx b/packages/react-sdk/src/components/Reaction/Reaction.tsx index b39a3235e0..98362f9fa8 100644 --- a/packages/react-sdk/src/components/Reaction/Reaction.tsx +++ b/packages/react-sdk/src/components/Reaction/Reaction.tsx @@ -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; }; -export const defaultEmojiReactions: Record = { +export const defaultEmojiReactionMap: Record = { ':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 ( -
+
- {emoji_code && defaultEmojiReactions[emoji_code]} + {emojiCode && emojiReactionMap[emojiCode]}
); diff --git a/packages/react-sdk/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx b/packages/react-sdk/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx index e5cb149d43..858c8dd005 100644 --- a/packages/react-sdk/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx +++ b/packages/react-sdk/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx @@ -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, @@ -104,9 +103,7 @@ export const DefaultParticipantViewUI = ({ /> )} - {reaction && ( - - )} + ); diff --git a/packages/styling/src/Reaction/Reaction-layout.scss b/packages/styling/src/Reaction/Reaction-layout.scss index fd1cf29f86..a7772a96ed 100644 --- a/packages/styling/src/Reaction/Reaction-layout.scss +++ b/packages/styling/src/Reaction/Reaction-layout.scss @@ -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;