There are two common ways to leverage pop-up windows in io.Connect Desktop:
- For io.Connect Desktop 10+, create the popup dynamically with
io.windows.createPopup(). - For older versions or existing apps you don’t want to rewrite, reuse a hidden frameless app/window and show it with
showPopup().
A) Available since Desktop 10+: createPopup()
Starting with io.Connect Desktop 10.0, you can create a popup with io.windows.createPopup().
createPopup() creates a hidden frameless popup window for you. You don’t need a separate app definition, an auto-started hidden app, or a preconfigured popup-window. You can create a simple popup content directly with JavaScript by using the returned browserWindow.document. or keepthe popup UI in a separate HTML file which is more structured and usually easier to maintain.
1. Create the launcher app
The launcher app contains the button that will show the popup.
<button type="button" id="button" class="btn btn-primary">
Show Dynamic Popup
</button>
<span id="status">Popup not created yet.</span>
<script src="index.js"></script>
2. Create the popup HTML
Create a separate popup.html file for the popup UI.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Quick Actions</title>
<style>
html,
body {
box-sizing: border-box;
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
font-family: Arial, sans-serif;
background: #1f2933;
color: #f5f7fa;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
.popup {
height: 100%;
padding: 16px;
display: flex;
flex-direction: column;
justify-content: center;
gap: 10px;
}
h3 {
margin: 0;
font-size: 18px;
}
p {
margin: 0;
color: #cbd5e1;
font-size: 13px;
}
.actions {
display: flex;
gap: 8px;
}
button {
padding: 6px 10px;
border-radius: 3px;
font: inherit;
font-size: 13px;
cursor: pointer;
}
.primary {
border: 0;
background: #4f8cff;
color: white;
}
.secondary {
border: 1px solid #64748b;
background: transparent;
color: #f5f7fa;
}
</style>
</head>
<body>
<div class="popup">
<h3>Quick Actions</h3>
<p>This frameless popup was created dynamically with io.windows.createPopup().</p>
<div class="actions">
<button class="primary">Open Details</button>
<button class="secondary">Copy ID</button>
</div>
</div>
</body>
</html>
3. Create and show the popup
In the launcher app, create the popup with createPopup(), load the HTML page into it, and show it relative to the button.
window.addEventListener("DOMContentLoaded", initializeApp);
async function initializeApp() {
const io = await IODesktop();
const button = document.getElementById("button");
const status = document.getElementById("status");
const myWindow = io.windows.my();
const popup = await io.windows.createPopup({
width: 320,
height: 160
});
popup.browserWindow.location.href =
"http://localhost:4242/popup/create-popup-app/popup.html";
status.textContent = "Popup created.";
button.addEventListener("click", async () => {
await showPopup(popup, myWindow, button);
status.textContent = "Popup shown.";
});
}
function getButtonBounds(button) {
return {
left: Math.round(button.getBoundingClientRect().left),
top: Math.round(button.getBoundingClientRect().top),
width: Math.round(button.getBoundingClientRect().width),
height: Math.round(button.getBoundingClientRect().height)
};
}
async function showPopup(popup, myWindow, button) {
const popupOptions = {
windowId: popup.ioConnectWindow.id,
targetBounds: getButtonBounds(button),
size: {
width: 320,
height: 160
},
targetLocation: "bottom",
verticalOffset: 12
};
await myWindow.showPopup(popupOptions);
}
The important pieces are:
createPopup()creates the hidden frameless popup window.browserWindow.location.hrefloads the HTML page into that popup.ioConnectWindow.idis passed aswindowIdtoshowPopup().targetBoundstells io.Connect Desktop where the popup should appear.targetLocationandverticalOffsetcontrol the popup placement.
You can also create the content directly with JavaScript, as shown in the official docs:
const popup = await io.windows.createPopup();
popup.browserWindow.document.body.innerText = "My Popup";
This is useful for quick examples or simple messages, but a separate HTML file is easier to read, style, test, and maintain.
B) Pre-10 Versions and Existing Apps: showPopup()
If you already have a hidden app or hidden window that you use as a popup, you don’t have to rewrite it immediately. You can still show that window with showPopup().
This is the pattern used by older examples:
- Define a visible app that triggers the popup.
- Define a hidden app that contains the popup UI.
- Find the hidden popup window by name.
- Pass its window ID to
showPopup().
For io.Connect Desktop 10+, the hidden popup window must be frameless. Register the apps.
{
"name":"popup-demo",
"title":"Popup Demo",
"type": "window",
"ignoreSavedLayout": true,
"details":{
"url":"http://localhost:4242/popup/popup-app/index.html",
"mode": "html",
"top": 200,
"left": 200
}
},
{
"name": "popup-window",
"title": "Popup",
"type": "window",
"ignoreSavedLayout": true,
"hidden": true,
"autoStart": true,
"details": {
"url": "http://localhost:4242/popup/popup-window/index.html",
"mode": "frameless",
"hidden": true
}
}
Then from the visible app:
async function initializeApp() {
// Initialize the `@interopio/desktop` library.
await initializeIOConnect().catch(console.error);
// Reference to the window which will be used as a popup.
const popup = io.windows.find("popup-window");
if (!popup) {
console.error("Popup window wasn't found. Make sure the popup-window app is registered and running.");
return;
}
// Reference to the button which will trigger the popup when clicked.
const button = document.getElementById("button");
// Reference to this window.
const myWindow = io.windows.my();
button.addEventListener("click", () => {
activatePopup(popup, myWindow, button);
});
};
And show the popup button:
const popup = io.windows.find("popup-window");
const myWindow = io.windows.my();
await myWindow.showPopup({
windowId: popup.id,
targetBounds: getButtonBounds(button),
size: {
width: 320,
height: 160
},
targetLocation: "bottom",
verticalOffset: 12
});
Use this approach when the popup already exists as a separate app with its own configuration, lifecycle, or compatibility requirements.
This will work in io.Connect 10+, but only with a frameless window. If you see this error:
Method 'showAsPopup' can not be called for window with id ... and mode "html"
then the window you’re trying to show as a popup was created as an HTML window, not a frameless one.
For the hidden-window approach, check the app definition loaded by io.Connect Desktop and make sure it contains:
"mode": "frameless"
If the config is already fixed but the error still appears, restart io.Connect Desktop or close the already-running hidden popup instance. Existing windows keep the mode they were created with, so a running "html" instance must be recreated.