♻️(feat) extract pip options menu component

keep pip options layout reusable and isolated
This commit is contained in:
Cyril
2026-01-21 12:41:18 +01:00
parent 07e172041f
commit fa6967635d
2 changed files with 94 additions and 0 deletions
@@ -2,9 +2,49 @@ import { useTranslation } from 'react-i18next'
import { RiMoreFill } from '@remixicon/react'
import { Button, Menu } from '@/primitives'
import { OptionsMenuItems } from './OptionsMenuItems'
import { useOverlayPortalContainer } from '@/primitives/useOverlayPortalContainer'
import { useEffect, useRef, useState } from 'react'
import { PipOptionsMenu } from './PipOptionsMenu'
export const OptionsButton = () => {
const { t } = useTranslation('rooms')
const portalContainer = useOverlayPortalContainer()
const isInPiP =
portalContainer && portalContainer.ownerDocument !== document
const [isOpen, setIsOpen] = useState(false)
const wrapperRef = useRef<HTMLDivElement>(null)
useEffect(() => {
if (!isOpen || !isInPiP) return
const doc = wrapperRef.current?.ownerDocument ?? document
const handlePointerDown = (event: PointerEvent) => {
const target = event.target as Node | null
const wrapper = wrapperRef.current
if (!wrapper || !target) return
if (!wrapper.contains(target)) {
setIsOpen(false)
}
}
doc.addEventListener('pointerdown', handlePointerDown, true)
return () => {
doc.removeEventListener('pointerdown', handlePointerDown, true)
}
}, [isInPiP, isOpen])
if (isInPiP) {
return (
<PipOptionsMenu
wrapperRef={wrapperRef}
isOpen={isOpen}
setIsOpen={setIsOpen}
label={t('options.buttonLabel')}
/>
)
}
return (
<Menu variant="dark">
@@ -0,0 +1,54 @@
import React from 'react'
import { RiMoreFill } from '@remixicon/react'
import { Box, Button } from '@/primitives'
import { css } from '@/styled-system/css'
import { OptionsMenuItems } from './OptionsMenuItems'
type PipOptionsMenuProps = {
wrapperRef: React.RefObject<HTMLDivElement>
isOpen: boolean
setIsOpen: (isOpen: boolean) => void
label: string
}
export const PipOptionsMenu = ({
wrapperRef,
isOpen,
setIsOpen,
label,
}: PipOptionsMenuProps) => {
return (
<div
ref={wrapperRef}
className={css({
position: 'relative',
})}
>
<Button
id="room-options-trigger"
square
variant="primaryDark"
aria-label={label}
tooltip={label}
onPress={() => setIsOpen(!isOpen)}
>
<RiMoreFill />
</Button>
{isOpen && (
<div
className={css({
position: 'absolute',
left: '50%',
bottom: 'calc(100% + 0.85rem)',
transform: 'translateX(-50%)',
zIndex: 10,
})}
>
<Box size="sm" type="popover" variant="dark">
<OptionsMenuItems />
</Box>
</div>
)}
</div>
)
}