突然始めたから初心者レベルやで。
適当にプロジェクト作って、こんな画面を作成。
(プロジェクト作成方法とかは何がいいのか知らないので割愛)

いろいろ検索するとだいたいレンダラープロセス(HTML)のほうでNodeの機能(主にremote)を呼び出してるんだけど、
現在はデフォルトで非推奨らしいのでcontextBridgeを使って、なんでもメインプロセスで動かす必要があるらしい。
まぁそりゃレンダラーのほうでなんでも実行されたらセキュリティ的にあぶないし。
ボタンでダイアログ
とりあえずボタン押したらダイアログを出す。
contextBridgeに関しては以下のページがすごく参考になりました。
https://blog.katsubemakito.net/nodejs/electron/ipc-for-contextbridge
まずはpreload.jsを作成して、レンダラー → メインを作成。名前は適当に「dialogMsg」にしてます。
const { ipcRenderer, contextBridge } = require("electron");
contextBridge.exposeInMainWorld("electron", {
  // レンダラー → メイン
  dialogMsg: async (data) => await ipcRenderer.invoke("dialogMsg", data),
});
メインプロセス側のindex.jsはipcMainでダイアログを出す処理を作成。
// Native
const { join } = require("path");
const { format } = require("url");
// Packages
const { BrowserWindow, app, ipcMain, dialog} = require("electron");
const isDev = require("electron-is-dev");
const prepareNext = require("electron-next");
// Prepare the renderer once the app is ready
app.on("ready", async () => {
  await prepareNext("./renderer");
  // ウィンドウ作成
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: join(__dirname, "preload.js"),
    },
  });
  // URL作成
  const url = isDev
    ? "http://localhost:8000"
    : format({
        pathname: join(__dirname, "../renderer/out/index.html"),
        protocol: "file:",
        slashes: true,
      });
  if (isDev) {
    // 開発者ツール
    mainWindow.webContents.openDevTools();
  }
  mainWindow.loadURL(url);
});
// 終了処理
app.on("window-all-closed", app.quit);
// 以下レンダーとの通信
ipcMain.handle("dialogMsg", (event, data) => {
  const w = BrowserWindow.getFocusedWindow();
  dialog.showMessageBox(w, {
    type: "info",
    title: "タイトル",
    message: data,
  });
  return;
});
レンダラープロセス側のindex.jsではonClickイベントでdialogActionを呼び出して、
メインプロセス側の処理を呼び出し。
import { useState, useEffect } from "react";
export default function Home() {
  // 初回のイベント
  useEffect(() => {
    console.log("useEffect");
  }, []);
  // ボタンイベント
  const dialogAction = async (event) => {
    console.log("dialogAction");
    await window.electron.dialogMsg("テストだよ");
  };
  return (
    <div className="main">
      <h1 id="test">
        右クリックサンプル
      </h1>
      <button id="test_button" type="button" onClick={dialogAction}>
        TEST
      </button>
      <style jsx>{`
        h1 {
          font-size: 20px;
        }
      `}</style>
      <style jsx global>{`
        body {
          background-color: white;
        }
      `}</style>
    </div>
  );
}
h1タグで右クリック
まぁダイアログとほぼ同じですね。まぁあれなんでレンダラーのほうのイベントもキックします。
まずはpreload.jsを修正。レンダラー → メインのpopupMenuを追加して、メイン → レンダラーを追加しました。
const { ipcRenderer, contextBridge } = require("electron");
contextBridge.exposeInMainWorld("electron", {
  // レンダラー → メイン
  dialogMsg: async (data) => await ipcRenderer.invoke("dialogMsg", data),
  popupMenu: async (data) => await ipcRenderer.invoke("popupMenu", data),
  // メイン → レンダラー
  on: (channel, callback) =>
    ipcRenderer.on(channel, (event, argv) => callback(event, argv)),
});
次にメインプロセス側でメニュー作成とそれを表示するipcMainを追加。
// メニューを作成
const menu = Menu.buildFromTemplate([
  {
    label: "Test Menu",
    click: () => {
      // ウィンドウを取得して、レンダラーに通知
      const w = BrowserWindow.getFocusedWindow();
      w.webContents.send("popuo-return");
    },
  },
  { type: "separator" },
  { role: "quit" },
]);
// コンテキストメニューを表示
ipcMain.handle("popupMenu", (event) => {
  const w = BrowserWindow.getFocusedWindow();
  menu.popup(w);
  return;
});
レンダラー側ではonContextMenuを追加してcontextMenuイベントを呼び出して、ContextMenuを表示して、
メニューを選択したら、popuo-returnを起動して、レンダラー側でAlertを表示。
import { useState, useEffect } from "react";
export default function Home() {
  // 初回のイベント
  useEffect(() => {
    console.log("useEffect");
    window.electron.on("popuo-return", (event) => {
      alert("右クリックからのアラート");
    });
  }, []);
  // 右クリックメニュー
  const contextMenu = async (event) => {
    console.log("contextMenu", event.currentTarget);
    event.preventDefault();
    await window.electron.popupMenu();
  };
  // ボタンイベント
  const dialogAction = async (event) => {
    console.log("dialogAction");
    await window.electron.dialogMsg("テストだよ");
  };
  return (
    <div className="main">
      <h1 id="test" onContextMenu={contextMenu}>
        右クリックサンプル
      </h1>
      <button id="test_button" type="button" onClick={dialogAction}>
        TEST
      </button>
      <style jsx>{`
        h1 {
          font-size: 20px;
        }
      `}</style>
      <style jsx global>{`
        body {
          background-color: white;
        }
      `}</style>
    </div>
  );
}
以上です。



