Discourse 3.1.0.beta6 incorpora una nueva API basada en componentes <DModal>. DModal forma parte del kit de interfaz de usuario y se importa desde discourse/ui-kit/d-modal.
Esto reemplaza la antigua API basada en controladores, que ahora está en desuso. Si tienes modales existentes que utilizan las API antiguas, consulta la guía de migración aquí.
Renderizado de un modal
Los modales se renderizan incluyendo el componente <DModal> en una plantilla de handlebars. Si aún no tienes una plantilla adecuada, consulta Using Plugin Outlet Connectors from a Theme or Plugin.
Un modal simple se vería algo así:
<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}}
El helper
mutse utiliza aquí como una forma exclusiva de hbs para establecer un valor. También podrías establecermodalIsVisibleutilizando cualquier otro método estándar de Ember.
Este ejemplo creará un modal simple como este:
Envolver en un componente
Antes de introducir más complejidad, generalmente es mejor envolver tu nuevo modal en su propia definición de Componente. Movamos lo de <DModal> dentro de un nuevo componente <MyModal />
// components/my-modal.gjs
<template>
<DModal @title="My Modal" @closeModal={{@closeModal}}>
Hello world, this is some content in a modal
</DModal>
</template>
Mejorar este archivo .gjs a un componente basado en clase te permitirá introducir lógica y estado más complejos.
Para hacer uso del nuevo componente, actualiza el punto de llamada para que lo referencie, asegurándote de pasar un argumento @closeModal.
<DButton
@translatedLabel="Show Modal"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}
Agregando un pie de página
Muchos modales tienen algún tipo de llamada a la acción. En Discourse, estas suelen ubicarse en la parte inferior del modal. Para hacer esto posible, DModal tiene una serie de ‘bloques nombrados’ en los que se puede renderizar contenido. Aquí está el ejemplo actualizado para incluir dos botones en el pie de página, uno de los cuales es nuestro botón estándar 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>
Renderizado de un modal desde un contexto no-hbs
Idealmente, las instancias de <DModal> deben renderizarse desde dentro de una plantilla de Ember utilizando la técnica declarativa demostrada anteriormente. Si eso no es factible para tu caso de uso, se puede hacer inyectando el servicio modal y llamando a modal.show().
Asegúrate de haber envuelto tu modal en su propio componente como se describió anteriormente. Luego, dispara el modal pasando una referencia de tu clase de componente a showModal:
import MyModal from "discourse/components/my-modal";
// (inyecta el servicio modal en el lugar correspondiente)
// Agrega esta llamada cada vez que quieras abrir el modal.
// Se pasará automáticamente un argumento `@closeModal` a tu componente.
this.modal.show(MyModal);
// Opcionalmente, pasa un parámetro '`model`'. Se pasa como `@model` a tu componente.
// Esto puede incluir datos, y también acciones/llamadas de retorno para que tu Modal las use.
this.modal.show(MyModal, {
model: { topic: this.topic, someAction: this.someAction },
});
// `modal.show()` devuelve una promesa, por lo que puedes esperar a que se cierre.
// Se resolverá con los datos pasados a la acción `@closeModal`
const result = await this.modal.show(MyModal);
¡Más personalización!
<DModal> tiene una serie de bloques nombrados y argumentos.
Argumentos
| Arg | Propósito |
|---|---|
@closeModal |
Requerido para que la UI de cierre aparezca en absoluto. |
@title |
Renderiza <h1 id="discourse-modal-title">; conecta aria-labelledby. |
@subtitle |
Texto pequeño debajo del título. |
@flash / @flashType |
Alerta en línea en la parte superior del modal (DFlashMessage). |
@hideHeader, @hideFooter |
Oculta regiones enteras. |
@headerClass, @bodyClass |
Clase adicional en los contenedores de encabezado/cuerpo. |
@dismissable |
Verdadero por defecto cuando se establece @closeModal. Deshabilita Esc / clic en el fondo / X. |
@autofocus |
Verdadero por defecto. Enfoca automáticamente el primer elemento enfocable mediante dTrapTab. |
@submitOnEnter |
Verdadero por defecto. Enter hace clic en .d-modal__footer .btn-primary a menos que el enfoque esté en un formulario / textarea / select-kit. |
@beforeClose |
async ({ initiatedBy }) => boolean. Devuelve false para cancelar el cierre (p. ej., confirmación de formulario sucio). |
@hidden |
Pausa el manejo del teclado; se usa cuando un modal anidado está encima. |
@tagName |
"div" (predeterminado) o "form". Usa "form" para formularios para que el envío nativo funcione. |
Bloques
| Block | Posición | Cuándo usarlo |
|---|---|---|
default / :body |
Área de contenido principal | Área predeterminada |
:aboveHeader |
Parte superior, antes del encabezado | Raramente necesario; para contenido que debe estar por encima de la barra de título (p. ej., un banner). |
:headerAboveTitle |
Dentro del encabezado, antes del título | Presente pero sin uso. Raramente necesario. |
:belowModalTitle |
Dentro de .d-modal__title, después del <h1> |
Excelente posición para información meta complementaria. |
:headerBelowTitle |
Dentro del encabezado, después del bloque de título | Pestañas, sub-navegación o campo de búsqueda que forma parte del encabezado. |
:headerPrimaryAction |
Lado derecho del encabezado solo en móvil | Reemplaza el botón de cierre X con una acción principal (p. ej., “Guardar”). También renderiza automáticamente un botón “Cancelar” a la izquierda y agrega .--has-primary-action al encabezado. |
:belowHeader |
Entre el encabezado y el cuerpo | Contenido de sub-encabezado persistente (p. ej., buscador) que está fuera del cuerpo desplazable, por lo que tiene una posición fija. |
:aboveFooter |
Entre el cuerpo y el pie de página | Suprimido cuando se establece @hideFooter. Úsalo para contenido vinculado al pie de página pero fuera de él. También es raro. |
:footer |
Barra de acciones inferior | Botones primarios y secundarios. El primer .btn-primary aquí es lo que activa Enter. |
:belowFooter |
Después del pie de página | Raramente necesario; ignora @hideFooter. Útil para texto de estado fuera del área del pie de página con borde. |
Fuentes: la guía de estilo interactiva para argumentos, y la implementación de la plantilla d-modal para bloques nombrados.
CSS
Usa las clases .d-modal como ancla para sobrescribir el núcleo y evita el selector de herencia .modal.
4 modificadores disponibles:
- .
--largeestablece el ancho máximo en 800px (solo escritorio) - .
--maxestablece el ancho máximo en 90vw (solo escritorio) - .
has-searchestablece la altura fija (80vh): destinado a modales con sistema de búsqueda/filtro para evitar cambios de altura basados en la longitud del resultado (solo escritorio) .--stackedestablece los botones del pie de página en apilamiento (solo móvil)
Este documento está controlado por versiones - sugiere cambios en github.

