Utilisation de l'API DModal pour afficher des fenêtres modales (popups/dialogues) dans Discourse

Discourse 3.1.0.beta6 est livré avec une toute nouvelle API basée sur le composant <DModal>. DModal fait partie du kit d’interface utilisateur et est importé depuis discourse/ui-kit/d-modal.

:information_source: Cela remplace l’ancienne API basée sur les contrôleurs, qui est désormais obsolète. Si vous avez des modales existantes utilisant les anciennes API, consultez le guide de migration ici.

Affichage d’une modale

Les modales sont affichées en incluant le composant <DModal> dans un modèle handlebars. Si vous n’avez pas encore de modèle approprié, consultez Using Plugin Outlet Connectors from a Theme or Plugin.

Une modale simple ressemblerait à ceci :

<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: L’helper mut est utilisé ici comme moyen exclusif à hbs pour définir une valeur. Vous pourriez également définir modalIsVisible en utilisant n’importe quelle autre méthode standard d’Ember.

Cet exemple créera une modale simple comme celle-ci :

Encapsulation dans un composant

Avant d’introduire plus de complexité, il est généralement préférable d’encapsuler votre nouvelle modale dans sa propre définition de composant. Déplaçons le contenu <DModal> à l’intérieur d’un nouveau composant <MyModal />

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

La mise à niveau de ce fichier .gjs en composant basé sur une classe vous permettra d’introduire une logique et un état plus complexes.

Pour utiliser le nouveau composant, mettez à jour le site d’appel pour y faire référence, en vous assurant de passer un argument @closeModal.

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

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

Ajout d’un pied de page

De nombreuses modales ont une sorte d’appel à l’action. Dans Discourse, celles-ci sont généralement situées en bas de la modale. Pour rendre cela possible, DModal dispose d’un certain nombre de « blocs nommés » dans lesquels du contenu peut être rendu. Voici l’exemple mis à jour pour inclure deux boutons dans le pied de page, dont notre bouton standard 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>

Affichage d’une modale depuis un contexte non-hbs

Idéalement, les instances de <DModal> doivent être affichées depuis un modèle Ember en utilisant la technique déclarative démontrée ci-dessus. Si cela n’est pas réalisable pour votre cas d’utilisation, cela peut être fait en injectant le service modal et en appelant modal.show().

Assurez-vous d’avoir encapsulé votre modale dans son propre composant comme décrit ci-dessus. Ensuite, déclenchez la modale en passant une référence de votre classe de composant à showModal :

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

// (injectez le service modal à l'endroit approprié)

// Ajoutez cet appel chaque fois que vous souhaitez ouvrir la modale.
// Un argument `@closeModal` sera automatiquement passé à votre composant.
this.modal.show(MyModal);

// Optionnellement, passez un paramètre `model`. Passé en tant que `@model` à votre composant.
// Cela peut inclure des données, ainsi que des actions/callbacks pour votre modale.
this.modal.show(MyModal, {
  model: { topic: this.topic, someAction: this.someAction },
});

// `modal.show()` renvoie une promesse, vous pouvez donc attendre qu'elle soit fermée
// Elle sera résolue avec les données passées à l'action `@closeModal`
const result = await this.modal.show(MyModal);

Plus de personnalisation !

<DModal> dispose d’un certain nombre de blocs nommés et d’arguments.

Arguments

Arg But
@closeModal Requis pour que l’interface de fermeture s’affiche du tout.
@title Affiche <h1 id="discourse-modal-title"> ; câble aria-labelledby.
@subtitle Petit texte sous le titre.
@flash / @flashType Alerte en ligne en haut de la modale (DFlashMessage).
@hideHeader, @hideFooter Masque les régions entières.
@headerClass, @bodyClass Classe supplémentaire sur les enveloppes d’en-tête/corps.
@dismissable Vrai par défaut lorsque @closeModal est défini. Désactive Échap / clic sur l’arrière-plan / X.
@autofocus Vrai par défaut. Met automatiquement le focus sur le premier élément focalisable via dTrapTab.
@submitOnEnter Vrai par défaut. Entrée clique sur .d-modal__footer .btn-primary sauf si le focus est dans un formulaire / zone de texte / select-kit.
@beforeClose async ({ initiatedBy }) => boolean. Renvoie false pour annuler la fermeture (par ex. confirmation de formulaire sale).
@hidden Met en pause le traitement du clavier ; utilisé lorsqu’une modale imbriquée est au-dessus.
@tagName "div" (par défaut) ou "form". Utilisez "form" pour les formulaires afin que la soumission native fonctionne.

Blocs

Block Position Quand l’utiliser
default / :body Zone de contenu principale Zone par défaut
:aboveHeader Tout en haut, avant l’en-tête Rarement nécessaire ; pour un contenu qui doit se situer au-dessus de la barre de titre (par ex. une bannière).
:headerAboveTitle À l’intérieur de l’en-tête, avant le titre Présent mais inutilisé. Rarement nécessaire.
:belowModalTitle À l’intérieur de .d-modal__title, après le <h1> Position excellente pour des informations métadonnées complémentaires.
:headerBelowTitle À l’intérieur de l’en-tête, après le bloc de titre Onglets, sous-navigation ou champ de recherche faisant partie de l’en-tête.
:headerPrimaryAction Côté droit de l’en-tête uniquement sur mobile Remplace le bouton de fermeture X par une action principale (par ex. « Enregistrer »). Affiche également automatiquement un bouton « Annuler » à gauche et ajoute .--has-primary-action à l’en-tête.
:belowHeader Entre l’en-tête et le corps Contenu de sous-en-tête persistant (par ex. recherche) situé en dehors du corps défilable, donc affichage collant.
:aboveFooter Entre le corps et le pied de page Supprimé lorsque @hideFooter est défini. À utiliser pour un contenu lié au pied de page mais situé en dehors. Également rare.
:footer Barre d’actions en bas Boutons principaux et secondaires. Le premier .btn-primary ici est ce que déclenche la touche Entrée.
:belowFooter Après le pied de page Rarement nécessaire ; ignore @hideFooter. Utile pour un texte de statut situé en dehors de la zone de pied de page bordée.

Sources : le style guide interactif pour les arguments, et l’implémentation du modèle d-modal pour les blocs nommés.

CSS

Utilisez les classes .d-modal comme ancre pour remplacer le cœur, et évitez le sélecteur .modal obsolète.

4 modificateurs disponibles :

  • .--large définit la largeur maximale à 800px (bureau uniquement)
  • .--max définit la largeur maximale à 90vw (bureau uniquement)
  • .has-search définit une hauteur fixe (80vh) : destiné aux modales avec système de recherche/filtre pour éviter un changement de hauteur basé sur la longueur des résultats (bureau uniquement)
  • .--stacked définit les boutons du pied de page en empilement (mobile uniquement)

Ce document est sous contrôle de version - suggérez des modifications sur github.

17 « J'aime »

Une publication a été divisée en un nouveau sujet : Puis-je afficher une modale depuis head_tag