نظرة عامة أساسية حول كيفية إنشاء مكوّن إشعار مؤقت متكيّف وسهل الاستخدام
في هذه المشاركة، أريد مشاركة أفكار حول كيفية إنشاء مكوّن إشعار منبثق. جرِّب العرض التوضيحي.
إذا كنت تفضّل مشاهدة فيديو، إليك نسخة من هذا المنشور على YouTube:
نظرة عامة
الإشعارات المنبثقة هي رسائل قصيرة غير تفاعلية وسلبية وغير متزامنة للمستخدمين. ويتم استخدامها بشكل عام كنمط ملاحظات على الواجهة لإعلام المستخدم بنتائج إجراء معيّن.
التفاعلات
تختلف الإشعارات المؤقتة عن الإشعارات والتنبيهات والطلبات لأنّها غير تفاعلية، أي لا يمكن إغلاقها أو الاحتفاظ بها. تُستخدَم الإشعارات لعرض معلومات أكثر أهمية أو رسائل متزامنة تتطلّب تفاعلاً أو رسائل على مستوى النظام (بدلاً من مستوى الصفحة). تكون الإشعارات المؤقتة أقلّ تفاعلاً من استراتيجيات الإشعارات الأخرى.
Markup
يُعدّ العنصر
<output>
خيارًا جيدًا لعرض الإشعارات المؤقتة لأنّه يتم الإعلان عنه لمستخدمي برامج قراءة الشاشة. يوفّر محتوى HTML الصحيح قاعدة آمنة يمكننا تعزيزها باستخدام JavaScript وCSS، وسيكون هناك الكثير من JavaScript.
إشعار منبثق
<output class="gui-toast">Item added to cart</output>
يمكن أن يكون أكثر
شمولاً
من خلال إضافة role="status"
. يوفّر ذلك خيارًا احتياطيًا في حال لم يمنح المتصفّح عناصر <output>
الدور الضمني وفقًا للمواصفات.
<output role="status" class="gui-toast">Item added to cart</output>
حاوية خبز محمص
يمكن عرض أكثر من إشعار واحد في الوقت نفسه. من أجل تنظيم إشعارات متعددة، يتم استخدام حاوية. يتعامل هذا الحاوية أيضًا مع موضع الإشعارات المؤقتة على الشاشة.
<section class="gui-toast-group">
<output role="status">Wizard Rose added to cart</output>
<output role="status">Self Watering Pot added to cart</output>
</section>
التنسيقات
لقد اخترتُ تثبيت الإشعارات المؤقتة في
inset-block-end
من مساحة العرض، وفي حال إضافة المزيد من الإشعارات المؤقتة، سيتم ترتيبها فوق بعضها بدءًا من حافة الشاشة.
حاوية واجهة المستخدم الرسومية
تتولّى حاوية الإشعارات المنبثقة جميع مهام التنسيق لعرض الإشعارات المنبثقة. يتم
تثبيت fixed
في إطار العرض، ويتم استخدام السمة المنطقية
inset
لتحديد
الحواف التي سيتم التثبيت عليها، بالإضافة إلى بعض padding
من حافة block-end
نفسها.
.gui-toast-group {
position: fixed;
z-index: 1;
inset-block-end: 0;
inset-inline: 0;
padding-block-end: 5vh;
}
بالإضافة إلى تحديد موضعها ضمن إطار العرض، فإنّ حاوية الإشعارات القصيرة هي حاوية شبكة يمكنها محاذاة الإشعارات القصيرة وتوزيعها. يتم توسيط العناصر كمجموعة باستخدام justify-content
، ويتم توسيطها بشكل فردي باستخدام justify-items
.
أضِف بعض gap
حتى لا تتلامس شرائح الخبز المحمّص.
.gui-toast-group {
display: grid;
justify-items: center;
justify-content: center;
gap: 1vh;
}
إشعار منبثق في واجهة المستخدم التصويرية
يحتوي الإشعار الفردي على بعض padding
، وبعض الزوايا الأكثر سلاسة مع
border-radius
،
ووظيفة min()
للمساعدة في تحديد الحجم على الأجهزة الجوّالة وأجهزة الكمبيوتر. يمنع الحجم المتجاوب في CSS التالي ظهور إشعارات أوسع من% 90 من إطار العرض أو 25ch
.
.gui-toast {
max-inline-size: min(25ch, 90vw);
padding-block: .5ch;
padding-inline: 1ch;
border-radius: 3px;
font-size: 1rem;
}
الأنماط
بعد ضبط التنسيق والموضع، أضِف CSS الذي يساعد في التكيّف مع إعدادات المستخدم وتفاعلاته.
حاوية الإشعارات
لا يمكن التفاعل مع الإشعارات المنبثقة، فالنقر عليها أو التمرير سريعًا لا يؤدي إلى أي إجراء، ولكنها تستهلك حاليًا أحداث المؤشر. يمكنك منع الإشعارات المنبثقة من حجب النقرات باستخدام رمز CSS التالي.
.gui-toast-group {
pointer-events: none;
}
إشعار منبثق في واجهة المستخدم التصويرية
امنح الإشعارات المظهر التكيّفي الفاتح أو الداكن مع خصائص مخصّصة، ونظام الألوان HSL، وطلب بحث عن الوسائط المفضّلة.
.gui-toast {
--_bg-lightness: 90%;
color: black;
background: hsl(0 0% var(--_bg-lightness) / 90%);
}
@media (prefers-color-scheme: dark) {
.gui-toast {
color: white;
--_bg-lightness: 20%;
}
}
Animation
يجب أن يظهر إشعار جديد مع مؤثر حركي عند دخوله إلى الشاشة.
يتم توفير خيار تقليل الحركة من خلال ضبط قيم translate
على 0
تلقائيًا، ولكن يمكن تعديل قيمة الحركة إلى طول في طلب بحث وسائط يتضمّن إعدادات مفضّلة للحركة . تظهر بعض الرسوم المتحركة للجميع، ولكن لا تظهر للبعض إلا إذا كانت المسافة التي تقطعها الرسالة القصيرة كبيرة.
في ما يلي إطارات المفاتيح المستخدَمة في الصورة المتحركة للإشعار المنبثق. ستتحكّم لغة CSS في ظهور الإشعار وتوقفه واختفائه، كل ذلك في صورة متحركة واحدة.
@keyframes fade-in {
from { opacity: 0 }
}
@keyframes fade-out {
to { opacity: 0 }
}
@keyframes slide-in {
from { transform: translateY(var(--_travel-distance, 10px)) }
}
بعد ذلك، يضبط عنصر الإشعار المتراكب المتغيرات وينسّق الإطارات الرئيسية.
.gui-toast {
--_duration: 3s;
--_travel-distance: 0;
will-change: transform;
animation:
fade-in .3s ease,
slide-in .3s ease,
fade-out .3s ease var(--_duration);
}
@media (prefers-reduced-motion: no-preference) {
.gui-toast {
--_travel-distance: 5vh;
}
}
JavaScript
بعد إعداد الأنماط ورمز HTML المتوافق مع برامج قراءة الشاشة، يجب استخدام JavaScript لتنظيم عملية إنشاء الإشعارات المنبثقة وإضافتها وإزالتها استنادًا إلى أحداث المستخدم. يجب أن تكون تجربة المطوّرين مع مكوّن الإشعارات المؤقتة بسيطة وسهلة الاستخدام، كما يلي:
import Toast from './toast.js'
Toast('My first toast')
إنشاء مجموعة الإشعارات المنبثقة والإشعارات المنبثقة
عندما يتم تحميل وحدة الإشعارات المنبثقة من JavaScript، يجب إنشاء حاوية إشعارات منبثقة وإضافتها إلى الصفحة. لقد اخترت إضافة العنصر قبل body
، ما يقلّل من احتمال حدوث مشاكل في التراكم لأنّ الحاوية تقع فوق حاوية جميع عناصر النص الأساسي.z-index
const init = () => {
const node = document.createElement('section')
node.classList.add('gui-toast-group')
document.firstElementChild.insertBefore(node, document.body)
return node
}
يتم استدعاء الدالة init()
داخليًا إلى الوحدة، ويتم تخزين العنصر
كـ Toaster
:
const Toaster = init()
يتم إنشاء عنصر HTML الخاص بالإشعارات باستخدام الدالة createToast()
. تتطلّب الدالة بعض النص لعرضه في الإشعار المؤقت، وتنشئ عنصر <output>
، وتضيف إليه بعض الفئات والسمات، وتضبط النص، ثم تعرض العقدة.
const createToast = text => {
const node = document.createElement('output')
node.innerText = text
node.classList.add('gui-toast')
node.setAttribute('role', 'status')
return node
}
إدارة إشعارات مؤقتة واحدة أو متعددة
تضيف JavaScript الآن حاوية إلى المستند لاحتواء الإشعارات المنبثقة، وهي جاهزة لإضافة الإشعارات المنبثقة التي تم إنشاؤها. تنسّق الدالة addToast()
عملية معالجة إشعار واحد أو عدة إشعارات. يتم أولاً التحقّق من عدد الإشعارات المنبثقة وما إذا كانت الحركة مناسبة،
ثم يتم استخدام هذه المعلومات إما لإضافة الإشعار المنبثق أو لتنفيذ بعض الرسوم المتحركة
الرائعة كي تبدو الإشعارات المنبثقة الأخرى وكأنّها "تفسح المجال" للإشعار المنبثق الجديد.
const addToast = toast => {
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Toaster.children.length && motionOK
? flipToast(toast)
: Toaster.appendChild(toast)
}
عند إضافة الإشعار الأول، تضيف Toaster.appendChild(toast)
إشعارًا إلى الصفحة يؤدي إلى تشغيل الصور المتحركة في CSS: الظهور، والانتظار 3s
، والاختفاء.
يتم استدعاء flipToast()
عندما تكون هناك إشعارات حالية، وذلك باستخدام أسلوب يُعرف باسم FLIP من بول
لويس. الفكرة هي حساب الفرق في مواضع الحاوية، قبل وبعد إضافة الإشعار الجديد.
يمكنك التفكير في الأمر على أنّه تحديد مكان المحمصة الآن، ومكانها المستقبلي، ثم تحريكها من مكانها الحالي إلى مكانها المستقبلي.
const flipToast = toast => {
// FIRST
const first = Toaster.offsetHeight
// add new child to change container size
Toaster.appendChild(toast)
// LAST
const last = Toaster.offsetHeight
// INVERT
const invert = last - first
// PLAY
const animation = Toaster.animate([
{ transform: `translateY(${invert}px)` },
{ transform: 'translateY(0)' }
], {
duration: 150,
easing: 'ease-out',
})
}
تتولّى شبكة CSS عملية إنشاء التصميم. عند إضافة إشعار جديد، يضعه Grid في البداية ويتركه متباعدًا عن الإشعارات الأخرى. في الوقت نفسه، يتم استخدام صورة متحركة على الويب لتحريك الحاوية من موضعها القديم.
تجميع كل JavaScript
عند استدعاء Toast('my first toast')
، يتم إنشاء إشعار مؤقت وإضافته إلى الصفحة (ربما يتم حتى تحريك الحاوية لاستيعاب الإشعار المؤقت الجديد)، ويتم عرض وعد، ويتم مراقبة الإشعار المؤقت الذي تم إنشاؤه لمعرفة ما إذا تم إكمال صورة CSS المتحركة (الصور المتحركة الثلاث ذات الإطارات الرئيسية) من أجل تنفيذ الوعد.
const Toast = text => {
let toast = createToast(text)
addToast(toast)
return new Promise(async (resolve, reject) => {
await Promise.allSettled(
toast.getAnimations().map(animation =>
animation.finished
)
)
Toaster.removeChild(toast)
resolve()
})
}
أعتقد أنّ الجزء المربك في هذا الرمز هو الدالة Promise.allSettled()
وعملية الربط toast.getAnimations()
. بما أنّني استخدمتُ عدة رسوم متحركة بإطارات مفتاحية
لإظهار الإشعار، وللتأكّد من أنّها انتهت جميعًا، يجب طلب كل منها من JavaScript ومراقبة
finished
الوعود الخاصة بكل منها للتأكّد من اكتمالها.
allSettled
يعمل ذلك لصالحنا، حيث يتم حلّه تلقائيًا على أنّه مكتمل بعد استيفاء جميع الوعود. يعني استخدام await Promise.allSettled()
أنّه يمكن لسطر الرمز التالي إزالة العنصر بثقة وافتراض أنّ الإشعار قد أكمل دورة حياته. أخيرًا، يؤدي استدعاء resolve()
إلى تنفيذ وعد Toast على مستوى عالٍ، ما يتيح للمطوّرين إمكانية تنظيف الذاكرة أو تنفيذ مهام أخرى بعد عرض الإشعار.
export default Toast
أخيرًا، يتم تصدير الدالة Toast
من الوحدة النمطية، لكي تستوردها النصوص البرمجية الأخرى وتستخدمها.
استخدام مكوّن Toast
يتم استخدام الإشعار اللحظي أو تجربة المطوّر للإشعار اللحظي من خلال استيراد الدالة Toast
واستدعائها باستخدام سلسلة رسائل.
import Toast from './toast.js'
Toast('Wizard Rose added to cart')
إذا أراد المطوّر إجراء عملية تنظيف أو أي شيء آخر بعد ظهور الإشعار، يمكنه استخدام async وawait.
import Toast from './toast.js'
async function example() {
await Toast('Wizard Rose added to cart')
console.log('toast finished')
}
الخاتمة
بعد أن عرفت كيف فعلتُ ذلك، كيف ستفعل أنت ذلك؟ 🙂
لنستكشف الطرق المختلفة لإنشاء مواقع إلكترونية على الويب. يمكنك إنشاء عرض توضيحي، إرسال تغريدة إليّ تتضمّن رابطًا إليه، وسأضيفه إلى قسم "ريمكسات من المنتدى" أدناه.
ريمكسات من إنشاء المنتدى
- @_developit باستخدام HTML/CSS/JS: العرض التوضيحي والرمز
- Joost van der Schee باستخدام HTML/CSS/JS: العرض التوضيحي والرمز