DModal APIを使用してDiscourseでモーダルウィンドウ(ポップアップ/ダイアログ)を表示する

Discourse 3.1.0.beta6 は、まったく新しいコンポーネントベースの <DModal> API を搭載しています。DModalUI キット の一部であり、discourse/ui-kit/d-modal からインポートされます。

:information_source: これは旧来のコントローラーベースの API を置き換えます。旧 API は現在非推奨です。旧 API を使用して既存のモーダルがある場合は、こちらのマイグレーションガイドを確認してください。

モーダルのレンダリング

モーダルは、handlebars テンプレートに <DModal> コンポーネントを含めることでレンダリングされます。適切なテンプレートを持っていない場合は、Using Plugin Outlet Connectors from a Theme or Plugin を確認してください。

シンプルなモーダルは次のようになります。

<DButton
  @translatedLabel="Show Modal"
  @action={{fn (mut this.modalIsVisible) true}}
/>

{{#if this.modalIsVisible}}
  <DModal @title="My Modal" @closeModal={{fn (mut this.modalIsVisible) false}}>
    Hello world, this is some content in a modal
  </DModal>
{{/if}}

:information_source: ここでは mut ヘルパー が、hbs のみで値を設定する方法として使用されています。modalIsVisible は他の標準的な Ember メソッドでも設定できます。

この例は、次のようなシンプルなモーダルを作成します。

コンポーネントでのラップ

さらに複雑さを加える前に、新しいモーダルを独自のコンポーネント定義にラップするのが通常は最善です。<DModal> の部分を新しい <MyModal /> コンポーネント内に移動しましょう。

// components/my-modal.gjs
<template>
  <DModal @title="My Modal" @closeModal={{@closeModal}}>
    Hello world, this is some content in a modal
  </DModal>
</template>

この .gjs ファイルをクラスベースのコンポーネントにアップグレードすることで、より複雑なロジックや状態を導入できます。

新しいコンポーネントを利用するには、呼び出し箇所を参照するように更新し、@closeModal 引数を渡すことを忘れないでください。

<DButton
  @translatedLabel="Show Modal"
  @action={{fn (mut this.modalIsVisible) true}}
/>

{{#if this.modalIsVisible}}
  <MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}

フッターの追加

多くのモーダルには、何らかのコールトゥアクション(CTA)があります。Discourse では、これらは通常モーダルの下部に配置されます。これを可能にするため、DModal には、その中にコンテンツをレンダリングできる複数の「名前付きブロック」があります。ここでは、フッターに 2 つのボタン(そのうちの 1 つは標準の DModalCancel ボタン)を含むように例を更新しました。

<DModal @title="My Modal" @closeModal={{@closeModal}}>
  <:body>
    Hello world, this is some content in a modal
  </:body>
  <:footer>
    <DButton class="btn-primary" @translatedLabel="Submit" />
    <DModalCancel @close={{@closeModal}} />
  </:footer>
</DModal>

非 hbs コンテキストからのモーダルレンダリング

理想적으로는、上記で示した宣言的なテクニックを使用して、Ember テンプレート内で <DModal> インスタンスをレンダリングすべきです。それが使用ケースに合わない場合は、modal サービスを注入して modal.show() を呼び出すことで実行できます。

上記で説明したように、モーダルを独自のコンポーネントにラップしていることを確認してください。その後、コンポーネントクラスの参照を showModal に渡してモーダルをトリガーします。

import MyModal from "discourse/components/my-modal";

// (関連する場所に modal サービスを注入)

// モーダルを開きたいときにこの呼び出しを追加します。
// `@closeModal` 引数は自動的にコンポーネントに渡されます。
this.modal.show(MyModal);

// 任意で '`model`' パラメータを渡します。`@model` としてコンポーネントに渡されます。
// これはデータや、モーダルが使用するアクション/コールバックを含むことができます。
this.modal.show(MyModal, {
  model: { topic: this.topic, someAction: this.someAction },
});

// `modal.show()` はプロミスを返すため、クローズを待つことができます。
// `@closeModal` アクションに渡されたデータで解決されます。
const result = await this.modal.show(MyModal);

さらにカスタマイズ可能に!

<DModal> には、複数の名前付きブロックと引数があります。

引数

引数 目的
@closeModal 閉じる UI が表示されるために必須です。
@title <h1 id="discourse-modal-title"> をレンダリングし、aria-labelledby を接続します。
@subtitle タイトルの下の小さなテキスト。
@flash / @flashType モーダルの上部のインラインアラート(DFlashMessage)。
@hideHeader, @hideFooter 領域全体を非表示にします。
@headerClass, @bodyClass ヘッダー/ボディーのラッパーに追加するクラス。
@dismissable @closeModal が設定されている場合、デフォルトで true です。Esc / バックドロップクリック / X を無効にします。
@autofocus デフォルトで true です。dTrapTab を介して最初のフォーカス可能な要素に自動フォーカスします。
@submitOnEnter デフォルトで true です。フォーカスがフォーム / テキストエリア / select-kit にない限り、Enter キーで .d-modal__footer .btn-primary をクリックします。
@beforeClose async ({ initiatedBy }) => boolean。クローズをキャンセルするには false を返します(例:未保存フォームの確認)。
@hidden キーボード処理を一時停止します。ネストされたモーダルが上部にある場合に使用されます。
@tagName "div"(デフォルト)または "form"。ネイティブの送信が動作するようにフォームには "form" を使用します。

ブロック

ブロック 位置 使用場面
default / :body メインコンテンツエリア デフォルトの領域
:aboveHeader 最上部、ヘッダーの前 まれに必要;タイトルバーの上(例:バナー)に配置しなければならないコンテンツ用。
:headerAboveTitle ヘッダー内、タイトル前 存在するが未使用。まれに必要。
:belowModalTitle .d-modal__title 内、<h1> の後 補足的なメタ情報のための優れた位置。
:headerBelowTitle ヘッダー内、タイトルブロック後 ヘッダーの一部であるタブ、サブナビ、または検索入力。
:headerPrimaryAction ヘッダーの右側(モバイルのみ X クローズボタンをプライマリアクション(例:“保存”)に置き換えます。また、左側に"キャンセル"ボタンを自動レンダリングし、ヘッダーに .--has-primary-action を追加します。
:belowHeader ヘッダーとボディーの間 スクロール可能なボディーの外側にある永続的なサブヘッダーコンテンツ(例:検索)で、スティッキー表示のために使用。
:aboveFooter ボディーとフッターの間 @hideFooter が設定されている場合に抑制されます。フッターに関連するが外側のコンテンツに使用。またまれです。
:footer 下部アクションバー プライマリ + セカンダリボタン。ここでの最初の .btn-primary は Enter キーでトリガーされるものです。
:belowFooter フッターの後 まれに必要;@hideFooter を無視します。境界付きフッター領域の外側のステータステキストに有用。

ソース:引数についてはインタラクティブスタイルガイド、名前付きブロックについては d-modal テンプレート実装 を参照してください。

CSS

.d-modal クラスをアンカーとして使用してコアをオーバーライドし、レガシーの .modal セレクタを避けてください。

利用可能な 4 つの修飾子:

  • .--large最大幅 を 800px に設定します(デスクトップのみ)
  • .--max最大幅 を 90vw に設定します(デスクトップのみ)
  • .has-search固定高さ(80vh)を設定します:検索/フィルタシステムを持つモーダルで、結果の長さに基づく高さの変化を避けるために意図されています(デスクトップのみ)
  • .--stacked はフッターのボタンをスタッキングに設定します(モバイルのみ)

このドキュメントはバージョン管理されています - 変更を github で提案してください。

「いいね!」 17

投稿が新しいトピックに分割されました: head_tagからモーダルを表示できますか