ダイアログ
hc-dialog は、標準の <dialog> 要素に適用する薄いクラスです。
モーダルのライフサイクル — フォーカストラップ、Escape で閉じる、
背景の inert、トップレイヤー描画 — はブラウザが所有し、この
コンポーネントは見た目の面だけを足します。
別名: モーダル、モーダルダイアログ(modal)。
基本の HTML
Section titled “基本の HTML”<button class="hc-button" data-variant="primary" onclick="document.getElementById('my-dialog').showModal()"> Open dialog</button>
<dialog class="hc-dialog" id="my-dialog" aria-labelledby="my-dialog-title"> <header class="hc-dialog__header"> <h2 class="hc-dialog__title" id="my-dialog-title">Confirm something</h2> </header> <div class="hc-dialog__body"> <p>Body content.</p> </div> <footer class="hc-dialog__footer"> <!-- form method="dialog" closes the dialog natively, no JS needed --> <form method="dialog"><button class="hc-button">Cancel</button></form> <form method="dialog"><button class="hc-button" data-variant="primary">OK</button></form> </footer></dialog>| パーツ | 用途 |
|---|---|
.hc-dialog | ルートの <dialog> 要素。 |
.hc-dialog__header | タイトル行。下に区切り線。 |
.hc-dialog__title | ヘッダー内の見出し。 |
.hc-dialog__body | メインのコンテンツ領域。ダイアログがビューポートより高いときスクロールするのはここ。 |
.hc-dialog__footer | アクション行。右寄せ、上に区切り線。 |
パーツは慣習です — どれでも省略できます。
背の高いダイアログ
Section titled “背の高いダイアログ”開いているダイアログはカラムなので、ビューポートより高い内容は 本文の中でスクロールし、ヘッダーとフッターはその場に留まります。 主要アクションはフッターにあるためこれが効きます — フィールドが十数個 ある検索パネルでは、そうしないとボタンが画面外に押し出されます。
3 つのパーツをまとめて 1 つのフォームで包んでも構いません。フッターの ボタンが本文のフィールドを送信する場合の通常の形です:
<dialog class="hc-dialog" id="filters" aria-labelledby="filters-title"> <form method="get" action="/orders"> <div class="hc-dialog__header"> <h2 class="hc-dialog__title" id="filters-title">検索条件</h2> </div> <div class="hc-dialog__body">…多数のフィールド…</div> <div class="hc-dialog__footer"> <button class="hc-button" type="submit" data-variant="primary">検索</button> </div> </form></dialog>横幅の広いパネルには --hc-dialog-max-width で余裕を与えてください。
高さの上限はブラウザが持つので、指定は不要です。
ネイティブのメソッドを使います:
dialog.showModal(); // modal, with focus trap and ::backdropdialog.show(); // non-modal, no backdropdialog.close(); // close (modal or non-modal)dialog.close('confirm'); // close and set returnValue解散に反応するには close イベントを待ち受けます:
dialog.addEventListener('close', () => { if (dialog.returnValue === 'confirm') { // user accepted }});htmx での利用
Section titled “htmx での利用”本文がサーバから来るモーダルは リモートダイアログレシピを 参照。事前の確認ステップ(承認までラウンドトリップなし)は 確認アクションを 参照してください。
ダイアログ内のフォームを成功時に閉じるには、
data-hc-close-dialog-on-success でオプトインします:
<form data-hx-post="/items" data-hx-target="closest dialog" data-hx-swap="outerHTML" data-hc-close-dialog-on-success> …</form>この糊付けは installCloseDialog() ビヘイビアです —
htmx:afterRequest を待ち受けて成功を確認し、最寄りの <dialog>
祖先の dialog.close() を呼びます。installCloseDialog() は冪等で、
アンインストーラを返します。ゼロ設定の
@hypermedia-components/core/behaviors エントリが自動インストールし、
htmx でスワップされた内容も自動で拾います。
アクセシビリティ
Section titled “アクセシビリティ”- ネイティブの
<dialog>要素を使ってください。showModal()を 本当に使えないのでない限り、<div role="dialog">でダイアログを 模倣しないでください。 showModal()で開かれたダイアログでは、フォーカストラップと Escape をブラウザが自動処理します。- ダイアログにラベルを付けてください。次のいずれかで:
- ダイアログにタイトルの id を指す
aria-labelledbyを設定する、 または - タイトルを最初のフォーカス可能要素より前に置き、開いたときに 読み上げられるようにする。
- ダイアログにタイトルの id を指す
- 破壊的な確認では、開いたときに Cancel ボタンへフォーカスして ください — 破壊的アクションへは決して。
テーマ用トークン
Section titled “テーマ用トークン”| トークンパス | 用途 |
|---|---|
dialog.bg / -fg | 面の色。 |
dialog.border | ダイアログ周りの枠線。 |
dialog.radius | 角丸。 |
dialog.padding | 各パーツのパディング。 |
dialog.gap | フッターのボタン間のギャップ。 |
dialog.max-width | 最大インラインサイズ。 |
dialog.backdrop | ::backdrop の色。 |
dialog.duration | 開閉トランジションの時間。 |
CSS 変数
Section titled “CSS 変数”生成される CSS 変数を表示
--hc-dialog-bg | -fg | -border--hc-dialog-radius | -padding | -gap | -max-width | -duration--hc-dialog-backdrop- ポップオーバーコンポーネント — 非モーダルの兄弟。
- 確認アクションレシピ
- リモートダイアログレシピ
レシピでの利用: リモートダイアログ · セッション切れ再認証