(feat) connect PiP to room and options menu

wire room-level PiP state to the options menu
This commit is contained in:
Cyril
2026-01-22 11:29:26 +01:00
parent e49355985a
commit 94488f31cf
16 changed files with 14 additions and 32 deletions
@@ -153,4 +153,3 @@ export const DocumentPiPPortal = ({
return portal
}
@@ -71,4 +71,3 @@ const PipControlsRight = styled('div', {
right: '1.35rem',
},
})
@@ -107,4 +107,3 @@ const PipGridWrapper = styled('div', {
height: '100%',
},
})
@@ -15,4 +15,3 @@ export const RoomPiP = () => {
</DocumentPiPPortal>
)
}
@@ -9,8 +9,7 @@ import { PipOptionsMenu } from './PipOptionsMenu'
export const OptionsButton = () => {
const { t } = useTranslation('rooms')
const portalContainer = useOverlayPortalContainer()
const isInPiP =
portalContainer && portalContainer.ownerDocument !== document
const isInPiP = portalContainer && portalContainer.ownerDocument !== document
const [isOpen, setIsOpen] = useState(false)
const wrapperRef = useRef<HTMLDivElement>(null)
@@ -33,8 +32,6 @@ export const OptionsButton = () => {
}
}, [isInPiP, isOpen])
if (isInPiP) {
return (
<PipOptionsMenu
@@ -21,4 +21,3 @@ export const PictureInPictureMenuItem = () => {
</MenuItem>
)
}
@@ -30,10 +30,10 @@ export const PipOptionsMenu = ({
const target = event.target as HTMLElement | null
const wrapper = wrapperRef.current
if (!wrapper || !target) return
// Don't close if clicking the trigger button
if (wrapper.querySelector('button')?.contains(target)) return
// Close if clicking a menu item (action will have fired)
if (target.closest('[role="menuitem"]')) {
// Use requestAnimationFrame to ensure action completes first, without visible delay
@@ -83,4 +83,4 @@ export const PipOptionsMenu = ({
)}
</div>
)
}
}
@@ -64,4 +64,3 @@ export const PipLateralMenu = () => {
</DialogTrigger>
)
}
@@ -19,10 +19,7 @@ export const RoomPiPProvider = ({
const open = useCallback(() => setIsOpen(true), [])
const close = useCallback(() => setIsOpen(false), [])
const toggle = useCallback(
() => setIsOpen((current) => !current),
[]
)
const toggle = useCallback(() => setIsOpen((current) => !current), [])
const value = useMemo(
() => ({
@@ -36,9 +33,6 @@ export const RoomPiPProvider = ({
)
return (
<RoomPiPContext.Provider value={value}>
{children}
</RoomPiPContext.Provider>
<RoomPiPContext.Provider value={value}>{children}</RoomPiPContext.Provider>
)
}
@@ -9,4 +9,3 @@ export type RoomPiPContextValue = {
}
export const RoomPiPContext = createContext<RoomPiPContextValue | null>(null)
@@ -1,7 +1,10 @@
import { useCallback, useEffect, useMemo, useState } from 'react'
type DocumentPictureInPicture = {
requestWindow: (options?: { width?: number; height?: number }) => Promise<Window>
requestWindow: (options?: {
width?: number
height?: number
}) => Promise<Window>
}
type WindowWithDocumentPiP = Window & {
@@ -67,4 +70,3 @@ export const useDocumentPiP = ({
closePiP,
}
}
@@ -8,4 +8,3 @@ export const useRoomPiP = () => {
}
return context
}
+1 -1
View File
@@ -24,7 +24,7 @@ export const Menu = ({
const [trigger, menu] = children
const boundaryElement = useOverlayBoundaryElement()
const portalContainer = useOverlayPortalContainer()
// Detect if we're in PiP: portal container is in a different document than the main window
const isInPiP = useMemo(
() =>
@@ -134,10 +134,7 @@ const Tooltip = ({
children: ReactNode
} & Partial<Omit<TooltipProps, 'children'>>) => {
return (
<StyledTooltip
arrowBoundaryOffset={arrowBoundaryOffset ?? 0}
{...props}
>
<StyledTooltip arrowBoundaryOffset={arrowBoundaryOffset ?? 0} {...props}>
<TooltipArrow />
{children}
</StyledTooltip>
@@ -82,7 +82,8 @@ export const VisualOnlyTooltip = ({
>
{wrappedChild}
</div>
{tooltipData && portalContainer &&
{tooltipData &&
portalContainer &&
createPortal(
<div
aria-hidden="true"
@@ -22,4 +22,3 @@ export const useOverlayBoundaryElement = () => {
return undefined
}, [portalContainer])
}