ダイアログ
hc-dialog は、標準の <dialog> 要素に適用する薄いクラスです。
モーダルのライフサイクル — フォーカストラップ、Escape で閉じる、
背景の inert、トップレイヤー描画 — はブラウザが所有し、この
コンポーネントは見た目の面だけを足します。
別名: モーダル、モーダルダイアログ(modal)。
基本の HTML
Section titled “基本の HTML”<!-- commandfor + command でネイティブに開く: スクリプトもリスナーも不要 --><button class="hc-button" data-variant="primary" type="button" commandfor="my-dialog" command="show-modal"> 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> にはクリックで開くための属性が自前にはありませんが、HTML の
invoker commands がどのボタンにもそれを与えます — 宣言的で、
スクリプトもリスナーも不要、Content-Security-Policy: default-src 'self'
が文句を言うものもありません:
<button class="hc-button" type="button" commandfor="my-dialog" command="show-modal">Open</button>
<dialog class="hc-dialog" id="my-dialog"> … <button class="hc-button" type="button" commandfor="my-dialog" command="close">Close</button></dialog>command="show-modal"はcommandforが id で指す要素のshowModal()を呼びます — フォーカストラップ、::backdrop、Escape、 閉じたときにオープナーへフォーカスが戻ることまで、すべてブラウザの 仕事です。command="close"はclose()を呼びます。どこからでも効き、 htmx フォームの内側でも動きます。そこではformmethod="dialog"のボタンは htmx に捕まってダイアログに届きません (remote-dialog レシピ が Cancel を別の<form method="dialog">に置いているのはそのためです — どちらの書き方でも構いません)。- どちらも
type="button"が必要です。submit ボタンは command を 無視してフォームを送信します。
非モーダルの show() や、戻り値つきで閉じるにはネイティブのメソッドを
使います:
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()(またはcommand="show-modal")で開かれたダイアログ では、フォーカストラップと 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- ポップオーバーコンポーネント — 非モーダルの兄弟。
- 確認アクションレシピ
- リモートダイアログレシピ
レシピでの利用: リモートダイアログ · セッション切れ再認証