{"id":"l-a11y-5-2","courseId":"web-accessibility","lang":"ar","kind":"lesson","summary":"اختبر Ticketly يدويًا بلوحة المفاتيح وNVDA وVoiceOver باستخدام أوامر التنقّل الأساسية، وتعرّف كيف تبدو الإعلانات الصحيحة، واكتب ملاحظات يستطيع المطوّرون العمل بها.","html":"<p>أخبرتك الأدوات الآلية بما ينقص Ticketly. أما لوحة المفاتيح وقارئ الشاشة فيخبرانك بما يعنيه استخدامه فعلًا. هذا هو الجزء من الاختبار الذي تتخطّاه معظم الفرق، وهو الجزء الذي يجد المشكلات التي يشتكي منها الناس حقًا. لا تحتاج إلى أن تصبح مستخدمًا خبيرًا لقارئ الشاشة. تحتاج إلى نحو خمسة عشر أمرًا وعادة الإصغاء بانتباه.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">جولة لوحة المفاتيح</h2>\n<p>ابدأ كل اختبار يدوي دون فأرة. انتقل من شريط العنوان إلى نهاية الصفحة بـ Tab، ثم عُد بـ Shift+Tab، واسأل عند كل محطة:</p>\n<ol>\n<li><strong>هل أستطيع الوصول إليه؟</strong> كل عنصر تحكّم تستطيع الفأرة استخدامه يجب أن يكون قابلًا للوصول.</li>\n<li><strong>هل أستطيع رؤيته؟</strong> التركيز مرئي بوضوح وغير مخفي خلف الأشرطة الثابتة.</li>\n<li><strong>هل الترتيب منطقي؟</strong> يتبع التركيز ترتيب قراءة الصفحة.</li>\n<li><strong>هل يعمل؟</strong> ‏Enter يتّبع الروابط ويفعّل الأزرار؛ وSpace يفعّل الأزرار ويبدّل مربّعات الاختيار؛ ومفاتيح الأسهم تعمل داخل أزرار الـ radio والتبويبات والقوائم.</li>\n<li><strong>هل أستطيع الخروج؟</strong> ‏Escape يُغلق نوافذ الحوار والقوائم، ويعود التركيز إلى العنصر الذي فتحها، ولا شيء يحبس التركيز.</li>\n</ol>\n<p>في Ticketly، وجدت هذه الجولة وحدها الـ tabindex الموجب، والتركيز غير المرئي، وزر الـ div، والنافذة المنبثقة التي تركت التركيز خلفها، قبل أن يفتح أحد قارئ شاشة.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">أيّ قارئات الشاشة تختبر</h2>\n<p>في استطلاع WebAIM لعام 2026، كانت قارئات الشاشة الأساسية الأكثر شيوعًا على أجهزة سطح المكتب <strong>JAWS</strong> ‏(55.0%) و<strong>NVDA</strong> ‏(32.9%)، وكلاهما على Windows، يليهما <strong>VoiceOver</strong> على macOS ‏(6.5%). وعلى الهاتف، يستخدم 72.2% من المشاركين <strong>VoiceOver</strong> على iOS، متقدّمًا بفارق كبير على <strong>TalkBack</strong> على Android ‏(29.5%). مصفوفة اختبار عملية:</p>\n<ul>\n<li><strong>NVDA مع Chrome أو Firefox</strong> على Windows. ‏NVDA مجاني ومفتوح المصدر، وسلوكه قريب بما يكفي من سلوك JAWS ليلتقط معظم المشكلات.</li>\n<li><strong>VoiceOver مع Safari</strong> على macOS، وهو مدمج في النظام.</li>\n<li><strong>VoiceOver على iOS</strong> لأي شيء يستخدمه الناس على الهواتف، وفي مهرجان يكاد يكون كل شيء كذلك.</li>\n</ul>\n<h2 id=\"sec-3\" tabindex=\"-1\">أساسيات NVDA</h2>\n<p>لـ NVDA وضعان. في <strong>وضع التصفّح (browse mode)</strong>، يقرأ NVDA الصفحة بمؤشّر افتراضي، والحروف المفردة تقفز بين العناصر. وفي <strong>وضع التركيز (focus mode)</strong>، تذهب ضغطات المفاتيح إلى عنصر التحكّم، فتستطيع الكتابة في حقل. يبدّل NVDA بينهما تلقائيًا حين تدخل حقلًا، وNVDA+Space يبدّل يدويًا. و<strong>مفتاح NVDA</strong> هو Insert افتراضيًا، ويمكنك أيضًا تفعيل Caps Lock مفتاحًا لـ NVDA، وهذا مريح على الحاسوب المحمول.</p>\n<div class=\"table-wrap\" role=\"region\" aria-label=\"جدول قابل للتمرير\" tabindex=\"0\"><table><thead>\n<tr>\n<th>الإجراء</th>\n<th>مفاتيح NVDA</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>تشغيل NVDA / إيقاف الكلام</td>\n<td>Ctrl+Alt+N / Ctrl</td>\n</tr>\n<tr>\n<td>القراءة من هنا</td>\n<td>NVDA+Down Arrow</td>\n</tr>\n<tr>\n<td>السطر أو العنصر التالي</td>\n<td>Down Arrow</td>\n</tr>\n<tr>\n<td>العنوان التالي / عنوان المستوى 2</td>\n<td>H / 2</td>\n</tr>\n<tr>\n<td>الـ landmark التالي</td>\n<td>D</td>\n</tr>\n<tr>\n<td>حقل النموذج / الزر / الرابط التالي</td>\n<td>F / B / K</td>\n</tr>\n<tr>\n<td>الجدول التالي، ثم التنقّل بين الخلايا</td>\n<td>T، ثم Ctrl+Alt+Arrows</td>\n</tr>\n<tr>\n<td>قائمة العناوين والروابط والـ landmarks</td>\n<td>NVDA+F7</td>\n</tr>\n</tbody>\n</table></div><p>أضِف Shift إلى أي أمر بحرف مفرد للعودة إلى الخلف.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">أساسيات VoiceOver ‏(macOS)</h2>\n<p>شغّل VoiceOver وأوقفه بـ <strong>Cmd+F5</strong>. و<strong>مفاتيح VO</strong> هي Control+Option. قبل أن تبدأ، افتح إعدادات Safari وفعّل <strong>“Press Tab to highlight each item on a webpage”</strong>؛ وإلا فسيتخطّى Tab الروابط في Safari وستبلّغ عن أخطاء غير موجودة.</p>\n<div class=\"table-wrap\" role=\"region\" aria-label=\"جدول قابل للتمرير\" tabindex=\"0\"><table><thead>\n<tr>\n<th>الإجراء</th>\n<th>مفاتيح VoiceOver</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>العنصر التالي / السابق</td>\n<td>VO+Right / VO+Left</td>\n</tr>\n<tr>\n<td>التفعيل</td>\n<td>VO+Space</td>\n</tr>\n<tr>\n<td>القراءة من هنا / إيقاف الكلام</td>\n<td>VO+A / Control</td>\n</tr>\n<tr>\n<td>العنوان التالي</td>\n<td>VO+Cmd+H</td>\n</tr>\n<tr>\n<td>الـ Rotor (العناوين، الروابط، الـ landmarks، عناصر النماذج)</td>\n<td>VO+U، ثم Left/Right للتبديل بين القوائم</td>\n</tr>\n</tbody>\n</table></div><p>على iOS، اسحب يمينًا ويسارًا للتنقّل بين العناصر، وانقر مرتين للتفعيل، وأدِر إصبعين على الشاشة لفتح الـ rotor.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>الاختبار بالقراءة من الأعلى إلى الأسفل فقط</span></p>\n<p>يضغط المختبِرون الجدد «اقرأ الكل» ويستمعون إلى الصفحة بأكملها. والمستخدمون الحقيقيون نادرًا ما يفعلون ذلك. اختبر بالطريقة التي يتنقّلون بها: اعرض قائمة العناوين، واقفز بين الـ landmarks، وتنقّل في النموذج بـ Tab، وافتح قائمة الروابط في الـ rotor. هناك تتّضح العناوين المفقودة، وأسماء “Book now” المكرّرة، والـ landmarks غير المسمّاة.</p>\n</aside>\n<h2 id=\"sec-5\" tabindex=\"-1\">كيف يبدو الصحيح</h2>\n<p>يجب أن يُعلَن كل عنصر تفاعلي مع <strong>اسم</strong> و<strong>دور</strong>، ومع <strong>حالة</strong> أو قيمة حين يكون ذلك مناسبًا. أصغِ إلى الجزء الناقص:</p>\n<div class=\"table-wrap\" role=\"region\" aria-label=\"جدول قابل للتمرير\" tabindex=\"0\"><table><thead>\n<tr>\n<th>ما تسمعه</th>\n<th>الحكم</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>“Book now Friday pass, button”</td>\n<td>اسم ودور: جيد</td>\n</tr>\n<tr>\n<td>“Save to wishlist, toggle button, not pressed”</td>\n<td>اسم ودور وحالة: جيد</td>\n</tr>\n<tr>\n<td>“edit text, blank”</td>\n<td>لا اسم: الحقل بلا label</td>\n</tr>\n<tr>\n<td>“Pay now” (ويتخطّاه Tab)</td>\n<td>لا دور، وغير قابل للتركيز: div قابل للنقر</td>\n</tr>\n<tr>\n<td>“graphic, IMG underscore 2041 dot jpeg”</td>\n<td>خاصية alt مفقودة</td>\n</tr>\n<tr>\n<td>“How do refunds work?, button” على disclosure</td>\n<td>لا حالة: aria-expanded مفقودة</td>\n</tr>\n</tbody>\n</table></div><p>وأصغِ أيضًا إلى ما لا يحدث: لا إعلان بعد إضافة تذكرة، ولا شيء يُقال حين تُفتح نافذة حوار، وخطأ يظهر بصمت.</p>\n<h2 id=\"sec-6\" tabindex=\"-1\">كتابة الملاحظات</h2>\n<p>الملاحظة التي يستطيع المطوّر إصلاحها دفعة واحدة لها ستة أجزاء:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">findings/ticketly-042.txt</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code>Title:    Quantity stepper buttons have no accessible name\nWhere:    /events/friday, Friday pass card\nSteps:    NVDA + Chrome. Tab to the &quot;−&quot; button after &quot;Quantity&quot;.\nActual:   NVDA says &quot;button&quot;. Same for &quot;+&quot;.\nExpected: &quot;Fewer Friday passes, button&quot; and &quot;More Friday passes, button&quot;.\nWCAG:     4.1.2 Name, Role, Value (A). Severity: high (blocks purchase).</code></pre></div>\n<aside class=\"callout callout-why\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><circle cx=\"12\" cy=\"12\" r=\"6\"/><circle cx=\"12\" cy=\"12\" r=\"2\"/></svg><span><span class=\"callout-kind\">لماذا يهمّ هذا</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>لماذا يهمّ هذا</span></p>\n<p>أن تختبر بالتقنيات المساعدة بنفسك ليس كالاختبار مع أشخاص ذوي إعاقة. يستخدم سمير NVDA بسرعة وبعادات لن تستطيع تقليدها في بضع ساعات. اختبارك الذاتي يلتقط العوائق الواضحة بتكلفة قليلة؛ أما جلسات اختبار قابلية الاستخدام المدفوعة مع مشاركين من ذوي الإعاقة فتجد الباقي، وتستحق أن تُخصَّص لها ميزانية مرة في السنة على الأقل.</p>\n</aside>\n<p>صار لديك كل ما تحتاجه من أدوات: الفحص الآلي، ولوحة المفاتيح، وقارئا شاشة. ويجمعها الدرس الأخير في تدقيق كامل لـ Ticketly، وفي عادات تُبقيه سهل الوصول بعد أن تغادر.</p>\n","toc":[{"id":"sec-1","text":"جولة لوحة المفاتيح","level":2},{"id":"sec-2","text":"أيّ قارئات الشاشة تختبر","level":2},{"id":"sec-3","text":"أساسيات NVDA","level":2},{"id":"sec-4","text":"أساسيات VoiceOver ‏(macOS)","level":2},{"id":"sec-5","text":"كيف يبدو الصحيح","level":2},{"id":"sec-6","text":"كتابة الملاحظات","level":2}],"takeaways":["جولة لوحة المفاتيح تتحقّق من إمكانية الوصول إلى كل عنصر، والترتيب، والتركيز المرئي، والتشغيل بـ Enter وSpace، والإغلاق بـ Escape للطبقات المنبثقة، وغياب المصائد.","اختبر NVDA مع Chrome أو Firefox على Windows، وVoiceOver مع Safari على macOS وiOS؛ ومعًا يغطّيان معظم الاستخدام الفعلي لقارئات الشاشة.","يتنقّل مستخدمو قارئ الشاشة عبر العناوين والـ landmarks والروابط وحقول النماذج، فاختبر بهذه الأوامر، لا بالقراءة من الأعلى فقط.","يجب أن يعطي كل إعلان اسمًا ودورًا وأي حالة موجودة؛ وغياب أي جزء من هذا الثلاثي خطأ."],"further":[{"title":"WebAIM: Using NVDA to Evaluate Web Accessibility","url":"https://webaim.org/articles/nvda/"},{"title":"WebAIM: Using VoiceOver to Evaluate Web Accessibility","url":"https://webaim.org/articles/voiceover/"},{"title":"WebAIM: Keyboard Accessibility","url":"https://webaim.org/techniques/keyboard/"},{"title":"W3C WAI: Easy Checks, A First Review of Web Accessibility","url":"https://www.w3.org/WAI/test-evaluate/preliminary/"}],"quiz":[{"q":"<p>تختبر Ticketly باستخدام NVDA في وضع التصفّح (browse mode). أيّ مفتاح يقفز إلى العنوان التالي؟</p>","options":[{"text":"H","why":"صحيح. في وضع التصفّح، الحروف المفردة تتنقّل بحسب نوع العنصر. وShift+H يعود إلى الخلف، ومن 1 إلى 6 تقفز إلى عنوان من ذلك المستوى."},{"text":"Tab","why":"ينتقل Tab بين العناصر القابلة للتركيز مثل الروابط والأزرار، ويتخطّى العناوين تمامًا."},{"text":"NVDA+F7","why":"هذا يفتح Elements List، وهي نافذة تعرض العناوين والروابط والـ landmarks وغيرها. مفيدة، لكنها ليست القفز بمفتاح واحد."},{"text":"D","why":"يقفز D إلى الـ landmark التالي، مثل main أو navigation، لا إلى العنوان التالي."}],"answer":0},{"q":"<p>في Safari على macOS مع تشغيل VoiceOver، يتخطّى Tab كل روابط Ticketly ولا يزور إلا حقول النماذج. ما الذي يحدث؟</p>","options":[{"text":"الروابط تنقصها خاصية href","why":"هذا ممكن في صفحة معطوبة، لكن كل الروابط هنا تعمل في المتصفّحات الأخرى. إنه إعداد في Safari، لا خطأ في الصفحة."},{"text":"لا يستطيع VoiceOver قراءة الروابط في Safari","why":"يقرأ VoiceOver الروابط في Safari جيدًا باستخدام VO+arrow keys والـ rotor. المشكلة في سلوك مفتاح Tab فقط."},{"text":"Safari لا يُدرج الروابط في ترتيب Tab افتراضيًا؛ فعّل “Press Tab to highlight each item” أو استخدم Option+Tab","why":"صحيح. فعّل هذا الإعداد قبل اختبار لوحة المفاتيح في Safari، وإلا فستبلّغ عن أخطاء غير موجودة."}],"answer":2},{"q":"<p>يصل التركيز إلى عنصر “Show more dates” في Ticketly فيقول NVDA ‏&quot;Show more dates, button&quot;. العنصر يكشف قائمة مخفية. ما الناقص؟</p>","options":[{"text":"لا شيء؛ الاسم والدور موجودان كلاهما","why":"في زر تبديل يُظهر المحتوى ويُخفيه، الحالة هي الجزء الثالث الذي يحتاجه المستخدمون. ومن دونها لا يعرفون إن كانت القائمة مفتوحة."},{"text":"الحالة، “collapsed” أو “expanded”، التي تأتي من aria-expanded","why":"صحيح. الاسم والدور والحالة معًا تخبر المستخدم ما هو عنصر التحكّم، وماذا يفعل، وما وضعه الحالي."},{"text":"وصف عبر aria-describedby يشرح أنه زر","why":"الدور يقول أصلًا إنه زر. والوصف سيكرّر ذلك بينما تبقى الحالة ناقصة."},{"text":"كلمة “link”، لأنه يكشف محتوى","why":"كشف المحتوى في مكانه فعلٌ، فالدور الصحيح هو button. والجزء الناقص هو الحالة."}],"answer":1}],"exercise":{"kind":"choice","multiple":true,"options":["div-pay","radio-group","blank-field","dialog-open","file-name","status-update","no-state"],"correct":["div-pay","blank-field","file-name","no-state"],"title":"أصغِ إلى صفحة الدفع في Ticketly","prompt":"<p>اختبرت صفحة الدفع في Ticketly باستخدام NVDA وChrome ودوّنت ما سمعته عند سبع نقاط. اختر <strong>كل إعلان يكشف خطأً</strong>. ولكل واحد منها، فكّر أيّ من الاسم والدور والحالة ناقص أو خاطئ.</p>\n","hints":["الإعلان الجيد فيه اسم ودور، وحالة حين يكون لعنصر التحكّم حالة.","أصغِ إلى ما هو ناقص: لا اسم، أو لا دور، أو لا حالة، أو اسم ملف حيث يجب أن يكون وصف.","أربعة من السبعة أخطاء."],"explanation":"<p>أربعة إعلانات تكشف أخطاء. “Pay now” بلا دور ويتخطّاه Tab هو div قابل للنقر: استخدم زرًّا. و&quot;edit text, blank&quot; حقل بلا label. و&quot;graphic, IMG underscore 2041 dot jpeg&quot; يعني أن الصورة بلا خاصية alt، فيلجأ قارئ الشاشة إلى اسم الملف. و&quot;How do refunds work?, button&quot; على عنصر للإظهار والإخفاء تنقصه حالته، فيجب إضافة aria-expanded. أما الثلاثة الأخرى فهي ما يبدو عليه الصحيح: مجموعة radio مسمّاة مع الموضع، ونافذة حوار مسمّاة تُعلن نفسها وأول حقل فيها، ورسالة حالة مهذّبة تُقرأ دون نقل التركيز.</p>\n","checkLabels":{},"optionText":{"div-pay":{"text":"عند قراءة الملخّص: “Pay now”. وينتقل Tab من حقل رقم البطاقة متجاوزًا إياه مباشرة إلى التذييل.","why":"خطأ. لا دور وغير قابل للتركيز: إنه div يتظاهر بأنه زر."},"radio-group":{"text":"عند الدخول بـ Tab إلى خيارات التذكرة: “Ticket type, grouping, Standing, radio button, checked, 1 of 2”.","why":"سلوك صحيح. الـ legend في الـ fieldset يسمّي المجموعة، ولزر الـ radio اسم ودور وحالة وموضعه."},"blank-field":{"text":"عند الانتقال بـ Tab إلى حقل البريد: “edit text, blank”.","why":"خطأ. الحقل بلا اسم متاح، فلا يعرف المستخدم ما يكتبه. يحتاج إلى label."},"dialog-open":{"text":"بعد ضغط Book now: “Book Friday pass, dialog, Quantity, spin button, 1”.","why":"سلوك صحيح. نافذة الحوار مسمّاة، وتُعلن نفسها، وانتقل التركيز إلى أول حقل فيها."},"file-name":{"text":"عند المرور بالأسهم على صورة المكان: “graphic, IMG underscore 2041 dot jpeg”.","why":"خطأ. الصورة بلا خاصية alt، فيقرأ NVDA اسم الملف. أضِف نصًا بديلًا ذا معنى، أو alt=“” إن كانت زخرفية."},"status-update":{"text":"بعد ضغط Add to basket، يبقى التركيز على الزر ويقول NVDA: “Ticket added. 2 tickets in your basket.”","why":"سلوك صحيح. أعلنت live region مهذّبة التحديث دون نقل التركيز."},"no-state":{"text":"على زر الأسئلة الشائعة الذي يُظهر إجابة ويُخفيها: “How do refunds work?, button”. والضغط عليه لا يغيّر شيئًا في الإعلان.","why":"خطأ. الـ disclosure يحتاج إلى aria-expanded ليسمع المستخدمون “collapsed” و&quot;expanded&quot;."}}},"words":766,"readMinutes":5}