ARIA وأنماط العناصر التفاعلية
WAI-ARIA مواصفة من W3C تخبر سماتُها (role وسمات aria-*) التقنياتِ المساعدة بماهية عنصر التحكم المخصص وحالته حين لا يوجد في HTML عنصر يؤدي دوره. فمكوّن التبويبات (Tabs) لا يقابله عنصر أصلي، لذلك يضع المطور role="tablist" على الحاوية، وrole="tab" على كل تبويب، وaria-selected="true" على التبويب الذي تظهر لوحته. ولا تغيّر ARIA إلا ما تكشفه شجرة إمكانية الوصول (Accessibility tree)؛ أما سلوك مفاتيح الأسهم الذي يتوقعه المستخدم من التبويبات فلا بد من كتابته بالشيفرة البرمجية.
ويصف دليل ممارسات تأليف ARIA (ARIA Authoring Practices Guide، ويُختصر APG) الصادر عن W3C كيف ينبغي أن تتصرف العناصر التفاعلية الشائعة: الأدوار والحالات والخصائص التي يحتاجها كل عنصر، والمفاتيح التي تشغّله. والنمط (Pattern) في APG هو بالنسبة إلى المختبِر نتيجة متوقعة جاهزة. ويحوّل هذا الدرس صفحات الأنماط إلى اختبارات لخمسة عناصر شائعة، وإلى عيوب تستند إلى النمط وإلى المعيار 4.1.2 من WCAG.
لماذا يهم
العناصر المخصصة (Custom widgets) من أسهل المواضع التي تتعطل فيها إمكانية الوصول في تطبيقات الويب الحديثة، لأن كل ما يقدمه العنصر الأصلي يجب أن يُعاد بناؤه يدوياً: الدور والاسم والحالة وحركة التركيز وكل مفتاح. فنافذة حوار يفلت منها التركيز إلى الصفحة التي خلفها، أو تبويبات لا تتغير حالة اختيارها أبداً، أو مربع تحرير وسرد لا يُعلَن فيه الخيار المميَّز، قد تمنع مستخدم لوحة المفاتيح أو قارئ الشاشة من إتمام عملية دفع أو نموذج. وهذه إخفاقات في معايير نجاح WCAG 2.2 مثل 4.1.2 الاسم والدور والقيمة (Name, Role, Value) و2.1.1 لوحة المفاتيح (Keyboard) و2.4.3 ترتيب التركيز (Focus Order)، وكلها من المستوى A.
وقد تكون ARIA الخاطئة أسوأ من غيابها: فالدور يَعِد بسلوك معيّن، وإذا غاب السلوك ضُلِّل المستخدم. وبالنسبة إلى المختبِر، تحوّل الأنماط ملاحظة غامضة مثل «التبويبات غير قابلة للوصول» إلى توقعات دقيقة قابلة للفحص يستطيع المطور العمل بها، وتساعد على الفصل بين إخفاقات WCAG الحقيقية والانحرافات عن عُرف متّبع.
ARIA في فقرة واحدة، والقاعدة الأولى
يشرح دليل اختبار قارئات الشاشة ARIA بالتفصيل؛ وهذه هي الخلاصة التي يبني عليها هذا الدرس. الأدوار (Roles) تقول ما هو العنصر (tab وdialog وmenu وcombobox). والحالات (States) أوضاع تتغير أثناء عمل المستخدم (aria-expanded وaria-selected وaria-checked). والخصائص (Properties) سمات وعلاقات أكثر ثباتاً (aria-label وaria-labelledby وaria-controls وaria-haspopup). ويُحسب الاسم القابل للوصول كما يصفه ذلك الدليل، مع تقدّم aria-labelledby وaria-label على غيرهما. وبعض الأدوار لا معنى لها إلا في سياقها: فالعنصر tab مكانه داخل tablist، وoption داخل listbox، وmenuitem داخل menu.
والقاعدة الأولى لاستخدام ARIA: إذا كان في HTML عنصر أو سمة أصلية فيها الدلالات والسلوك المطلوبان، فاستخدمها بدلاً من إضافة ARIA. فالعنصر <button> أفضل من <div role="button"> لأنه يقبل التركيز ويستجيب لـ Enter وSpace من تلقاء نفسه؛ والعنصران <details> و<summary> يقدّمان عنصر إفصاح جاهزاً؛ والعنصر <dialog> المفتوح بالدالة showModal() يجعل بقية الصفحة خاملة (inert). لذلك فأول سؤال في مراجعة أي عنصر مخصص: هل يحتاج إلى ARIA أصلاً؟ أما التبويبات وأزرار القوائم ومربعات التحرير والسرد ذات القوائم المخصصة فليس لها مقابل أصلي كامل، ولهذا تهمّ أنماطها المختبِرين.
كيف تقرأ صفحة نمط في APG
تتكوّن كل صفحة نمط في APG من الأجزاء نفسها، وكل جزء يتحول إلى نوع من الاختبارات. فاكتب النتائج المتوقعة قبل أن تفتح المنتج.
فمثلاً، يصبح مدخل Right Arrow في نمط التبويبات اختباراً بلوحة المفاتيح: ضع التركيز على تبويب، واضغط Right Arrow، وتوقّع انتقال التركيز إلى التبويب التالي، وعلى التبويب الأخير توقّع أن يلتفّ التركيز إلى الأول. ويصبح قسم الأدوار فحصاً في الشجرة: كل تبويب عنصر tab داخل tablist، ولا يحمل aria-selected="true" إلا التبويب الذي تظهر لوحته.
- About This Pattern (عن هذا النمط): الغرض من العنصر. طابِق العنصر بسلوكه لا بمظهره: فصفّ من الأزرار يبدّل اللوحات في مكانها هو تبويبات، وزر «عرض المزيد» عنصر إفصاح (Disclosure)، وقائمة روابط الموقع المنسدلة تنقّلٌ (Navigation) وليست
menu. - Keyboard Interaction (تفاعل لوحة المفاتيح): مدخل لكل مفتاح، وكل مدخل خطوة اختبار لها نتيجة متوقعة. والمفاتيح الموسومة «(Optional)»، مثل Home وEnd في التبويبات، ليست إلزامية، لكن إذا نفّذها المنتج وجب أن تعمل كما هو موصوف.
- WAI-ARIA Roles, States, and Properties (الأدوار والحالات والخصائص): الأدوار وأيّها يحتوي الآخر، والحالات التي يجب أن تتغير أثناء التشغيل، والخصائص التي تسمّي الأجزاء وتربط بينها. وكل سطر فحص في شجرة إمكانية الوصول. واقرأ الشروط بعناية: فعبارة «إذا كان لقائمة التبويبات تسمية مرئية» هي التي تحسم الاختيار بين
aria-labelledbyوaria-label. - Examples (الأمثلة): نماذج عاملة، لكل منها جدول لدعم لوحة المفاتيح وجدول للأدوار والخصائص والحالات وقيم
tabindex. ويكشف عمودtabindexأسلوب إدارة التركيز الذي يستخدمه المثال. - الخيارات التي يتركها النمط مفتوحة: التفعيل التلقائي أو اليدوي للتبويبات، والاتجاه الأفقي أو العمودي. اسأل الفريق أي صيغة اختار، وسجّلها في أساس الاختبار (Test basis)؛ وإلا فلن تستطيع التمييز بين العيب والقرار التصميمي.
تبويبان من صفحة الطلب، والأول هو المختار
<div الجزء 1:role="tablist" الجزء 2:aria-label="Order details"> <button الجزء 3:role="tab" id="t1" الجزء 4:aria-selected="true" الجزء 5:aria-controls="p1" الجزء 6:tabindex="0">Items</button> <button الجزء 3:role="tab" id="t2" الجزء 4:aria-selected="false" الجزء 5:aria-controls="p2" الجزء 6:tabindex="-1">Delivery</button> </div> <div الجزء 7:role="tabpanel" id="p1" الجزء 8:aria-labelledby="t1" الجزء 9:tabindex="0">…</div> <div الجزء 7:role="tabpanel" id="p2" الجزء 8:aria-labelledby="t2" الجزء 9:tabindex="0" الجزء 10:hidden>…</div>
- 1قائمة التبويباتتحتوي كل التبويبات؛ والقائمة كلها محطة Tab واحدة.
- 2اسم قائمة التبويباتالسمة
aria-labelledbyإذا وُجدت تسمية مرئية، وإلاaria-label. - 3دور tab على كل تبويبداخل tablist؛ والعنصر الأصلي
<button>يحتفظ بـ Enter وSpace. - 4حالة الاختيارقيمة
trueواحدة فقط، على التبويب الذي تظهر لوحته؛ تنتقل مع اللوحة ويُعلَن تغيّرها.4.1.2 - 5التبويب يشير إلى لوحتهالقيمة هي
idاللوحة. - 6tabindex المتنقلالتبويب المختار وحده في تسلسل Tab؛ ومع التفعيل التلقائي ينقل Left Arrow وRight Arrow التركيز والقيمة
0والاختيار معاً، ويلتفّان عند الطرفين. - 7لوحة التبويبلوحة واحدة لكل تبويب.
- 8اللوحة يسمّيها تبويبهامن يدخل اللوحة يسمع إلى أي تبويب تنتمي.
- 9اللوحة في تسلسل Tabضغطة Tab التالية بعد قائمة التبويبات تستقر هنا إذا لم يكن في أول محتوى اللوحة ما يقبل التركيز.
- 10اللوحة غير النشطة مخفيةخارج شجرة إمكانية الوصول وترتيب Tab حتى يُختار تبويبها.
المفاتيح: يدخل Tab القائمة عند التبويب المختار، وضغطة Tab التالية تنتقل إلى اللوحة؛ ويتنقل Left Arrow وRight Arrow بين التبويبات ويلتفّان؛ وHome وEnd اختياريان؛ وفي التفعيل اليدوي يُظهر Enter أو Space اللوحة.
التحقق من خمسة أنماط من البداية إلى النهاية
تحقّق من كل نمط في ثلاث جولات، لأن كل جولة تكشف عيوباً مختلفة. أولاً شجرة إمكانية الوصول في أدوات المطور (DevTools) في المتصفح: الدور والاسم والحالات قبل كل تفاعل وبعده. ثم لوحة المفاتيح وحدها: كل مفتاح في النمط، ومؤشر تركيز مرئي، والموضع الذي يستقر فيه التركيز عند فتح العنصر وإغلاقه. وأخيراً قارئ الشاشة: ما يُعلَن عند وصول التركيز، وهل يُعلَن كل تغيّر في الحالة. فقد يبدو العنصر سليماً في الشجرة ويُخفق مع لوحة المفاتيح، أو ينجح في الاثنتين ثم يُعلَن إعلاناً ضعيفاً لأن قارئات الشاشة تدعم الدور بدرجات مختلفة.
- نافذة الحوار المشروطة (Modal dialog). الشجرة: دور
dialogيسمّيه عنوانه المرئي، معaria-modal="true"في النافذة المخصصة، أو عنصر<dialog>أصلي مفتوح بالدالةshowModal(). لوحة المفاتيح: ينتقل التركيز إلى داخل النافذة عند فتحها، ويدور Tab وShift+Tab داخلها، ويغلقها Escape، ويعود التركيز إلى عنصر التحكم الذي فتحها. قارئ الشاشة: يُعلَن دور النافذة واسمها عند فتحها، ولا تتسرب القراءة بمفاتيح الأسهم إلى الصفحة التي خلفها. - الإفصاح والأكورديون (Disclosure وAccordion). الشجرة: عنصر
buttonتطابق قيمةaria-expandedفيه ما هو ظاهر؛ وفي الأكورديون يقع كل زر رأس داخل عنصر عنوان. لوحة المفاتيح: Enter وSpace يوسّعان القسم ويطويانه، ولا يصل Tab إلى المحتوى المطوي. قارئ الشاشة: تتحول «مطوي» (collapsed) إلى «موسَّع» (expanded) عند الضغط على الزر. - التبويبات (Tabs). الشجرة:
tablistله اسم؛ وعناصرtabتحملaria-controlsوaria-selected؛ وعناصرtabpanelيسمّيها تبويبها عبرaria-labelledby، واللوحات غير النشطة مخفية. لوحة المفاتيح: قائمة التبويبات محطة Tab واحدة تستقر على التبويب النشط؛ ويتنقل Left Arrow وRight Arrow بين التبويبات ويلتفّان عند الطرفين؛ وضغطة Tab التالية تدخل اللوحة، التي تأخذ هي نفسهاtabindex="0"إذا لم يكن في أول محتواها ما يقبل التركيز. وفي التخطيط من اليمين إلى اليسار، تحقّق من اتجاه الأسهم الذي سجّله فريقك. قارئ الشاشة: يُعلن كل تبويب اسمه ودوره وحالة اختياره، وغالباً موضعه، مثل 2 من 3. - زر القائمة (Menu button). الشجرة: عنصر
buttonيحملaria-haspopup، وaria-expanded="true"ما دامت القائمة مفتوحة، ويفتحmenuمن عناصرmenuitem. لوحة المفاتيح: Enter أو Space يفتح القائمة على أول عنصر فيها (وقد يفتحها Down Arrow أيضاً)، وUp Arrow وDown Arrow يتنقلان، وEnter يفعّل العنصر ويغلق القائمة، وEscape يغلقها ويعيد التركيز إلى الزر. قارئ الشاشة: يُعلن الزر أنه يفتح قائمة، ويُعلَن كل عنصر على أنه عنصر قائمة. - مربع التحرير والسرد (Combobox). الشجرة: لحقل الإدخال دور
combobox، واسم من تسميته، وaria-expandedتطابق حالة القائمة، وaria-controlsتشير إلىlistboxمن عناصرoption، وaria-activedescendantمضبوطة على معرّف الخيار المميَّز، الذي يحملaria-selected="true". لوحة المفاتيح: الكتابة تصفّي الخيارات، وDown Arrow يتنقل بينها بينما يبقى التركيز في الحقل، وEnter يقبل الخيار، وEscape يغلق القائمة. قارئ الشاشة: يُقرأ كل خيار مميَّز أثناء التنقل، وتبقى الكتابة ممكنة.
أسلوبا التركيز: tabindex المتنقل وaria-activedescendant
العناصر المركّبة (Composite widgets) مثل التبويبات والقوائم وصناديق القوائم والشبكات محطة Tab واحدة، ومفاتيح الأسهم تتنقل داخلها. ويصف APG طريقتين لبناء ذلك. في أسلوب tabindex المتنقل (Roving tabindex) يحمل العنصر الحالي tabindex="0" وكل عنصر آخر tabindex="-1"؛ ومع كل ضغطة سهم تنقل الشيفرة القيمة 0 إلى العنصر الجديد وتستدعي focus() عليه. فيتحرك تركيز DOM فعلاً، ويمرّر المتصفح العنصر إلى مجال الرؤية، وإذا غادر المستخدم العنصر بـ Tab ثم عاد، رجع التركيز إلى العنصر الذي تركه.
أما في أسلوب aria-activedescendant فيبقى تركيز DOM على عنصر واحد (الحاوية، أو حقل الإدخال في مربع التحرير والسرد)، وتضبط الشيفرة السمة على معرّف (id) العنصر النشط، فتعامله التقنيات المساعدة كأنه صاحب التركيز. وعلى الشيفرة أن ترسم مؤشر التركيز المرئي وأن تمرّر العنصر إلى مجال الرؤية بنفسها، لأن المتصفح لا يفعل أياً منهما. ويحتاج مربع التحرير والسرد إلى هذا الأسلوب ليواصل المستخدم الكتابة وهو يتنقل بين الخيارات.
ولتميّز بينهما، افتح لوحة Elements في أدوات المطور في Chrome أو Edge واضغط مفاتيح الأسهم، ولاحظ أي سمة تتغير. ثم أضف document.activeElement تعبيراً حياً (Live expression) عبر أيقونة العين أعلى Console، فيظل يُظهر أين يقع تركيز DOM فعلاً. ولكل أسلوب أعطال يمكن التعرف عليها:
- أسلوب tabindex المتنقل: تحتفظ عدة عناصر بالقيمة
tabindex="0"، فيمرّ Tab على كل تبويب بدلاً من الانتقال إلى اللوحة؛ أو لا يحمل أي عنصر القيمة0بعد إعادة الرسم، فلا يمكن الوصول إلى العنصر بـ Tab إطلاقاً (2.1.1). - أسلوب tabindex المتنقل: يحرّك مفتاح السهم التمييز المرئي لكن
focus()لا تُستدعى، فيبقى مؤشر التركيز وقارئ الشاشة على العنصر القديم. - أسلوب tabindex المتنقل: تبقى القيمة
0على العنصر الأول، فيعود Shift+Tab إلى تبويب غير التبويب المختار. - أسلوب
aria-activedescendant: تشير السمة إلى معرّف لم يعد موجوداً، وغالباً بعد تصفية القائمة وإعادة بنائها؛ فيتحرك التمييز ولا يقول قارئ الشاشة شيئاً. - أسلوب
aria-activedescendant: تتغير السمة لكن لا يُرسم أي تمييز، فلا يرى مستخدمو لوحة المفاتيح المبصرون موضعهم (ويُبلَّغ عنه عادةً تحت 2.4.7 Focus Visible)؛ أو يبقى الخيار النشط خارج مجال الرؤية. - أسلوب
aria-activedescendant: العنصر المشار إليه بلا دورoptionأوmenuitem، أو يقع خارج العنصر والقائمة التي يتحكم بها، فيُعلَن نصاً عادياً أو لا يُعلَن أصلاً.
مثال تطبيقي: اختبار تبويبات الطلب وكتابة العيوب
في صفحة طلب ثلاثة تبويبات: «المنتجات» و«التوصيل» و«الدفع». واختار الفريق أثناء التهذيب (Refinement) نمط التبويبات في APG مع التفعيل التلقائي، فصار ذلك أساس الاختبار. وتُنتج الجولات الثلاث أربع ملاحظات، تُصنَّف كل منها قبل الإبلاغ عنها.
عيب ARIA المفيد يسمّي المكوّن وصيغة النمط، ويذكر تسلسل المفاتيح بالضبط، ويصف الدور أو الاسم أو الحالة المتوقعة والفعلية كما تُظهرها الشجرة وكما يعلنها قارئ الشاشة، ولا يستشهد بمعيار WCAG إلا إذا أخفق المنتج فيه فعلاً. وفيما يلي الملاحظات الأربع مصنّفةً، ثم تقرير الملاحظة الثانية:
- الشجرة: الحاوية عنصر
<div>عادي، فتقع التبويبات الثلاثة تحت عقدة عامة (generic) بلا دورtablistوبلا اسم. وتشترط WAI-ARIA أن يكونtabداخلtablist؛ فالتجميع الذي يراه المستخدم غير مكشوف، وهذا إخفاق في 1.3.1 المعلومات والعلاقات (Info and Relationships)، وهو المعيار الذي تربطه به قاعدة ACT من W3C المسماة «ARIA required context role». - الشجرة وقارئ الشاشة: بعد Right Arrow إلى «التوصيل» تظهر لوحة التوصيل، لكن
aria-selected="true"تبقى على «المنتجات»، ولا يعلن قارئ الشاشة أن «التوصيل» مختار. فالحالة الظاهرة على الشاشة ليست الحالة المكشوفة: إخفاق في 4.1.2، بخطورة رئيسي (Major)، لأن المستخدم الكفيف لا يعرف أي لوحة يقرأ. - لوحة المفاتيح: كل تبويب يحمل
tabindex="0"، فيمرّ Tab على التبويبات الثلاثة قبل الوصول إلى اللوحة، ولا يفعل Right Arrow شيئاً على «الدفع» بدلاً من الالتفاف إلى «المنتجات». ومع ذلك يعمل كل تبويب من لوحة المفاتيح، فالمعيار 2.1.1 مستوفى: أبلغ عنه انحرافاً عن تفاعل لوحة المفاتيح في APG، بخطورة ثانوي (Minor)، ودون معيار WCAG. - الشجرة: للوحات دور
tabpanelلكن بلاaria-labelledby، فيدخل المستخدم اللوحة دون أن يسمع إلى أي تبويب تنتمي. وتشترط WAI-ARIA 1.2 اسماً للعنصر ذي الدورtabpanel، فأبلغ عنه استناداً إلى النمط وإلى WAI-ARIA، بخطورة ثانوي.
العنوان: تبويبات الطلب: حالة الاختيار تبقى على «المنتجات» بعد الانتقال إلى «التوصيل»
المكوّن: تبويبات تفاصيل الطلب، /orders/1042 · نمط APG Tabs، تفعيل تلقائي
البيئة: Windows 11 · Firefox · NVDA (الإصدارات في المرفق)
الخطوات: 1. انتقل بـ Tab إلى تبويب «المنتجات». 2. اضغط Right Arrow.
المتوقع: ينتقل التركيز واللوحة والاختيار إلى «التوصيل»:
aria-selected="true" على «التوصيل» و"false" على «المنتجات»؛
ويعلن قارئ الشاشة «التوصيل» تبويباً مختاراً.
الفعلي: تظهر لوحة «التوصيل»، لكن aria-selected="true" تبقى على «المنتجات»؛
ولا يعلن NVDA حالة الاختيار.
المعيار: WCAG 2.2 4.1.2 Name, Role, Value (المستوى A)
الخطورة: رئيسي (Major)
الدليل: لقطتا لوحة إمكانية الوصول قبل وبعد، ومقتطف DOMأخطاء شائعة
- إضافة ARIA حيث يكفي عنصر أصلي، ثم اختبار ARIA بدلاً من السؤال عن سبب وجودها. فالعنصر
<div role="button">يحتاج إلى قبول التركيز ومعالجة Enter وSpace، وهذا كله موجود في<button>. - الاكتفاء بالتحقق من وجود الأدوار. فالأدوار ثابتة، ومعظم العيوب حالات لا تتغير، مثل
aria-expandedوaria-selected، وتركيز لا يتحرك. افحص الشجرة قبل كل ضغطة مفتاح وبعدها. - عدّ كل اختلاف عن APG إخفاقاً في WCAG. فمعايير WCAG تشترط إمكانية التشغيل بلوحة المفاتيح وكشف الاسم والدور والقيمة، لا مفاتيح APG بعينها: والتبويبات التي تُشغَّل بـ Tab بدلاً من الأسهم تنحرف عن النمط، لكنها قد تستوفي 2.1.1.
- الثقة بالتمييز المرئي في عنصر يعتمد على
aria-activedescendant. فالتمييز والسمة يُضبطان كلٌّ على حدة، لذا تأكد أن السمة تشير إلى عنصر موجود له الدور الصحيح. - الاستشهاد بالمعيار 4.1.1 Parsing لعيوب ARIA في تدقيق وفق WCAG 2.2. فقد صنّفت WCAG 2.2 المعيار 4.1.1 متقادماً ومحذوفاً؛ استشهد بـ 4.1.2 أو 1.3.1 أو 2.1.1 بحسب ما يفقده المستخدمون فعلاً.
من منظور ضمان الجودة
في الفريق، مكان الحديث عن الأنماط قبل البناء. فعندما تُدخل قصة مستخدم (User story) عنصراً مخصصاً، اسأل هل يكفي عنصر أصلي، وإن لم يكفِ فأي نمط في APG وأي صيغة منه سيُتّبع. واكتب اسم النمط وصيغته في معايير القبول (Acceptance criteria)، ليشترك المصممون والمطورون والمختبِرون في نتيجة متوقعة واحدة، ويصبح جدول لوحة المفاتيح في النمط جزءاً من تعريف الإنجاز (Definition of Done).
وعند الاختبار، احتفظ بقائمة فحص لكل مكوّن مبنية من صفحة نمطه، ونفّذها في الجولات الثلاث، مسجلاً ثنائية المتصفح وقارئ الشاشة مع إصداراتهما. وأبلغ عن كل ملاحظة مع قاعدة النمط التي تكسرها، ومنفصلاً عنها معيار WCAG الذي تُخفق فيه إن وُجد، حتى يميّز الفرز (Triage) إخفاقات المطابقة من مشكلات الاتساق. وامنح مكوّنات نظام التصميم المشترك (Design system) أكبر قدر من الاهتمام: فمربع تحرير وسرد معطوب في المكتبة هو العيب نفسه في كل صفحة تستخدمه، وإصلاح واحد يعالجها جميعاً.
تمرين عملي
تحقق من مربع تحرير وسرد للمدينة وأبلغ عمّا يُخفق
في نموذج عنوان التوصيل حقل المدينة (City) مبنيّ على هيئة مربع تحرير وسرد قابل للكتابة، يتبع نمط Combobox في APG مع قائمة منبثقة من نوع listbox. وشيفرته عند تحميل الصفحة أدناه. وأثناء الاختبار بلوحة المفاتيح وقارئ الشاشة لاحظت: (1) يصل Tab إلى الحقل ويعلن قارئ الشاشة الاسم City ودور combobox؛ (2) كتابة "Da" تُظهر قائمة فيها مدينة واحدة هي Dammam، لكن aria-expanded تبقى "false"؛ (3) يميّز Down Arrow المدينة Dammam ويبقى التركيز في الحقل، لكن aria-activedescendant تُضبط على "opt-3" بينما لم تعد القائمة المعاد بناؤها تحتوي إلا <li id="opt-1" role="option">Dammam</li>، ولا يقول قارئ الشاشة شيئاً؛ (4) يضع Enter المدينة Dammam في الحقل ويغلق القائمة، ويغلق Escape القائمة حين تكون مفتوحة.
حدّد أسلوب إدارة التركيز الذي يستخدمه العنصر وكيف تتأكد منه. وصنّف كل ملاحظة ناجحة أو فاشلة، واذكر معيار WCAG أو قاعدة النمط لكل إخفاق، واكتب عنواناً لعيب عن كل إخفاق.
<label for="city">City</label>
<input id="city" role="combobox" aria-autocomplete="list"
aria-expanded="false" aria-controls="city-list">
<ul id="city-list" role="listbox" hidden>
<li id="opt-1" role="option">Riyadh</li>
<li id="opt-2" role="option">Jeddah</li>
<li id="opt-3" role="option">Dammam</li>
</ul>- اكتب الأدوار والحالات والخصائص التي يتوقعها نمط Combobox في APG لهذه الشيفرة.
- حدّد أسلوب التركيز من موضع بقاء تركيز DOM ومن السمة التي تتغير.
- قارن كل ملاحظة بقواعد لوحة المفاتيح والسمات في النمط.
- صنّف كل إخفاق: معيار WCAG، أو انحراف عن النمط فقط.
- اكتب لكل إخفاق عنوان عيب يسمّي المكوّن والحالة المعطوبة وأثرها.
إظهار الإجابة النموذجية
المتوقع لهذه الشيفرة (الخطوة 1): لحقل الإدخال دور combobox واسم مأخوذ من <label>؛ وقيمة aria-expanded هي "false" ما دامت القائمة مخفية و"true" ما دامت ظاهرة؛ وaria-controls تشير إلى listbox ذات المعرّف city-list المكوّنة من عناصر option؛ وaria-autocomplete="list" تطابق سلوك التصفية؛ وحين يُميَّز خيار تحمل aria-activedescendant معرّفه ويحمل الخيار نفسه aria-selected="true"؛ ويبقى تركيز DOM في حقل الإدخال.
الأسلوب: aria-activedescendant. فبينما يحرّك Down Arrow التمييز يبقى document.activeElement هو حقل الإدخال، ولا يتغير إلا السمة. وهذا ما يتوقعه النمط في مربع التحرير والسرد، فاختيار الأسلوب صحيح؛ أما تنفيذه فلا.
الملاحظتان 1 و4 ناجحتان: الاسم مأخوذ من <label>، والدور combobox، وEnter يقبل الخيار ويغلق القائمة، وEscape يغلق القائمة المفتوحة.
الملاحظة 2 فاشلة: يجب أن تكون قيمة aria-expanded هي "true" ما دامت القائمة ظاهرة، وإلا فلن يعرف مستخدمو قارئ الشاشة أن اقتراحات ظهرت؛ وتعدّ WAI-ARIA 1.2 السمة aria-expanded إلزامية للدور combobox. المعيار: WCAG 2.2 4.1.2 Name, Role, Value (الحالة غير مكشوفة). العنوان: «مربع المدينة: aria-expanded تبقى false بينما قائمة الاقتراحات ظاهرة».
الملاحظة 3 فاشلة: بعد التصفية تشير السمة إلى معرّف لم يعد موجوداً، فلا يوجد خيار نشط لدى التقنيات المساعدة ولا تُعلَن المدينة المميَّزة أبداً. وهذا إخفاق في 4.1.2 أيضاً، بخطورة رئيسي (Major) على الأقل، لأن المستخدم لا يسمع أي مدينة هو على وشك قبولها. العنوان: «مربع المدينة: المدينة المميَّزة لا تُعلَن؛ aria-activedescendant تشير إلى معرّف خيار محذوف بعد التصفية». واقترح معرّفات ثابتة لكل مدينة، أو تحديث السمة بعد كل إعادة رسم، وأعد الاختبار بعمليات تصفية تغيّر طول القائمة.
أسئلة شائعة
هل APG معيار يمكن أن يُخفق فيه المنتج؟
لا. APG إرشادات غير معيارية (Informative) من W3C تبيّن كيف تُطبَّق WAI-ARIA؛ أما WCAG 2.2 فهي المعيار الذي تُقاس به المطابقة. استخدم أنماط APG سلوكاً متوقعاً في حالات الاختبار، ولا تستشهد بمعيار WCAG إلا حين يفقد المستخدمون ما يشترطه، وأبلغ عن بقية الاختلافات عن النمط بوصفها عيوب اتساق أو قابلية استخدام.
هل تُفعَّل التبويبات عند وصول التركيز إليها أم عند Enter فقط؟
يصف APG الطريقتين. ويوصي بالتفعيل التلقائي حين يمكن إظهار اللوحة دون تأخير ملحوظ، وبالتفعيل اليدوي، بـ Enter أو Space، حين يكون إظهار اللوحة بطيئاً. وكلاهما صحيح إذا اختاره الفريق عن قصد وطبّقه باتساق، فسجّل الاختيار في معايير القبول.
أيهما أفضل: tabindex المتنقل أم aria-activedescendant؟
لا أفضلية عامة. فأسلوب tabindex المتنقل يحرّك التركيز الحقيقي، فيمرّر المتصفح إلى العنصر الذي عليه التركيز وينسّقه. وأسلوب aria-activedescendant يُبقي التركيز على عنصر واحد، وهذا ما يحتاجه مربع التحرير والسرد ليواصل المستخدم الكتابة. اختبر الأسلوب الذي يستخدمه العنصر مقابل علامات تعطّله الخاصة به.
هل ما زلت أحتاج إلى قارئ شاشة إذا بدت شجرة إمكانية الوصول سليمة؟
نعم، مع ثنائية واحدة على الأقل. فالشجرة تُظهر ما يكشفه المتصفح، أما ما يسمعه المستخدمون فلا يُظهره إلا قارئ الشاشة، بما في ذلك تغيّرات الحالة التي لا تُعلَن واختلاف قارئات الشاشة في دعم دور معيّن.
المراجع
- ARIA Authoring Practices Guide (APG)أنماط للعناصر الشائعة (التبويبات والقوائم ونوافذ الحوار والقوائم المنسدلة) مع تفاعل لوحة المفاتيح المتوقع واستخدام ARIA — المرجع الذي تُقارَن به المكونات المخصصة.
- Accessible Rich Internet Applications (WAI-ARIA) 1.2توصية W3C التي تعرّف أدوار ARIA وحالاتها وخصائصها — أي كيف تُعلن عناصر الواجهة المخصّصة معناها للتقنيات المساعدة.
- Web Content Accessibility Guidelines (WCAG) 2.2توصية W3C التي تحدد معايير النجاح القابلة للاختبار لإتاحة محتوى الويب، مرتّبةً تحت أربعة مبادئ وثلاثة مستويات مطابقة (A وAA وAAA).
- Understanding WCAG 2.2الشرح التوضيحي لكل إرشاد ومعيار نجاح في WCAG 2.2: الغرض، ومن يستفيد، والأمثلة والتقنيات (غير إلزامي).
تدرّب بأدوات متقن
تجميل HTML بمسافات بادئة صحيحة للعناصر المتداخلة، مع الحفاظ على كتل pre وscript وstyle.
ولّد حالات اختبار منظّمة (المعرّف والعنوان والشروط المسبقة والخطوات والنتيجة المتوقّعة والأولوية) من وصف الميزة وقائمة الحقول.
ولّد قائمة تحقق QA مخصّصة (وظيفية وواجهة مستخدم وAPI وأمان وأداء وإمكانية وصول وإصدار) لأي ميزة باستخدام الذكاء الاصطناعي من متقن.
حوّل الملاحظات الأولية إلى تقرير خطأ كامل: خطوات إعادة الإنتاج، والمتوقّع مقابل الفعلي، والبيئة، ودرجة الخطورة، وقائمة تحقق للمرفقات.
للتعمّق أكثر
تقدّمك في هذا الموضوع
سجّل الدخول لتتابع تقدّمك
علّم الموضوعات مكتملة، وتابع من حيث توقفت، وافتح امتحانات التخصص.