From 1771527c2d4c3fc05c319198e795cc0896c004b5 Mon Sep 17 00:00:00 2001 From: Cyril Date: Thu, 22 Jan 2026 11:15:05 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=84(style)=20align=20pip=20layout=20wi?= =?UTF-8?q?th=20room=20styling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit match pip background and spacing to --- CHANGELOG.md | 2 ++ .../livekit/components/DocumentPiPPortal.tsx | 30 +++++++++++++++++++ .../livekit/components/PipControlBar.tsx | 4 +-- .../rooms/livekit/components/PipView.tsx | 20 +++++++++++-- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a10c6c3..259b465a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -235,6 +235,8 @@ and this project adheres to - ✨(backend) monitor throttling rate failure through sentry #964 - 🚀(paas) add PaaS deployment scripts, tested on Scalingo #957 +- ✨(feat) Introduce Picture-in-Picture (PiP) #890 + ### Changed diff --git a/src/frontend/src/features/rooms/livekit/components/DocumentPiPPortal.tsx b/src/frontend/src/features/rooms/livekit/components/DocumentPiPPortal.tsx index 5fe98598..043644c8 100644 --- a/src/frontend/src/features/rooms/livekit/components/DocumentPiPPortal.tsx +++ b/src/frontend/src/features/rooms/livekit/components/DocumentPiPPortal.tsx @@ -29,6 +29,34 @@ const copyStyles = (source: Document, target: Document) => { }) } +const syncThemeAttribute = (source: Document, target: Document) => { + const theme = source.documentElement.getAttribute('data-lk-theme') + if (theme) { + target.documentElement.setAttribute('data-lk-theme', theme) + } +} + +const syncCssVariables = (source: Document, target: Document) => { + const sourceView = source.defaultView + if (!sourceView) return + + const applyVarsFrom = (element: HTMLElement | null) => { + if (!element) return + const styles = sourceView.getComputedStyle(element) + for (let i = 0; i < styles.length; i += 1) { + const property = styles[i] + if (!property.startsWith('--')) continue + const value = styles.getPropertyValue(property) + if (value) { + target.documentElement.style.setProperty(property, value) + } + } + } + + applyVarsFrom(source.documentElement) + applyVarsFrom(source.body) +} + /** * 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 @@ -71,6 +99,8 @@ export const DocumentPiPPortal = ({ const doc = win.document ensureBaseStyles(doc) copyStyles(document, doc) + syncThemeAttribute(document, doc) + syncCssVariables(document, doc) const existingContainer = containerRef.current if (!existingContainer || existingContainer.ownerDocument !== doc) { const nextContainer = doc.createElement('div') diff --git a/src/frontend/src/features/rooms/livekit/components/PipControlBar.tsx b/src/frontend/src/features/rooms/livekit/components/PipControlBar.tsx index 427e59fe..d57dbb56 100644 --- a/src/frontend/src/features/rooms/livekit/components/PipControlBar.tsx +++ b/src/frontend/src/features/rooms/livekit/components/PipControlBar.tsx @@ -45,9 +45,7 @@ const PipControls = styled('div', { alignItems: 'center', gap: '0.5rem', padding: '0.5rem 0.75rem', - backgroundColor: 'var(--lk-controlbar-bg)', - borderTop: '1px solid', - borderColor: 'var(--lk-control-border-color)', + backgroundColor: 'primaryDark.50', width: '100%', position: 'relative', }, diff --git a/src/frontend/src/features/rooms/livekit/components/PipView.tsx b/src/frontend/src/features/rooms/livekit/components/PipView.tsx index db67d607..e19cf3c8 100644 --- a/src/frontend/src/features/rooms/livekit/components/PipView.tsx +++ b/src/frontend/src/features/rooms/livekit/components/PipView.tsx @@ -48,9 +48,11 @@ export const PipView = () => { {/* Keep stage height stable to avoid layout shifting on track changes. */} {hasMultipleTiles ? ( - - - + + + + + ) : ( )} @@ -94,3 +96,15 @@ const PipStage = styled('div', { }, }) +const PipGridWrapper = styled('div', { + base: { + position: 'relative', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + width: '100%', + height: '100%', + }, +}) +