Mounting a React component in a picture in picture window

Deepak Mondal
2 min readAug 19, 2023

--

Google has introduced the documentPictureInPicture API in chrome 116.

In this article we explore how to mount a simple react component in the picture in picture window without the need to first mount it on our main application.

Step 1 — Set up component structure

We make two components. MainComponent.js and Counter.js. In MainComponent.js we set up a simple button that will open up the Counter.js component in the PIP window.

MainComponent.js

import React from "react";

const MainComponent = () => {
async function openPictureInPicture() {
//
}

return (
<div>
<div onClick={openPictureInPicture}>Open counter</div>
</div>
);
};

export default MainComponent;

Counter.js

import React, { useState, useEffect } from "react";
const Counter = () => {
const [count, setCount] = useState(0);

useEffect(() => {
setCount(1);
}, []);

const addNumber = () => {
setCount((prevCount) => prevCount + 1);
};
const subtractNumber = () => {
setCount((prevCount) => prevCount - 1);
};

try {
return (
<div>
<div onClick={subtractNumber}>-</div>
<button>{count}</button>
<div onClick={addNumber}>+</div>
</div>
);
} catch (error) {
console.error("ERROR_CODE: _RENDER\n", error);
return <></>;
}
};

export default Counter;

Step 2 — Add the picture in picture functionality

In the openPictureInPicture() function we request for a picture in picture window.

const pipWindow = await window.documentPictureInPicture.requestWindow();

We create a div element in the body of the pip window. On this div we will mount our Counter.js

const pipDiv = pipWindow.document.createElement("div");
pipDiv.setAttribute("id", "pip-root");
pipWindow.document.body.append(pipDiv);

Now we mount our Counter.js component on the div with id “pip-root”.

const PIP_ROOT = ReactDOM.createRoot(
pipWindow.document.getElementById("pip-root")
);
PIP_ROOT.render(<Counter />);

Step 3 — Combining it all

The final MainComponent.js code should look something like this.

import React from "react";
import Counter from "./Counter";
import ReactDOM from "react-dom/client";

const MainComponent = () => {
async function openPictureInPicture() {
const pipWindow = await window.documentPictureInPicture.requestWindow();
const pipDiv = pipWindow.document.createElement("div");
pipDiv.setAttribute("id", "pip-root");
pipWindow.document.body.append(pipDiv);
const PIP_ROOT = ReactDOM.createRoot(pipWindow.document.getElementById("pip-root"));
PIP_ROOT.render(<Counter />);
}

return (
<div>
<div onClick={openPictureInPicture}>Open counter</div>
</div>
);
};

export default MainComponent;

and the app should look something like this on the browser.

Now we have our own react component mounting on a picture in picture window!

Learn more about document picture in picture here https://developer.chrome.com/docs/web-platform/document-picture-in-picture/

Cover Photo by Blake Connally on Unsplash

--

--

No responses yet