بناء مكون نخب

نظرة عامة أساسية حول كيفية إنشاء مكوِّن إشعار منبثق تكيّفي يمكن الوصول إليه.

أود في هذه المقالة أن أشارككم بالتفكير في كيفية إنشاء مكون الخبز المحمص. ندعوك لبدء العرض التوضيحي.

عرض توضيحي

إليك نسخة من هذه المشاركة على 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;
}

لقطة شاشة تعرض حجم مربّع أدوات مطوّري البرامج والمساحة المتروكة متراكبة على عنصر .gui-toast-container.

بالإضافة إلى وضع نفسها داخل إطار العرض، تُعد حاوية الخبز المحمص حاوية من الشبكة يمكنها محاذاة الخبز المحمص وتوزيعه. تظهر العناصر في منتصفها مجموعة تحتوي على justify-content وأن يتم توسيطها بشكل فردي باستخدام justify-items. يُرجى رمي gap قليلاً حتى لا تلمس رسائل الخبز المحمص.

.gui-toast-group {
  display: grid;
  justify-items: center;
  justify-content: center;
  gap: 1vh;
}

لقطة شاشة متراكبة على سطح شبكة CSS على مجموعة مستخدمي التطبيق المنبثق، هذه المرة
يسلط الضوء على المساحة والثغرات بين عناصر إشعار نخب الطفل.

واجهة المستخدم الرسومية الجديدة

نخب فردي يضم 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;
}

لقطة شاشة لعنصر .gui-toast واحد مع المساحة المتروكة والحدود
النطاق الجغرافي المعروض.

الأنماط

باستخدام تعيين التنسيق وتحديد الموضع، يمكنك إضافة 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')

إنشاء مجموعة الخبز المحمص

عند تحميل وحدة Toast من JavaScript، يجب أن تنشئ حاوية toast وإضافته إلى الصفحة. اخترتُ إضافة العنصر قبل 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 ترفع التنسيق. عند إضافة نخب جديد، تضعه الشبكة في البداية ويفصلها عن بعضها البعض. في الوقت نفسه، وتستخدم شبكة الصورة المتحركة هي يُستخدم لتحريك الحاوية من الموضع القديم.

وضع كل رموز 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() يفي بوعد "توست" عالي المستوى يمكن للمطوّرين حذف البيانات أو إجراء أي عمل آخر بمجرد أن يظهر الإشعار المنبثق.

export default Toast

وأخيرًا، يتم تصدير الدالة Toast من الوحدة، بالنسبة إلى النصوص البرمجية الأخرى إلى البيانات واستخدامها.

استخدام مكون Toast

يتم استخدام الخبز المحمص، أو تجربة مطور الخبز، عن طريق استيراد Toast وتسميها باستخدام سلسلة رسالة.

import Toast from './toast.js'

Toast('Wizard Rose added to cart')

إذا أراد المطور القيام بأي عمل تنظيف أو أي شيء، بعد أن تظهر، فيمكنها استخدام البيانات غير المتزامنة الانتظار.

import Toast from './toast.js'

async function example() {
  await Toast('Wizard Rose added to cart')
  console.log('toast finished')
}

الخاتمة

الآن بعد أن تعرّفت على كيفية إجراء ذلك، كيف يمكنك‽ 🙂

يمكننا تنويع أساليبنا وتعلُّم جميع طرق إنشاء المحتوى على الويب. أنشئ عرضًا توضيحيًا وأضيف روابط تغريدة إليّ. انتقِل إلى قسم الريمكسات في المنتدى أدناه.

ريمكسات من إنشاء المنتدى