eyecatch

dialog elementで Modal作ってますか? SvelteでModalを作ってみた

Posted on 2023/12/13
# Technology

dialog element について

<dialog> は alert window や モダル、ダイアログなどの様な画面上でユーザーにアクションを促す様なコンポネントを表示したい時に使用されます。

よくある実装は close or open を status として持って <div> の表示を制御する方法が多く見受けられますが、それは <dialog> の存在がまだ薄いからな様な気がしてます。

今回せっかくなので最近人気上昇中の Svelte で簡単に実装してみました。

MDN: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog

Svelte での実装すると

REPL: https://svelte.dev/repl/ab996f113bd4418db6a2aa3c1721559b?version=4.2.8

<script>
  export let dialog;
</script>

<dialog bind:this={dialog} on:close>
  <slot />
</dialog>
<script>
  import Modal from "./Modal.svelte"
  let dialog;

  const openModal = () => {
    dialog.showModal();
  }

  const closeModal = () => {
    dialog.close();
  }
</script>

<button on:click={openModal}>Open modal</button>
<Modal bind:dialog >
	<h1>Hello from Modal!!</h1>
	<button on:click={closeModal}>Close</button>
</Modal>

Output

A modal と non-modal dialog とは

dialog には a modal と non-modal dialog の2種類のモードタイプがあります。

A modal はユーザーにアクションを行わせるために、黒色のオーバーレイなどで操作していたコンテンツを操作無効にしてモダル内のみのアクションに集中させるモダル。

Non-modal dialog はモダルが開いた状態でも今まで使ってたコンテンツも操作が可能なダイアログ。

open attribute は非推奨

<dialog open /> または .show() で開閉をすると dialog は non-modal となる。その場合背景の overlay は表示されなくなるので 非推奨となっている。

その代わりに用意されてるAPIとして .showModal().close() を使用すると modal として dialog が使用でき、overlay が表示される様になる。

背景は ::backdrop でスタイリング

背景の overlay は ::backdrop にスタイルを当てることで変更することができる。

::backdrop {
  background-image: linear-gradient(
    45deg,
    magenta,
    rebeccapurple,
    dodgerblue,
    green
  );
  opacity: 0.75;
}

こんな感じにすると虹色の背景も作れる。

下記のように @starting-style でアニメーションも可能

dialog::backdrop {
  background-color: rgb(0 0 0 / 0);
  transition:
    display 0.7s allow-discrete,
    overlay 0.7s allow-discrete,
    background-color 0.7s;
}

dialog[open]::backdrop {
  background-color: rgb(0 0 0 / 0.25);
}

@starting-style {
  dialog[open]::backdrop {
    background-color: rgb(0 0 0 / 0);
  }
}

method="dialog" で form を close することもできる

下記の2通りのやり方で .close() を呼ばなくても開いている dialog をとじることができる。

# Pattern 1 - form action method
<dialog open>
  <p>Greetings, one and all!</p>
  <form method="dialog">
    <button>OK</button>
  </form>
</dialog>

# Pattern 2 - formmethod
<button formmethod="dialog">Close</button>

dialogは#top-layer に 追加される

Modal mode での dialog は #top-layer と呼ばれる <html> の兄弟要素に配置されるので html のどの要素よりも上に表示されます。
気をつけないといけないのが他の toast など layer の上に表示されたいものよりも上のレイヤーで表示されることに注意してください。

Browser compatibility