📝(docs) add pip component documentation

add jsdoc comments to pip components and hooks
This commit is contained in:
Cyril
2026-01-21 13:12:18 +01:00
parent 3e3d9f31a5
commit 09bb4daebc
7 changed files with 37 additions and 9 deletions
@@ -29,6 +29,12 @@ const copyStyles = (source: Document, target: Document) => {
}) })
} }
/**
* React Portal that renders children into a Document Picture-in-Picture window.
* Handles PiP window lifecycle, style injection, React root management, and uses UNSAFE_PortalProvider
* to ensure React Aria overlays render correctly within the PiP window.
* Creates a fresh React root on reopen to prevent black screen issues.
*/
export const DocumentPiPPortal = ({ export const DocumentPiPPortal = ({
isOpen, isOpen,
width, width,
@@ -9,7 +9,10 @@ import { HandToggle } from './controls/HandToggle'
import { OptionsButton } from './controls/Options/OptionsButton' import { OptionsButton } from './controls/Options/OptionsButton'
import { StartMediaButton } from './controls/StartMediaButton' import { StartMediaButton } from './controls/StartMediaButton'
// Compact PiP toolbar; keep all PiP-specific controls in one place. /**
* Compact control bar for the Picture-in-Picture window.
* Centralizes all PiP controls (devices, reactions, screen share, options, etc.) in one reusable component.
*/
export const PipControlBar = ({ export const PipControlBar = ({
showScreenShare, showScreenShare,
}: { }: {
@@ -23,7 +23,11 @@ const pickTrackForPip = (
return tracks[0] return tracks[0]
} }
// Renders the PiP viewport and a compact control bar inside the PiP window. /**
* Main view component for the Picture-in-Picture window.
* Handles track selection (prioritizes screen share), layout switching (grid for multiple participants),
* and renders the control bar and side panel within the PiP window.
*/
export const PipView = () => { export const PipView = () => {
const tracks = useTracks( const tracks = useTracks(
[ [
@@ -2,6 +2,10 @@ import { DocumentPiPPortal } from './DocumentPiPPortal'
import { PipView } from './PipView' import { PipView } from './PipView'
import { useRoomPiP } from '../hooks/useRoomPiP' import { useRoomPiP } from '../hooks/useRoomPiP'
/**
* Wrapper that mounts the PiP UI when room-level PiP state is enabled.
* Bridges RoomPiPProvider state with DocumentPiPPortal and PipView rendering.
*/
export const RoomPiP = () => { export const RoomPiP = () => {
const { isOpen, close } = useRoomPiP() const { isOpen, close } = useRoomPiP()
@@ -11,14 +11,17 @@ type PipOptionsMenuProps = {
label: string label: string
} }
// PiP-specific options menu positioned locally above the trigger button. /**
* PiP-specific options menu with absolute positioning for correct alignment in PiP window.
* Renders locally (unlike standard Menu) and closes automatically on item click or outside click.
*/
export const PipOptionsMenu = ({ export const PipOptionsMenu = ({
wrapperRef, wrapperRef,
isOpen, isOpen,
setIsOpen, setIsOpen,
label, label,
}: PipOptionsMenuProps) => { }: PipOptionsMenuProps) => {
// Close menu when a menu item action completes (e.g., transcription, effects). // Close menu when a menu item action completes (e.g., transcription, effects, recording).
useEffect(() => { useEffect(() => {
if (!isOpen) return if (!isOpen) return
const doc = wrapperRef.current?.ownerDocument ?? document const doc = wrapperRef.current?.ownerDocument ?? document
@@ -1,6 +1,11 @@
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import { RoomPiPContext } from './roomPiPContext' import { RoomPiPContext } from './roomPiPContext'
/**
* Context Provider that manages Picture-in-Picture state at the room level.
* Handles open/closed state, browser support detection, and exposes open/close/toggle functions.
* Components access PiP state via the useRoomPiP hook.
*/
export const RoomPiPProvider = ({ export const RoomPiPProvider = ({
children, children,
}: { }: {
@@ -1,20 +1,23 @@
import { useMemo } from 'react' import { useMemo } from 'react'
import { useUNSAFE_PortalContext } from '@react-aria/overlays' import { useUNSAFE_PortalContext } from '@react-aria/overlays'
/**
* Hook to retrieve the portal container for overlays (menus, tooltips, popovers).
* Returns the container from UNSAFE_PortalProvider context (pip-root in PiP, undefined in main window).
*/
export const useOverlayPortalContainer = () => { export const useOverlayPortalContainer = () => {
const { getContainer } = useUNSAFE_PortalContext() const { getContainer } = useUNSAFE_PortalContext()
// Read the portal container provided by UNSAFE_PortalProvider.
// This is how overlays know which document/window they should render into.
// "UNSAFE" means we're overriding the library default container on purpose.
return useMemo(() => getContainer?.() ?? undefined, [getContainer]) return useMemo(() => getContainer?.() ?? undefined, [getContainer])
} }
/**
* Hook to retrieve the boundary element for overlay positioning.
* Returns the portal container in PiP (for PiP-relative positioning), undefined in main window.
*/
export const useOverlayBoundaryElement = () => { export const useOverlayBoundaryElement = () => {
const portalContainer = useOverlayPortalContainer() const portalContainer = useOverlayPortalContainer()
return useMemo(() => { return useMemo(() => {
// Use the portal container as the positioning boundary.
// In PiP this keeps overlays positioned relative to the PiP window.
if (portalContainer) return portalContainer if (portalContainer) return portalContainer
return undefined return undefined
}, [portalContainer]) }, [portalContainer])