From 38ab001bcf1b15fdd5b9f5906bfa95bfb31b8aab Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Wed, 26 Feb 2025 16:31:21 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BF=EF=B8=8F(frontend)=20allow=20the=20re?= =?UTF-8?q?action=20toolbar=20to=20be=20accessible=20by=20keyboard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix an accessibility issue. Reaction wasn't accessible using keyboard. This fix is imperfect, the animation doesn't perflectly replicate the menu one. --- .../components/controls/ReactionsToggle.tsx | 145 ++++++++++++++---- 1 file changed, 119 insertions(+), 26 deletions(-) diff --git a/src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx b/src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx index cb6669d6..90097fab 100644 --- a/src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx +++ b/src/frontend/src/features/rooms/livekit/components/controls/ReactionsToggle.tsx @@ -1,9 +1,9 @@ import { useTranslation } from 'react-i18next' import { RiEmotionLine } from '@remixicon/react' -import { useState, useRef } from 'react' +import { useState, useRef, useEffect } from 'react' import { css } from '@/styled-system/css' import { useRoomContext } from '@livekit/components-react' -import { Menu, ToggleButton, Button } from '@/primitives' +import { ToggleButton, Button } from '@/primitives' import { NotificationType } from '@/features/notifications/NotificationType' import { NotificationPayload } from '@/features/notifications/NotificationPayload' import { @@ -27,6 +27,8 @@ export const ReactionsToggle = () => { const instanceIdRef = useRef(0) const room = useRoomContext() + const [isVisible, setIsVisible] = useState(false) + const sendReaction = async (emoji: string) => { const encoder = new TextEncoder() const payload: NotificationPayload = { @@ -53,42 +55,133 @@ export const ReactionsToggle = () => { }, ANIMATION_DURATION) } + // Custom animation implementation for the emoji toolbar + // Could not use a menu and its animation, because a menu would make the toolbar inaccessible by keyboard + // animation isn't perfect + const [isRendered, setIsRendered] = useState(isVisible) + const [opacity, setOpacity] = useState(isVisible ? 1 : 0) + + useEffect(() => { + if (isVisible) { + // Show: first render, then animate in + setIsRendered(true) + // Need to delay setting opacity to ensure CSS transition works + // (using requestAnimationFrame to ensure DOM has updated) + requestAnimationFrame(() => { + requestAnimationFrame(() => { + setOpacity(1) + }) + }) + } else if (isRendered) { + // Hide: first animate out, then unrender + setOpacity(0) + + // Wait for animation to complete before removing from DOM + const timer = setTimeout(() => { + setIsRendered(false) + }, 200) // Match this to your animation duration + return () => clearTimeout(timer) + } + }, [isVisible, isRendered]) + return ( <> - +
setIsVisible(!isVisible)} > - - {EMOJIS.map((emoji, index) => ( - - ))} - -
+ {EMOJIS.map((emoji, index) => ( + + ))} + + + )} + + ) } + +// export const ReactionsToolBar = () => { +// const { t } = useTranslation('rooms', { keyPrefix: 'controls.reactions' }) +// +// const [reactions, setReactions] = useState([]) +// const instanceIdRef = useRef(0) +// const room = useRoomContext() +// +// const sendReaction = async (emoji: string) => { +// const encoder = new TextEncoder() +// const payload: NotificationPayload = { +// type: NotificationType.ReactionReceived, +// data: { +// emoji: emoji, +// }, +// } +// const data = encoder.encode(JSON.stringify(payload)) +// await room.localParticipant.publishData(data, { reliable: true }) +// +// const newReaction = { +// id: instanceIdRef.current++, +// emoji, +// participant: room.localParticipant, +// } +// setReactions((prev) => [...prev, newReaction]) +// +// // Remove this reaction after animation +// setTimeout(() => { +// setReactions((prev) => +// prev.filter((instance) => instance.id !== newReaction.id) +// ) +// }, ANIMATION_DURATION) +// } +// +// return <> +// }