From ecf5d443d633596e60edc78dca35cf1f381d4293 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Mon, 18 May 2026 15:23:36 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(frontend)=20refactor=20strip?= =?UTF-8?q?=20components=20and=20improve=20naming=20clarity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename strip-related components into a more generic container abstraction. Extract the buttons container into a dedicated component file and update related naming to improve readability and maintainability. --- .../toolbar/ReactionButtonsContainer.tsx | 71 +++++++++++++++++++ .../components/toolbar/ReactionsToolbar.tsx | 70 +----------------- 2 files changed, 74 insertions(+), 67 deletions(-) create mode 100644 src/frontend/src/features/reactions/components/toolbar/ReactionButtonsContainer.tsx diff --git a/src/frontend/src/features/reactions/components/toolbar/ReactionButtonsContainer.tsx b/src/frontend/src/features/reactions/components/toolbar/ReactionButtonsContainer.tsx new file mode 100644 index 00000000..9a1897c0 --- /dev/null +++ b/src/frontend/src/features/reactions/components/toolbar/ReactionButtonsContainer.tsx @@ -0,0 +1,71 @@ +import { useEffect, useRef, useState } from 'react' +import { styled } from '@/styled-system/jsx' +import { useReactionsToolbar } from '../../hooks/useReactionsToolbar' +import { useIsMobile } from '@/utils/useIsMobile' + +const StyledContainer = styled('div', { + base: { + display: 'flex', + gap: '0.2rem', + borderRadius: '21px', + padding: '0.15rem', + backgroundColor: 'primaryDark.100', + opacity: 0, + transform: 'translateY(3.25rem)', + transition: 'opacity, transform', + transitionDuration: '0.5s', + transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)', + pointerEvents: 'none', + }, + variants: { + isVisible: { + true: { + opacity: 1, + transform: 'translateY(0)', + pointerEvents: 'auto', + }, + }, + desktopOffset: { + true: { + // Ideally this value should be calculated dynamically in JavaScript to keep + // the reaction toolbar perfectly centered relative to the reaction toggle. + // However, for simplicity and to follow a pragmatic 80/20 approach, + // this value is currently hardcoded in CSS. + marginRight: '30px', + }, + }, + }, +}) + +export const ReactionButtonsContainer = ({ + children, +}: { + children: React.ReactNode +}) => { + const { isOpen } = useReactionsToolbar() + const isMobile = useIsMobile() + const ref = useRef(null) + + const [isVisible, setIsVisible] = useState(false) + + useEffect(() => { + if (isOpen) { + // defer one frame so the browser paints opacity:0 first + const id = requestAnimationFrame(() => setIsVisible(true)) + return () => cancelAnimationFrame(id) + } else { + setIsVisible(false) + } + }, [isOpen]) + + return ( + + {children} + + ) +} diff --git a/src/frontend/src/features/reactions/components/toolbar/ReactionsToolbar.tsx b/src/frontend/src/features/reactions/components/toolbar/ReactionsToolbar.tsx index 5cc3f7fb..23e23dbc 100644 --- a/src/frontend/src/features/reactions/components/toolbar/ReactionsToolbar.tsx +++ b/src/frontend/src/features/reactions/components/toolbar/ReactionsToolbar.tsx @@ -3,10 +3,9 @@ import { useReactionsToolbar } from '../../hooks/useReactionsToolbar' import { ReactionButton } from './ReactionButton' import { Emoji } from '../../types' import { styled } from '@/styled-system/jsx' -import { useIsMobile } from '@/utils/useIsMobile' -import { useEffect, useRef, useState } from 'react' import { useDelayUnmount } from '@/hooks/useDelayUnmount' import { ReactionsKeyboardNavigation } from './ReactionsKeyboardNavigation' +import { ReactionButtonsContainer } from './ReactionButtonsContainer' const Container = styled('div', { base: { @@ -20,69 +19,6 @@ const Container = styled('div', { }, }) -const StyledStrip = styled('div', { - base: { - display: 'flex', - gap: '0.2rem', - borderRadius: '21px', - padding: '0.15rem', - backgroundColor: 'primaryDark.100', - opacity: 0, - transform: 'translateY(3.25rem)', - transition: 'opacity, transform', - transitionDuration: '0.5s', - transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)', - pointerEvents: 'none', - }, - variants: { - isVisible: { - true: { - opacity: 1, - transform: 'translateY(0)', - pointerEvents: 'auto', - }, - }, - desktopOffset: { - true: { - // Ideally this value should be calculated dynamically in JavaScript to keep - // the reaction toolbar perfectly centered relative to the reaction toggle. - // However, for simplicity and to follow a pragmatic 80/20 approach, - // this value is currently hardcoded in CSS. - marginRight: '30px', - }, - }, - }, -}) - -const Strip = ({ children }: { children: React.ReactNode }) => { - const { isOpen } = useReactionsToolbar() - const isMobile = useIsMobile() - const ref = useRef(null) - - const [isVisible, setIsVisible] = useState(false) - - useEffect(() => { - if (isOpen) { - // defer one frame so the browser paints opacity:0 first - const id = requestAnimationFrame(() => setIsVisible(true)) - return () => cancelAnimationFrame(id) - } else { - setIsVisible(false) - } - }, [isOpen]) - - return ( - - {children} - - ) -} - export const ReactionsToolbar = () => { const { isOpen } = useReactionsToolbar() const shouldMount = useDelayUnmount(isOpen, 300) @@ -94,11 +30,11 @@ export const ReactionsToolbar = () => { {/* eslint-disable-next-line jsx-a11y/no-autofocus*/} - + {Object.values(Emoji).map((emoji) => ( ))} - +