Dialog not centered in InDesign UXP when using React + HTML <dialog> element

,

Hi everyone,

I’m developing a React-based UXP plugin for InDesign, and I’m using the standard HTML <dialog> element with showModal() to display modal dialogs.

The dialog appears correctly and works fine functionally, but it’s not centered on the screen — it often opens toward the bottom-left corner of the window, especially when the dialog’s size is small (e.g., width 390px, height 150px).

Here’s a simplified version of my code:

import React, { useEffect, useRef } from "react";

export default function DialogBase({ title, width = "400px", height = "auto", children, onClose }) {
  const dialogRef = useRef(null);

  useEffect(() => {
    const dialog = dialogRef.current;
    if (!dialog) return;

    try {
      dialog.showModal();
    } catch {
      dialog.setAttribute("open", "");
    }

    const handleKeyDown = (e) => {
      if (e.key === "Escape") onClose?.("escape");
    };
    dialog.addEventListener("keydown", handleKeyDown);
    return () => dialog.removeEventListener("keydown", handleKeyDown);
  }, [onClose]);

  return (
    <dialog
      ref={dialogRef}
      style={{
        width,
        height,
        border: "none",
        borderRadius: "8px",
        backgroundColor: "#F1F1F1",
        boxShadow: "0 8px 20px rgba(0,0,0,0.4)",
      }}
    >
      <form method="dialog">
        {title && <div style={{ padding: "6px 10px", background: "#e0e0e0" }}>{title}</div>}
        <div style={{ padding: "10px" }}>{children}</div>
      </form>
    </dialog>
  );
}

try with dialog.uxpShowModal({..opts}) instead of plain showModal
I think there’s a bit of magic behind the scenes.

import React, { useEffect, useRef } from "react";

export default function DialogBase({
  title,
  width = "400px",
  height = "auto",
  children,
  onClose,
}) {
  const dialogRef = useRef(null);

  useEffect(() => {
    const dialog = dialogRef.current;
    if (!dialog) return;

    const widthNum = parseInt(width);
    const heightNum = parseInt(height);

    try {
      if (dialog.uxpShowModal) {
        dialog.uxpShowModal({
          title: title || "",
          resize: "both",
          size: { width: widthNum || 400, height: heightNum || 300 },
        });
      } else {
        dialog.showModal();
      }
    } catch (err) {
      console.warn("Dialog open error:", err);
      dialog.setAttribute("open", "");
    }

    const handleKeyDown = (e) => {
      if (e.key === "Escape") onClose?.("escape");
    };
    const handleDialogClose = () => {
      onClose?.("native");
    };

    dialog.addEventListener("keydown", handleKeyDown);
    dialog.addEventListener("close", handleDialogClose);

    return () => {
      dialog.removeEventListener("keydown", handleKeyDown);
      dialog.removeEventListener("close", handleDialogClose);
      dialog.close?.();
    };
  }, [onClose, title, width, height]);

  return (
    <dialog
      ref={dialogRef}
      style={{
        border: "none",
        borderRadius: "8px",
        backgroundColor: "#F1F1F1",
        boxShadow: "0px 8px 20px rgba(0,0,0,0.4)",
        fontFamily: "Adobe Clean, sans-serif",
        overflow: "hidden",
      }}
    >
      <form method="dialog" style={{ width: "100%", height: "100%", margin: 0 }}>
        {title && (
          <div
            style={{
              backgroundColor: "#e0e0e0",
              padding: "6px 10px",
              fontWeight: "bold",
              fontSize: "14px",
              borderBottom: "1px solid #ccc",
              textAlign: "center",
            }}
          >
            {title}
          </div>
        )}
        <div
          style={{
            padding: "10px",
            overflowY: "auto",
            boxSizing: "border-box",
            height: "calc(100% - 32px)",
          }}
        >
          {children}
        </div>
      </form>
    </dialog>
  );
}

I tried using dialog.uxpShowModal({...}), the dialog still appears at the top-left corner of the screen instead of being centered.

The behavior is different for macOS and Windows. On macOS, dialogs that do not exceed a certain size are displayed at the bottom left.

However, I have not yet found a solution for this, except to specify a larger width.