HTML/CSS で自作のダイアログを作る

Recipe ID: dlg-011

OS ネイティブのダイアログではなく、アプリのデザインに完全にマッチした HTML/CSS 製のカスタムダイアログを作成する方法を紹介します。

1. フロントエンドから作成する (TypeScript/HTML)

HTML5 の <dialog> 要素を使用する方法が最も簡単です。

HTML (index.html)

<!-- ダイアログを開くボタン -->
<button id="open-dialog-btn" class="button">カスタムダイアログを開く</button>

<!-- ダイアログ本体 -->
<dialog id="my-dialog" class="custom-dialog">
  <form method="dialog">
    <h3 class="dialog-title">確認</h3>
    <p class="dialog-message">自作の HTML/CSS ダイアログです。<br>閉じるにはどちらかのボタンを押してください。</p>
    
    <div class="dialog-actions">
      <!-- value属性が戻り値になります -->
      <button value="cancel" class="dialog-btn cancel">キャンセル</button>
      <button value="ok" class="dialog-btn ok">OK</button>
    </div>
  </form>
</dialog>

CSS (styles.css)

/* ダイアログ全体のスタイル */
.custom-dialog {
  border: none;
  border-radius: 12px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
  padding: 24px;
  max-width: 400px;
  width: 90%;
  font-family: sans-serif;
  animation: fadeIn 0.3s ease-out;
}

/* 背景を暗くする */
.custom-dialog::backdrop {
  background-color: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(2px); /* すりガラス効果 */
}

.dialog-title {
  margin-top: 0;
  color: #333;
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 20px;
}

.dialog-btn {
  padding: 8px 16px;
  border-radius: 6px;
  border: none;
  cursor: pointer;
  font-weight: bold;
}

.dialog-btn.ok {
  background-color: #d06283;
  color: white;
}

.dialog-btn.cancel {
  background-color: #f0f0f0;
  color: #333;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(-20px); }
  to { opacity: 1; transform: translateY(0); }
}

TypeScript

const dialog = document.getElementById('my-dialog') as HTMLDialogElement;
const openBtn = document.getElementById('open-dialog-btn');

openBtn?.addEventListener('click', () => {
  if (typeof dialog.showModal === "function") {
    // モーダルとして開く
    dialog.showModal();
  } else {
    alert("このブラウザは <dialog> 要素をサポートしていません");
  }
});

dialog.addEventListener('close', () => {
  console.log('Result:', dialog.returnValue);
});

// 背景クリックで閉じる
dialog.addEventListener('click', (event) => {
  if (event.target === dialog) {
    dialog.close('cancel');
  }
});

2. バックエンドから作成する (Rust)

このレシピはフロントエンドのみの実装パターンですが、Rust 側からイベントを送信してダイアログを開かせることも可能です。

use tauri::Emitter; // Emitter トレイトをインポートする必要があります

#[tauri::command]
fn trigger_custom_dialog(app: tauri::AppHandle) {
    // フロントエンドにイベントを送信
    app.emit("open-custom-dialog", ()).unwrap();
}

TypeScript 側で listen:

import { listen } from '@tauri-apps/api/event';

// イベントをリッスン
listen('open-custom-dialog', () => {
  const dialog = document.getElementById('my-dialog') as HTMLDialogElement | null;
  dialog?.showModal();
});

補足

  • showModal(): 他の要素への操作をブロックする「モーダルモード」になります。
  • form method="dialog": フォーム内のボタンを押すと自動的にダイアログが閉じられ、returnValue がセットされます。
  • デザインの自由度:
    • ネイティブダイアログと異なり、完全に自由に CSS でスタイリングできます。アニメーション、画像、動画、複雑なレイアウトを含めることが可能です。
    • Tauri アプリ全体の世界観を統一したい場合に非常に有効です。