# Using Popup Windows in io.Connect Desktop

**URL:** <https://community.interop.io/t/using-popup-windows-in-io-connect-desktop/589>\
**Category:** io.Connect Desktop\
**Created:** [May 27, 2026, 8:13am UTC](https://community.interop.io/t/using-popup-windows-in-io-connect-desktop/589 "2026-05-27T08:13:47Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![toni.petrov](https://yyz2.discourse-cdn.com/flex028/user_avatar/community.interop.io/toni.petrov/32/17_2.png) [@toni.petrov](https://community.interop.io/u/toni.petrov)\
**Post date:** [May 27, 2026, 8:13am UTC](https://community.interop.io/t/using-popup-windows-in-io-connect-desktop/589/1 "2026-05-27T08:13:47Z")

</div>

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()`](https://docs.interop.io/desktop/capabilities/windows/window-management/javascript/index.html#creating-popup-windows).

`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.

```html
<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.

```html
<!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.

```js
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.href` loads the HTML page into that popup.
- `ioConnectWindow.id` is passed as `windowId` to `showPopup()`.
- `targetBounds` tells io.Connect Desktop where the popup should appear.
- `targetLocation` and `verticalOffset` control the popup placement.

You can also create the content directly with JavaScript, as shown in the official docs:

```js
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:

1. Define a visible app that triggers the popup.
2. Define a hidden app that contains the popup UI.
3. Find the hidden popup window by name.
4. Pass its window ID to `showPopup()`.

For io.Connect Desktop 10+, the hidden popup window must be frameless. Register the apps.

```json
{
        "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:

```javascript
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:

```javascript
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:

```plaintext
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:

```json
"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.

## References

- [Popup Windows](https://docs.interop.io/desktop/capabilities/windows/window-management/javascript/index.html#popup_windows)
- [CreatePopupOptions](https://docs.interop.io/desktop/reference/javascript/windows/createpopupoptions/index.html)
- [PopupOptions](https://docs.interop.io/desktop/reference/javascript/windows/popupoptions/index.html)
- [IOConnectWindow.showPopup()](https://docs.interop.io/desktop/reference/javascript/windows/ioconnectwindow/index.html#showpopup)
