0Pricing
React Academy · درس

التعامل مع التركيز ومصائد لوحة المفاتيح في النوافذ المنبثقة

حافظوا على التركيز داخل النوافذ المنبثقة المفتوحة لإتاحة الوصول باستخدام useRef ومستمعات الأحداث

التعامل مع التركيز ومصائد لوحة المفاتيح في النوافذ المنبثقة درس مجاني في React Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في React Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة React Academy 4 دروس في المجموع.

مرحبًا

ستنفّذ في هذا الدرس حصرًا للتركيز داخل نافذة منبثقة، بحيث لا يستطيع مستخدمو لوحة المفاتيح الانتقال باستخدام Tab إلى خارج النافذة المفتوحة — وهو متطلب أساسي لإمكانية الوصول (WCAG 2.4.3).

لماذا تُطلب مصائد التركيز؟

عند فتح نافذة منبثقة، يجب أن يتمكن مستخدمو لوحة المفاتيح من التفاعل مع محتوى النافذة فقط. ومن دون مصيدة تركيز، يؤدي الضغط على Tab إلى نقل التركيز إلى العناصر الموجودة خلف طبقة النافذة — وهي عناصر مخفية بصريًا، لكنها لا تزال قابلة للوصول.

ما المقصود بمصيدة التركيز؟

تعترض مصيدة التركيز أحداث مفتاحي Tab وShift+Tab، وعندما يغادر التركيز النافذة، تعيده إلى أول عنصر قابل للتركيز أو آخر عنصر قابل للتركيز داخلها.

العثور على العناصر القابلة للتركيز

استخدم querySelectorAll مع محدد يغطي جميع العناصر التفاعلية. واستبعد العناصر المعطّلة والمخفية.
const FOCUSABLE = [
  'a[href]', 'button:not([disabled])',
  'input:not([disabled])', 'select', 'textarea',
  '[tabindex]:not([tabindex="-1"])'
].join(',');

const focusable = Array.from(
  modalRef.current.querySelectorAll(FOCUSABLE)
);

تنفيذ المصيدة

استمع إلى حدث keydown على حاوية النافذة. عند الضغط على Tab، إذا كان التركيز على العنصر الأخير، فانقله إلى العنصر الأول. وعند الضغط على Shift+Tab، إذا كان التركيز على العنصر الأول، فانقله إلى العنصر الأخير.
function handleTab(e) {
  const focusable = /* array of focusable elements */;
  const first = focusable[0];
  const last = focusable[focusable.length - 1];
  if (e.key !== 'Tab') return;
  if (e.shiftKey) {
    if (document.activeElement === first) {
      e.preventDefault(); last.focus();
    }
  } else {
    if (document.activeElement === last) {
      e.preventDefault(); first.focus();
    }
  }
}

نقل التركيز عند الفتح

عند فتح النافذة، انقل التركيز إلى أول عنصر قابل للتركيز داخلها (أو إلى حاوية النافذة نفسها باستخدام `tabIndex=-1`). ويمنع ذلك بقاء التركيز على الزر الذي فتح النافذة.
useEffect(() => {
  if (isOpen) {
    const first = modalRef.current?.querySelector(FOCUSABLE);
    first?.focus();
  }
}, [isOpen]);

استعادة التركيز عند الإغلاق

عند إغلاق النافذة، أعد التركيز إلى العنصر الذي كان نشطًا قبل فتحها. خزّن مرجعًا إلى `document.activeElement` في وقت فتح النافذة.
const previousFocus = useRef(null);

useEffect(() => {
  if (isOpen) {
    previousFocus.current = document.activeElement;
  } else {
    previousFocus.current?.focus();
  }
}, [isOpen]);

استخدام مكتبة focus-trap-react

للاستخدام في بيئة الإنتاج، فكّر في استخدام مكتبة **focus-trap-react**. فهي تتعامل مع جميع الحالات الخاصة: Shadow DOM وiframes والعناصر القابلة للتركيز المضافة ديناميكيًا وإلغاء التفعيل عند الضغط على Escape.
import FocusTrap from 'focus-trap-react';

{isOpen && (
  <FocusTrap>
    <div role="dialog" aria-modal="true">
      {children}
    </div>
  </FocusTrap>
)}

سمات ARIA للنوافذ المنبثقة

أضف `role="dialog"` و`aria-modal="true"` إلى حاوية النافذة. وأضف `aria-labelledby` يشير إلى عنوان النافذة. ويخبر ذلك قارئات الشاشة بأن مربع الحوار نافذة منبثقة، ويجعلها تعلن عنه بشكل صحيح.
<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="modal-title"
>
  <h2 id="modal-title">Confirm Delete</h2>
  ...
</div>

السمة inert للخلفية

تزيل سمة HTML `inert` على حاوية ما جميع عناصرها من ترتيب التركيز ومن إمكانية الوصول عبر قارئات الشاشة. اضبط `document.getElementById('root').inert = true` أثناء فتح النافذة لمنع الوصول إلى الخلفية بشكل متين.
useEffect(() => {
  const root = document.getElementById('root');
  if (isOpen) root.setAttribute('inert', '');
  else root.removeAttribute('inert');
}, [isOpen]);

تحقق سريع

ما الذي يجب أن يحدث عندما يضغط مستخدم لوحة مفاتيح على Tab أثناء وجود التركيز على آخر عنصر قابل للتركيز داخل نافذة تطبّق مصيدة التركيز؟

مراجعة

نفّذت مصيدة تركيز: عثرت على العناصر القابلة للتركيز، واعترضت Tab/Shift+Tab، ونقلت التركيز عند الفتح، واستعدت التركيز عند الإغلاق. استخدم focus-trap-react في بيئة الإنتاج، وأضف role='dialog' وaria-modal لقارئات الشاشة.

التالي

الدرس التالي: **التلميحات والقوائم المنسدلة باستخدام Portals** — ستعرض التلميحات والقوائم المنسدلة التي تتجاوز الحاويات ذات overflow-hidden باستخدام createPortal.

الأسئلة الشائعة

هل درس «التعامل مع التركيز ومصائد لوحة المفاتيح في النوافذ المنبثقة» مجاني؟

نعم — نص درس «التعامل مع التركيز ومصائد لوحة المفاتيح في النوافذ المنبثقة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة React Academy، انتقل إلى CoddyKit PRO. تتضمن دورة React Academy 4 دروس في المجموع.

ماذا ستتعلم في «التعامل مع التركيز ومصائد لوحة المفاتيح في النوافذ المنبثقة»؟

حافظوا على التركيز داخل النوافذ المنبثقة المفتوحة لإتاحة الوصول باستخدام useRef ومستمعات الأحداث تتمرن على React Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ React Academy؟

لا تُشترط خبرة سابقة. React Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «التعامل مع التركيز ومصائد لوحة المفاتيح في النوافذ المنبثقة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس React Academy هذا؟

نعم. كل درس في React Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. ما هي React Portals؟
  2. إنشاء مكوّن Modal باستخدام Portals
  3. التعامل مع التركيز ومصائد لوحة المفاتيح في النوافذ المنبثقة
  4. التلميحات والقوائم المنسدلة باستخدام Portals
← العودة إلى React Academy