Discourse 3.1.0.beta6 est livré avec une nouvelle API basée sur des composants <DModal>. DModal fait partie de la boîte à outils UI et est importé depuis discourse/ui-kit/d-modal.
Cela remplace l’ancienne API basée sur des 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}}
L’helper
mutest utilisé ici comme moyen spécifique à hbs pour définir une valeur. Vous pourriez également définirmodalIsVisibleen utilisant toute 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 vers un composant basé sur une classe vous permettra d’introduire une logique et un état plus complexes.
Pour utiliser le nouveau composant, mettez à jour le point d’appel pour le référencer, 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 un certain type d’action d’appel. Dans Discourse, ceux-ci sont généralement situés en bas de la modale. Pour rendre cela possible, DModal a 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 <DModal> devraient être affichées depuis un modèle Ember en utilisant la technique déclarative démontrée ci-dessus. Si ce 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";
// (inject the modal service in the relevant place)
// Add this call whenever you want to open the modal.
// A `@closeModal` argument will be passed to your component automatically.
this.modal.show(MyModal);
// Optionally, pass a '`model`' parameter. Passed as `@model` to your component.
// This can include data, and also actions/callbacks for your Modal to use.
this.modal.show(MyModal, {
model: { topic: this.topic, someAction: this.someAction },
});
// `modal.show()` returns a promise, so you can wait for it to be closed
// It will resolve with the data passed to the `@closeModal` action
const result = await this.modal.show(MyModal);
Plus de personnalisation !
<DModal> a un certain nombre de blocs nommés et d’arguments.
Arguments
| Arg | Purpose |
|---|---|
@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 |
Masquer des régions entières. |
@headerClass, @bodyClass |
Classe supplémentaire sur les enveloppe 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 focusable 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. Renvoyer false pour annuler la fermeture (ex. confirmation de formulaire modifié). |
@hidden |
Met la gestion du clavier en pause ; 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 | When to use |
|---|---|---|
default / :body |
Zone de contenu principale | Zone par défaut |
:aboveHeader |
Tout en haut, avant l’en-tête | Rarement nécessaire ; pour du contenu qui doit être situé au-dessus de la barre de titre (ex. une bannière). |
:headerAboveTitle |
Dans l’en-tête, avant le titre | Présent mais inutilisé. Rarement nécessaire. |
:belowModalTitle |
Dans .d-modal__title, après le <h1> |
Excellente position pour des informations métadonnées complémentaires. |
:headerBelowTitle |
Dans 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 sur mobile uniquement | Remplace le bouton de fermeture X par une action principale (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 (ex. recherche) qui est en dehors du corps défilable, pour un affichage collant. |
:aboveFooter |
Entre le corps et le pied de page | Supprimé lorsque @hideFooter est défini. Utiliser pour du contenu lié au pied de page mais en dehors de celui-ci. Également rare. |
:footer |
Barre d’actions en bas | Boutons principaux et secondaires. Le premier .btn-primary ici est ce que déclenche Entrée. |
:belowFooter |
Après le pied de page | Rarement nécessaire ; ignore @hideFooter. Utile pour le texte de statut 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 écraser le noyau et évitez le sélecteur .modal obsolète.
4 modificateurs disponibles :
- .
--largedéfinit la largeur maximale à 800px (bureau uniquement) - .
--maxdéfinit la largeur maximale à 90vw (bureau uniquement) - .
has-searchdéfinit une hauteur fixe (80vh) : destiné aux modales avec système de recherche/filtre pour éviter le changement de hauteur basé sur la longueur des résultats (bureau uniquement) .--stackeddé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.

