يأتي إصدار Discourse 3.1.0.beta6 مع واجهة برمجة تطبيقات مبنية على مكوّنات جديدة كليًا باسم <DModal>. يُعدّ DModal جزءًا من مجموعة واجهات المستخدم ويتم استيراده من discourse/ui-kit/d-modal.
هذا يحلّ محل واجهة برمجة التطبيقات القديمة المبنية على المتحكمات (controllers)، والتي أصبحت الآن غير مدعومة. إذا كان لديك نوافذ منبثقة (modals) قائمة تستخدم واجهات التطبيقات القديمة، فراجع دليل الترحيل هنا.
عرض نافذة منبثقة (Rendering a Modal)
تُعرض النوافذ المنبثقة عن طريق تضمين مكوّن <DModal> في قالب handlebars. إذا لم يكن لديك قالب مناسب بالفعل، فراجع 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}}
يُستخدم مساعد
mutهنا كطريقة خاصة بملفات hbs فقط لضبط قيمة. يمكنك أيضًا ضبطmodalIsVisibleباستخدام أي طريقة Ember قياسية أخرى.
سيؤدي هذا المثال إلى إنشاء نافذة منبثقة بسيطة مثل هذه:
التغليف في مكوّن (Wrapping in a component)
قبل إدخال أي تعقيد إضافي، من الأفضل عادةً تغليف النافذة المنبثقة الجديدة في تعريف مكوّن خاص بها. لنقم بنقل محتوى <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 إلى مكوّن مبنٍ على فئة (class-based component) ستسمح لك بإدخال منطق وحالة أكثر تعقيدًا.
للاستفادة من المكوّن الجديد، حدّث موقع الاستدعاء (call site) للإشارة إليه، مع التأكد من تمرير حجة @closeModal.
<DButton
@translatedLabel="Show Modal"
@action={{fn (mut this.modalIsVisible) true}}
/>
{{#if this.modalIsVisible}}
<MyModal @closeModal={{fn (mut this.modalIsVisible) false}} />
{{/if}}
إضافة تذييل (Adding a footer)
تحتوي العديد من النوافذ المنبثقة على نوع من إجراءات الاستدعاء (call-to-action). في Discourse، تميل هذه الإجراءات إلى أن تكون في أسفل النافذة المنبثقة. لجعل هذا ممكنًا، يحتوي DModal على عدد من “الكتل المسمّاة” (named blocks) التي يمكن عرض المحتوى بداخلها. إليك المثال محدثًا ليشمل زرين في التذييل، أحدهما هو زر 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 (Rendering a modal from a non-hbs context)
في المثالي، يجب عرض حالات <DModal> من داخل قالب Ember باستخدام التقنية التوضيحية (declarative) المُستعرضة أعلاه. إذا لم يكن ذلك ممكنًا لحالتك، فيمكن القيام بذلك عن طريق حقن خدمة modal واستدعاء modal.show().
تأكد من أنك قمت بتغليف نافذتك المنبثقة في مكوّن خاص بها كما هو موصوف أعلاه. ثم، قم بتشغيل النافذة المنبثقة عن طريق تمرير مرجع لفئة مكوّنك إلى showModal:
import MyModal from "discourse/components/my-modal";
// (حقن خدمة modal في المكان المناسب)
// أضف هذا الاستدعاء في أي وقت تريد فيه فتح النافذة المنبثقة.
// سيتم تمرير حجة `@closeModal` إلى مكوّنك تلقائيًا.
this.modal.show(MyModal);
// اختياريًا، مرّر معامل '`model`'. يُمرر كـ `@model` إلى مكوّنك.
// يمكن أن يتضمن بيانات، وأيضًا إجراءات/معالجات (actions/callbacks) لاستخدامها في نافذتك المنبثقة.
this.modal.show(MyModal, {
model: { topic: this.topic, someAction: this.someAction },
});
// `modal.show()` يعيد وعدًا (promise)، لذا يمكنك الانتظار حتى تُغلق
// سيُحل (resolve) بالبيانات المُمررة إلى إجراء `@closeModal`
const result = await this.modal.show(MyModal);
مزيد من القابلية للتخصيص! (More customizability!)
يحتوي <DModal> على عدد من الكتل والحجج المسمّاة.
الحجج (Arguments)
| الحجة | الغرض |
|---|---|
@closeModal |
مطلوب حتى تظهر واجهة الإغلاق (dismiss UI) على الإطلاق. |
@title |
يعرض <h1 id="discourse-modal-title">؛ يربط aria-labelledby. |
@subtitle |
نص صغير أسفل العنوان. |
@flash / @flashType |
تنبيه مضمّن في أعلى النافذة المنبثقة (DFlashMessage). |
@hideHeader, @hideFooter |
إخفاء المناطق بأكملها. |
@headerClass, @bodyClass |
فئة إضافية على أغلفة الترويسة/الجسم. |
@dismissable |
افتراضيًا true عند ضبط @closeModal. يعطّل Esc / النقر على الخلفية / X. |
@autofocus |
افتراضيًا true. يركّز تلقائيًا على أول عنصر قابل للتركيز عبر dTrapTab. |
@submitOnEnter |
افتراضيًا true. يُرسل Enter إلى .d-modal__footer .btn-primary ما لم يكن التركيز في نموذج / textarea / select-kit. |
@beforeClose |
async ({ initiatedBy }) => boolean. أعد false لإلغاء الإغلاق (مثل تأكيد النموذج المُعدّل). |
@hidden |
يوقف معالجة لوحة المفاتيح؛ يُستخدم عندما تكون نافذة منبثقة متداخلة في الأعلى. |
@tagName |
"div" (افتراضي) أو "form". استخدم "form" للنماذج حتى يعمل الإرسال الأصلي. |
الكتل (Blocks)
| الكتلة | الموقع | متى يُستخدم |
|---|---|---|
الافتراضية / :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 كمرجع لتجاوز النواة (core)، وتجنّب المحدد القديم .modal.
4 معدّلات (modifiers) متاحة:
- .
--largeيضبط العرض الحد الأقصى إلى 800 بكسل (للسطح المكتب فقط) - .
--maxيضبط العرض الحد الأقصى إلى 90vw (للسطح المكتب فقط) - .
has-searchيضبط الارتفاع الثابت (80vh): مخصص للنوافذ المنبثقة التي تحتوي على نظام بحث/تصفية لتجنب تغيير الارتفاع بناءً على طول النتائج (للسطح المكتب فقط) .--stackedيضبط أزرار التذييل لتكون متراكمة (للهاتف فقط)
هذا المستند مُدار بإصدار - اقترح تعديلات على github.

