פיתוח אפליקציות נגישות יותר של Angular

1. לפני שמתחילים

לוגו שחור של Angular

נגישות היא חלק חיוני בפיתוח אתרים. היא מבטיחה שהמשתמשים יוכלו לראות את האפליקציות, להבין אותן, לנווט בהן וליצור איתן אינטראקציה. למעשה, לאחד מכל ארבעה מבוגרים בארה"ב יש מוגבלות שמשפיעה על הפעילויות העיקריות בחיים שלהם. ברחבי העולם, לכ-15% מאוכלוסיית העולם – יותר ממיליארד אנשים – יש מוגבלות כלשהי, וכ-2% עד 4% מהאוכלוסייה סובלים מקשיים משמעותיים.

מצבים נפוצים שמשפיעים על השימוש של אנשים באינטרנט כוללים עיוורון או לקות ראייה, חירשות או לקות שמיעה, מיומנויות מוטוריות מוגבלות, לקויות קוגניטיביות ועיוורון צבעים – וזו רק רשימה חלקית.

בקורס הזה, a11y הוא קיצור של המילה accessibility (נגישות). שימו לב שאחרי a מופיעים 11 תווים ואז y.

לקבלת מבוא מעמיק לבעיות ולטכניקות לעיצוב אפליקציות נגישות, אפשר לעיין במאמר בנושא נגישות.

מה תפַתחו

  • שימוש בשיטות מומלצות ובטכניקות מובנות כדי לפתור בעיות נפוצות של נגישות לאתרים באפליקציית הדגמה של חנות דמפלינג ב-Angular
  • עמידה בכל הנחיות הנגישות, WCAG 2.0 ו-ARIA 1.2, ועמידה בביקורות הנגישות של axe ו-Lighthouse.

אתר החנות של Dumpling Time עם עיצוב ורוד ואדום אתר החנות של Dumpling Time בעיצוב סגול וירוק

מה תלמדו

במאמר הזה נסביר על שמונה בעיות נפוצות בנגישות באפליקציות Angular שמשפיעות על המשתמשים, איך לזהות אותן ואיך לפתור אותן. באופן ספציפי יותר, אתם:

  • שימוש ב-הכלים למפתחים ב-Chrome, ב-Lighthouse וב-axe כדי לבדוק את הנגישות של האפליקציה
  • פתרון בעיות באפליקציות בדף יחיד (SPA) באמצעות כותרות דפים ייחודיות
  • תיקון בעיות של ניגודיות צבעים נמוכה למשתמשים עם ליקויי ראייה
  • שימוש ב-HTML סמנטי כדי לוודא שקוראי המסך מנווטים בדף בצורה נכונה
  • שימוש ב-Angular Material והסרת הקינון של רכיבי בקרה כדי לוודא שקוראי מסך יכולים לגשת לכל רכיבי הבקרה
  • הוספת תמיכה ב-ARIA לקוראי מסך
  • ייבוא של חבילת הנגישות של Angular CDK ושימוש בה
  • שימוש ב-FocusTrap לניווט בקורא מסך ברכיב בהתאמה אישית
  • הכרזה על התראות באמצעות CDK LiveAnnouncer
  • זיהוי משתמשים עם מצב ניגודיות גבוהה והטמעה של ערכות נושא עם ניגודיות גבוהה

מה תצטרכו

2. להגדרה

לקבלת הקוד

כל מה שצריך לפרויקט הזה נמצא במאגר GitHub. כדי להתחיל, משכפלים את הקוד ופותחים אותו בסביבת הפיתוח המועדפת.

שיבוט המאגר והצגת האפליקציה

השיטה המומלצת לביצוע ה-codelab הזה היא באמצעות VSCode או סביבת פיתוח משולבת (IDE) מקומית.

  1. פותחים כרטיסייה חדשה בדפדפן ועוברים אל https://github.com/googlecodelabs/angular-accessibility.
  2. מבצעים Fork ושכפול של המאגר, ומעבירים את cd angular-accessibility/ למאגר.
  3. כדאי לעיין בענף קוד לתחילת הדרך git checkout get-started.
  4. פותחים את הקוד ב-VSCode או בסביבת הפיתוח המשולבת (IDE) המועדפת.
  5. מריצים את הפקודה npm install כדי להתקין את התלות שנדרשת להרצת השרת.
  6. מריצים את הפקודה ng serve כדי להפעיל את השרת.
  7. פותחים כרטיסייה בדפדפן ועוברים אל http://localhost:4200.

3. הגדרת ערך בסיס

מה נקודת ההתחלה שלך?

נקודת ההתחלה שלכם היא אפליקציית מסעדה בסיסית שנוצרה במיוחד בשביל ה-codelab הזה. הקוד פושט כדי להציג את המושגים ב-codelab הזה, והפונקציונליות שלו מוגבלת.

אתר החנות של Dumpling Time בעיצוב סגול וירוק

לצפייה בהדגמה

כדי להתחיל, כדאי להכיר את שלוש הפונקציות של האפליקציה:

  1. משתמשים בסרגל הניווט כדי להציג את המסלולים החנות שלנו, הסיפור שלנו ואיפה אנחנו, ורואים פרטים על חברת הכופתאות.
  2. אפשר לשנות את העיצוב כדי להפעיל או להשבית את המצב הבהיר או הכהה.
  3. מתאימים אישית את המילוי, הכמות והצבע של הכיסונים בהזמנה.
  4. בוחרים באפשרות רכישה כדי לרשום את ההזמנה המותאמת אישית במסוף.

שימוש ב-Angular כדי לפתור בעיות נפוצות בנגישות לאינטרנט

ב-codelab הזה תתמקדו בנגישות של התכונות הקיימות באפליקציה הזו. תתחילו בזיהוי בעיות נגישות באפליקציה, ואז תהפכו את 🛑 ל-✅ על ידי הטמעת פתרון.

איך יודעים מה צריך לתקן?

מתחילים כל דוגמה בזיהוי בעיית הנגישות באמצעות שילוב של בדיקות ידניות ואוטומטיות.

במצב הנוכחי של האינטרנט, חובה לבדוק את הנגישות באופן ידני.

יש לכם כלים שיכולים לזהות בעיות נגישות, אבל אין כלי שיכול לאשר שאפליקציה נגישה באופן מלא. בדיקות ידניות מאפשרות לבדוק מגוון רחב של מושגי נגישות, כולל סדר תוכן לוגי ושוויון בין תכונות.

בדיקה ידנית

כדי לבדוק את הנגישות בקורס הזה באופן ידני, מפעילים את קורא המסך המובנה במחשב ומנווטים באפליקציה באמצעות המקלדת. מידע נוסף זמין במאמר בנושא סמנטיקה וקוראי מסך.

כדאי לתרגל את השימוש בקורא המסך כדי להבין איך לנווט במסך.

אפשר להשתמש ב-VoiceOver המובנה ב-MacOS. לוחצים על העדפות מערכת > נגישות > VoiceOver > הפעלת VoiceOver. כדי להפעיל או להשבית את VoiceOver, לוחצים במהירות שלוש פעמים על TouchID תוך כדי לחיצה על המקש Command.

בקורס הזה, אתם בודקים בעיקר בעיות באופן ידני, ומשתמשים בכלים אוטומטיים כדי לבדוק תכונות ספציפיות שאפשר להפוך לאוטומטיות.

בדיקות אוטומטיות

אתם גם משתמשים בכמה כלים לפיתוח כדי לבצע אוטומציה של האפליקציה ולבדוק אותה. הכלים האלה מאפשרים לכם לבדוק דברים כמו נוכחות של טקסט חלופי בתמונה או יחס הניגודיות של צבע הטקסט. אפשר לחשוב על הכלים האלה כעל כלי ניתוח סטטיים (linters). הם יכולים לזהות שקיים טקסט חלופי, אבל אתם צריכים לבדוק באופן ידני שהתוכן הגיוני ושימושי.

‫Lighthouse והכלים למפתחים ב-Chrome

  1. פותחים את הכלים למפתחים ב-Chrome.
  2. בוחרים בכרטיסייה Lighthouse ומסמנים את תיבת הסימון Accessibility (נגישות).
  3. לוחצים על יצירת דוח כדי להריץ ביקורת נגישות של Lighthouse.

דוגמה לכרטיסייה של Lighthouse עם לחצן ליצירת דוח בכרטיסייה של כלי הפיתוח ל-Chrome

Axe

  1. מתקינים את התוסף axe DevTools. יכול להיות שתצטרכו להפעיל מחדש את הדפדפן כדי לראות את התוסף.
  2. פותחים את הכלים למפתחים ב-Chrome.
  3. בוחרים בכרטיסייה axe DevTools ואז באפשרות Scan all of my page כדי להריץ סריקה של axe DevTools.

איתור שגיאות בקוד (linting)

אתם יכולים להשתמש בכללי Angular ESLint כדי לבצע בדיקת קוד (linting) של מאפייני נגישות שאפשר להפוך לאוטומטיים.

ב-eslint.json, מוסיפים את ההגדרות הבאות שקשורות לנגישות:

"@angular-eslint/template/accessibility-alt-text": 2,
"@angular-eslint/template/accessibility-elements-content": 2,
"@angular-eslint/template/accessibility-label-for": 2,
"@angular-eslint/template/no-positive-tabindex": 2,
"@angular-eslint/template/accessibility-table-scope": 2,
"@angular-eslint/template/accessibility-valid-aria": 2,
"@angular-eslint/template/click-events-have-key-events": 2,
"@angular-eslint/template/mouse-events-have-key-events": 2,
"@angular-eslint/template/no-autofocus": 2,
"@angular-eslint/template/no-distracting-elements": 2

מידע נוסף זמין בכללי ESLint העדכניים ב-GitHub.

נקודת ההתחלה

באמצעות שיטות הבדיקה החדשות, תוכלו לזהות את הבעיות הבאות באפליקציה באמצעות ביקורות של Lighthouse ו-axe, ו-VoiceOver ידני:

ביקורת Lighthouse בכלי הפיתוח ל-Chrome עם ציון של 82

ביקורת נגישות:

  • 🛑 לכל הדפים יש את אותה כותרת דף
  • 🛑 הניגודיות בין הצבעים של הרכיבים צריכה להיות מספקת
  • ‫🛑 HTML צריך להיות מסודר בסדר הגיוני, לכלול שם ותפקיד
  • 🛑 אי אפשר לסמן תיבות סימון מוטמעות בקוראי מסך
  • 🛑 קורא המסך לא קורא את הערכים של פס ההזזה
  • ‫🛑 המיקוד של קורא המסך בכלי לבחירת צבעים יוצא מתיבת הדו-שיח
  • 🛑 לא מתקבלות הודעות על שינויים, שגיאות והתראות
  • ‫🛑 מצב הניגודיות הגבוהה לא מופעל

4. הגדרת כותרות ייחודיות לדפים

כותרות דפים ייחודיות ותמציתיות עוזרות למשתמשים בשירותי נגישות להבין במהירות את התוכן והמטרה של דף אינטרנט. כותרות הדפים חשובות מאוד למשתמשים עם ליקויי ראייה, כי הן רכיב הדף הראשון שתוכנת קריאת המסך מכריזה עליו.

‫Angular היא אפליקציה של דף יחיד, ולכן רוב המעברים, כמו מעבר לדף חדש, לא כוללים טעינה מחדש של הדף. עד לאחרונה, המשמעות הייתה שלכל דף הייתה כותרת דף זהה, ולא היה אפשר להבין ממנה את התוכן או המטרה של הדף.

ב-Angular v14, הנתב הוסיף שיטה מובנית להגדרת שמות דפים ייחודיים. כך אפשר לוודא שהמפתחים פועלים לפי השיטות המומלצות לכותרות דפים.

בסיום הקטע הזה, האפליקציה שלכם תעבור את הביקורת הבאה:

  • 🛑 לכל הדפים יש את אותה כותרת דף

כל אחד מהשלבים האלה מופיע מתחת לתגובה: TODO: #4. Define unique page titles.

זיהוי הבעיה

כדי לזהות את הבעיה הזו, מפעילים את קורא המסך ועוברים בין הכרטיסיות החנות שלנו, הסיפור שלנו ואיפה אנחנו כדי לראות את שמות הדפים:

  1. מפעילים את VoiceOver.
  2. אפשר להשתמש בניווט באמצעות מקש Tab כדי לעבור בין דפים.
  3. מוודאים שכותרת הדף תמיד נגישה ב-Angular.

זו בעיה כי כותרת הדף צריכה להיות ייחודית כדי שהמשתמש יוכל להבין במהירות על מה הדף בלי לנווט בו.

דפדפן Chrome עם שלוש כרטיסיות פתוחות עם אותו שם דף: 'a11y in Angular'

הוספת שמות משמעותיים לדפים

אם דף או תצוגה משתנים, חשוב לנהל את שם הדף בצורה נכונה. כדי לפתור את הבעיה, צריך להשתמש במאפיין Router.title המובנה של Angular כדי להגדיר כותרות ייחודיות לכל דף.

  1. מוסיפים שם ייחודי לכל אחד משלושת המסלולים שהוגדרו:

src/app/app-routing.module.ts

const routes: Routes = [
  { path: 'shop', component: ShopComponent, title: 'Our Shop – a11y in Angular' },
  { path: 'about', component: AboutComponent, title: 'Our Story - a11y in Angular' },
  { path: 'locate', component: LocationComponent, title: 'Find Us - a11y in Angular' },
  { path: '',   redirectTo: '/shop', pathMatch: 'full' },
  { path: '**', component: ShopComponent },
];

הפעולה הזו תייבא ותשתמש אוטומטית ב- Router's Title Service כדי לנהל את השינוי של שם הדף בניווט כך שיתאים לנכס השם שהוגדר בנתיבים שלנו. אפשר גם לנהל כותרות דפים מורכבות יותר באמצעות TitleStrategy בהתאמה אישית.

אימות השינויים

מפעילים שוב את קורא המסך ובודקים שהשינויים שביצעתם פתרו את הבעיה. עכשיו לדפים יש כותרות ייחודיות.

דפדפן Chrome עם שלוש כרטיסיות פתוחות עם כותרת דף ייחודית: Our Shop - a11y in Angular,‏ Our Story - a11y in Angular,‏ Find Us - a11y in Angular

ביקורת נגישות:

  • לכל הדפים יש כותרות ייחודיות
  • 🛑 הניגודיות בין הצבעים של הרכיבים צריכה להיות מספקת
  • ‫🛑 HTML צריך להיות מסודר בסדר הגיוני, לכלול שם ותפקיד
  • 🛑 אי אפשר לסמן תיבות סימון מוטמעות בקוראי מסך
  • 🛑 קורא המסך לא קורא את הערכים של פס ההזזה
  • ‫🛑 המיקוד של קורא המסך בכלי לבחירת צבעים יוצא מתיבת הדו-שיח
  • 🛑 לא מתקבלות הודעות על שינויים, שגיאות והתראות
  • ‫🛑 מצב הניגודיות הגבוהה לא מופעל

5. הקפדה על ניגודיות צבעים מספקת

העיצוב שלכם אולי נראה מגניב, אבל הוא לא כזה אם אנשים עם לקויות ראייה כמו עיוורון צבעים לא יכולים לקרוא את התוכן. ההנחיות לנגישות בתוכן אינטרנטי (WCAG 2.0) מגדירות סדרה של יחסי ניגודיות צבעים, שמבטיחים שהתוכן יהיה נגיש. ב-Angular ובאינטרנט, אפשר להגדיר פלטות צבעים שיבטיחו שהרכיבים יעמדו בסטנדרטים האלה ויהיו גלויים למשתמשים עם לקות ראייה ועיוורון צבעים.

בסיום הקטע הזה, האפליקציה שלכם תעבור את הביקורת הבאה:

  • 🛑 הניגודיות בין הצבעים של הרכיבים צריכה להיות מספקת

אפשר לראות את כל השלבים האלה מתחת לתגובות: TODO: #5. Ensure adequate color contrast.

שימוש בכלים למפתחים ב-Chrome כדי לזהות בעיות שקשורות לניגודיות נמוכה

כדי לזהות את הבעיה הזו, צריך להשתמש בכלים למפתחים ב-Chrome כדי לבדוק את הרכיבים באפליקציה.

  1. משתמשים בכלי הבדיקה כדי לראות את לחצני סמל התפריט. אפשר לראות שהניגודיות היא 1.85, הרבה מתחת לדרישות WCAG.

כלי הפיתוח ל-Chrome בודק רכיב של כפתור דף הבית עם ניגודיות נמוכה

  1. כדי לראות את הבעיות האלה של יחס הניגודיות, מריצים את הביקורת על הנגישות בסריקה של Lighthouse או axe.

תוצאות הביקורת של Lighthouse בכלי הפיתוח ל-Chrome עם השגיאה: 'יחס הניגודיות של צבעי הרקע והחזית אינו מספיק'

שינוי צבע העיצוב של Material

ערכת הצבעים של הרכיבים מוגדרת בעיצוב Material בהתאמה אישית. מעדכנים את ערך העיצוב כך שיעמוד בהנחיות לגבי יחס הניגודיות של הצבעים.

מעדכנים את עיצוב Material כדי להשתמש בצבע טקסט כהה יותר, וכך להגדיל את יחס הניגודיות של הסמלים:

src/styles.scss

$light-primary: mat.define-palette(mat.$pink-palette, $default: A100, $lighter: 100, $text: 900);

אפשר גם להשתמש בכלים מובנים לנגישות ב<a href="https://developers.google.com/web/tools/chrome-devtools">כלים למפתחים ב-Chrome</a> כדי למצוא צבע שעומד בתקנים, או לעדכן ערכי צבע ספציפיים ב-Sass.

אימות השינויים

צריך לבדוק שוב את הרכיבים ולאמת את השינויים. עכשיו אמורה להיות ניגודיות צבעים מספקת בעיצוב.

כלי הפיתוח ל-Chrome בודקים רכיב של לחצן דף הבית עם ניגודיות מספקת

ביקורת נגישות

  • לכל הדפים יש כותרות ייחודיות
  • יש יחס ניגודיות מספיק בין הצבעים
  • ‫🛑 HTML צריך להיות מסודר בסדר הגיוני, לכלול שם ותפקיד
  • 🛑 אי אפשר לסמן תיבות סימון מוטמעות בקוראי מסך
  • 🛑 קורא המסך לא קורא את הערכים של פס ההזזה
  • ‫🛑 המיקוד של קורא המסך בכלי לבחירת צבעים יוצא מתיבת הדו-שיח
  • 🛑 לא מתקבלות הודעות על שינויים, שגיאות והתראות
  • ‫🛑 מצב הניגודיות הגבוהה לא מופעל

6. שימוש ב-HTML סמנטי

רכיבי HTML מקוריים מתעדים מספר דפוסי אינטראקציה סטנדרטיים שחשובים לנגישות. אפשר לעצב פסקה כ-span ואפשר לעצב div כלחצן, אבל רכיב HTML סמנטי מבטיח שקוראי מסך וניווט באמצעות המקלדת יבינו את האינטראקציות והפקדים של ה-HTML.

כשיוצרים רכיבי Angular, מומלץ לעשות שימוש חוזר ברכיבים המקוריים האלה ישירות כשאפשר, במקום להטמיע מחדש התנהגויות שנתמכות היטב. כך מוודאים שלדף יש מבנה תוכן טוב וזרימת תוכן טבעית, ושהכרטיסייה מסודרת בסדר הגיוני כדי לעזור למשתמשים לנווט באתר באמצעות שימוש יעיל במקלדת.

בסיום הקטע הזה, האפליקציה שלכם תעבור את הביקורת הבאה:

  • ‫🛑 HTML צריך להיות מסודר בסדר הגיוני, לכלול שם ותפקיד

אפשר לראות את כל השלבים האלה מתחת לתגובות: TODO: #6. Use Semantic HTML.

זיהוי הבעיה

  1. מפעילים את VoiceOver.
  2. משתמשים במקש Tab כדי לעבור לכרטיסייה הסיפור שלנו.
  3. שימו לב שסדר הכרטיסיות לא רציף.
  4. לוחצים על Purchas.
  5. שימו לב שהלחצן לא מזוהה כלחצן.

תוצאות הביקורת של Lighthouse בכלי הפיתוח ל-Chrome עם השגיאה: רכיבי הכותרת לא מופיעים בסדר יורד רציף. כשהכותרות מופיעות בסדר הנכון ואינן מדלגות על רמות, הן מבהירות את המבנה הסמנטי של הדף. כך קל יותר לנווט ולהבין את הדף כשמשתמשים בטכנולוגיות מסייעות. למידע נוסף

שינוי של <div> ל-<button>

מחליפים את רכיב ה-<div> המותאם אישית בכפתור Material:

src/app/shop/shop.component.html

<button mat-flat-button 
  color="primary" 
  class="purchase-button"
  (click)="fauxPurchase()">
  Purchase
</button>

שימוש ברכיבי כותרת באופן עקבי

משנים את הסדר של הטקסט כדי להשתמש ב-HTML סמנטי ומחילים סגנון באמצעות טיפוגרפיה של Angular Material:

src/app/about/about.component.html

<h2>Who are we?</h2>
<p class="mat-subheading-2">Have you ever thought, "wow, I love dumplings"?</p>
<p class="right mat-subheading-1">Who hasn't.</p>
<p class="center mat-subheading-1">We took it one step further and created Dumpling Dumpling,</p> 
<p class="center mat-subheading-1">double the dumpling, double the fun.</p>
<div class="spacer"></div>
<h2>How are we different?</h2>
<p class="mat-subheading-2">Handmade in San Francisco, California, we craft fully customizable dumplings. Glitter? Rainbows? Vegan? We do it all.</p>
<p class="right mat-subheading-2">This shop is concept only.</p>

אימות השינויים

מפעילים שוב את קורא המסך ובודקים שהשינויים שביצעתם פתרו את הבעיה. ‫VoiceOver מזהה עכשיו את הלחצן והטקסט נקרא בסדר הגיוני.

ביקורת נגישות:

  • לכל הדפים יש כותרות ייחודיות
  • יש יחס ניגודיות מספיק בין הצבעים
  • HTML סמנטי מבטיח אינטראקציה לוגית
  • 🛑 אי אפשר לסמן תיבות סימון מוטמעות בקוראי מסך
  • 🛑 קורא המסך לא קורא את הערכים של פס ההזזה
  • ‫🛑 המיקוד של קורא המסך בכלי לבחירת צבעים יוצא מתיבת הדו-שיח
  • 🛑 לא מתקבלות הודעות על שינויים, שגיאות והתראות
  • ‫🛑 מצב הניגודיות הגבוהה לא מופעל

7. יצירת אמצעי בקרה שאפשר לבחור באמצעות Angular Material

דוגמה לדפוס אינטראקציה מורכב של שירותי נגישות הוא פקדים מוטמעים. לדוגמה, פריטי משנה בתפריט או תיבות סימון מוטמעות. איך אתם מציינים למשתמש שאפשר לבחור תת-קבוצה של אפשרויות או לנווט לפריט בתפריט הקודם?

ב-Angular, כדי ליצור רכיבים שניתן לנווט בהם, צריך לפשט את התפריטים ואת אמצעי הבקרה ככל האפשר. בדוגמה הזו, משתמשים בתיבת רשימה של Angular Material כדי ליצור דוגמה אחת של דפוס האינטראקציה הזה.

בסיום הקטע הזה, האפליקציה שלכם תעבור את הביקורת הבאה:

  • 🛑 אי אפשר לסמן תיבות סימון מוטמעות בקוראי מסך

אפשר לראות את כל השלבים האלה מתחת לתגובות: TODO: #7. Create selectable controls with Angular Material.

זיהוי הבעיה

כדי לזהות את הבעיה הזו, נפעיל את קורא המסך וננסה לבחור תיבת סימון מוטמעת.

  1. מפעילים את VoiceOver.
  2. לבחור טעמים שונים למילוי.
  3. שימו לב שכאשר VoiceOver קורא את תיבות הסימון של ההורה, לא מצוינים ילדים. איך יודעים שתיבת הסימון טבעוני לא מסומנת עכשיו אחרי שביטלת את הסימון של תיבת הסימון בוק צ'וי?

תפריט תיבות סימון של תוספות עם האפשרויות: תוספות טופו ושיטאקי טבעוניים עם בוק צ&#39;וי בשר עוף בשר אימפוסיבל

נגישות ב-Angular Material

מחליפים את תיבת הסימון הסמנטית בתיבת הסימון של Angular Material, שמכילה ידע מובנה על דפוס האינטראקציה הזה. חשוב לציין שהחלפת רכיבים ב-Material לא מבטיחה נגישות. כמו כל רכיב אחר, צריך לבדוק ידנית כי יש הרבה דרכים להטמיע את Material בצורה לא נגישה.

החלפת תיבות סימון בתיבות סימון של Material

  1. קודם מוסיפים את רשימת המילויים החדשה ומשתנה לאחסון הטעמים של המילויים שנבחרו:

src/app/shop/shop.component.ts

@Component(...)
export class ShopComponent implements OnInit {
  fillings: string[] = ['Bok Choy & Chili Crunch', 'Tofu & Mushroom', 'Chicken & Ginger', 'Impossible Meat & Spinach'];
  selectedFillings: string[] = [];

  fauxPurchase(): void {
    let flavor = '';
    this.selectedFillings.forEach(filling => {
      flavor = flavor + " " + filling
    })
  }
}
  1. מוסיפים <mat-selection-list> כדי להחליף את הקיבוץ המסורבל הזה של תיבות סימון ב-HTML:

src/app/shop/shop.component.html

<mat-selection-list [(ngModel)]="selectedFillings" 
  aria-label="Dumpling fillings">
  <mat-list-option *ngFor="let flavor of fillings" 
    [value]="flavor" 
    color="primary">
    {{ flavor }}
  </mat-list-option>
</mat-selection-list>

בנוסף, TODOהערותsrc/app/shop/shop.component.scss מופיעות במקומות שבהם אפשר להסיר קוד Sass שלא נמצא בשימוש ב-src/app/shop/shop.component.scss כדי לנקות את הסגנון.

אימות השינויים

מפעילים שוב את קורא המסך ובודקים שהשינויים שביצעתם פתרו את הבעיה. עכשיו אפשר לסמן את תיבות הסימון ולעבור ביניהן בצורה אינטואיטיבית יותר באמצעות קורא מסך.

תפריט תיבות סימון של תוספות עם הפריטים: תוספות בוק צ&#39;וי, טופו עם פטריות וצ&#39;ילי קראנץ&#39;, עוף עם ג&#39;ינג&#39;ר, בשר אימפוסיבל ותרד, כמות

ביקורת נגישות:

  • לכל הדפים יש כותרות ייחודיות
  • יש יחס ניגודיות מספיק בין הצבעים
  • HTML סמנטי מבטיח אינטראקציה לוגית
  • קוראי המסך יכולים להגיע לכל אמצעי הבקרה
  • 🛑 קורא המסך לא קורא את הערכים של פס ההזזה
  • ‫🛑 המיקוד של קורא המסך בכלי לבחירת צבעים יוצא מתיבת הדו-שיח
  • 🛑 לא מתקבלות הודעות על שינויים, שגיאות והתראות
  • ‫🛑 מצב הניגודיות הגבוהה לא מופעל

8. הוספת תוויות בקרה באמצעות ARIA

שינית את ה-HTML הסמנטי ואת רכיבי Material באפליקציית Angular, אבל חלק מהרכיבים דורשים מאפיינים ספציפיים כדי שקוראי המסך יוכלו לנווט בהם באופן מלא.

המפרט של Web Accessibility Initiative's Accessible Rich Internet Applications ‏ (WAI-ARIA או ARIA) עוזר לפתור בעיות שלא ניתן לטפל בהן באמצעות HTML מקורי. באמצעות המאפיין הזה אפשר לציין מאפיינים שמשנים את האופן שבו אלמנט מתורגם לעץ הנגישות.

בסיום הקטע הזה, האפליקציה שלכם תעבור את הביקורת הבאה:

  • 🛑 קורא המסך לא קורא את הערכים של פס ההזזה

אפשר לראות את כל השלבים האלה מתחת לתגובות: TODO: #8. Provide control labels with ARIA.

זיהוי הבעיה

כדי לזהות את הבעיה הזו, מפעילים את קורא המסך ומזיזים את פס ההזזה:

  1. מפעילים את VoiceOver.
  2. עוברים אל פס ההזזה של הכמות ומשנים את הערך.
  3. שימו לב שתווית הערך חסרה.

תוצאות הביקורת של Lighthouse בכלי פיתוח ל-Chrome עם השגיאה:  לשדות הזנת קלט של ARIA אין שמות נגישים כשאין לשדה להזנת קלט תווית נגישות, קוראי מסך מציינים שם גנרי, ובמצב כזה אנשים שמסתמכים על קוראי מסך יתקשו להשתמש בשדה. למידע נוסף

שימוש במאפייני ARIA

שליטה בתוויות באמצעות aria-label עד <mat-slider>:

src/app/shop/shop.component.html

<mat-slider
  aria-label="Dumpling order quantity slider"
  id="quantity"
  name="quantity"
  color="primary"
  class="quantity-slider"
  [max]="13"
  [min]="1"
  [step]="1"
  [tickInterval]="1"
  thumbLabel
  [(ngModel)]="quantity">
</mat-slider>

אימות השינויים

מפעילים שוב את קורא המסך ובודקים שהשינויים שביצעתם פתרו את הבעיה. עכשיו אפשר להזיז את פס ההזזה.

ביקורת Lighthouse בכלי הפיתוח ל-Chrome עם ביקורת שעברה לבקרות ARIA של קורא המסך.

ביקורת נגישות:

  • לכל הדפים יש כותרות ייחודיות
  • יש יחס ניגודיות מספיק בין הצבעים
  • HTML סמנטי מבטיח אינטראקציה לוגית
  • קוראי המסך יכולים להגיע לכל אמצעי הבקרה
  • הרכיב Slider משתמש במאפייני ARIA כדי לספק תווית
  • ‫🛑 המיקוד של קורא המסך בכלי לבחירת צבעים יוצא מתיבת הדו-שיח
  • 🛑 לא מתקבלות הודעות על שינויים, שגיאות והתראות
  • ‫🛑 מצב הניגודיות הגבוהה לא מופעל

9. הוספת היכולות של ‎ @angular/cdk/a11y

עד עכשיו הסתמכתם על כלים מובנים של Angular כדי לפתור בעיות נפוצות שקשורות לנגישות. עכשיו נבדוק את מודול הנגישות של CDK ונראה איך הוא יכול לעזור לנו לפתור בעיות מורכבות יותר שספציפיות ל-Angular.

בסוף הקטע הזה, תמשיכו את הקורס הזה עם כלי מודול הנגישות של Angular.

השלבים האלה מופיעים מתחת לתגובה: TODO: #9. Add the power of @angular/cdk/a11y.

ייבוא המודול

מוסיפים את המודול לאפליקציה:

src/app/app.module.ts

import { A11yModule } from '@angular/cdk/a11y';

@NgModule({
  declarations: [...],
  imports: [
    A11yModule
  ],
  providers: [...],
  bootstrap: [...]
})

מה '@angular/cdk/a11y' עושה?

מודול הנגישות מספק מספר כלים לשיפור הנגישות, והוא שימושי במיוחד ליוצרי רכיבים.

בקטעים הבאים מוסבר איך להוסיף שלושה שירותים נפוצים: FocusTrap,‏ LiveAnnouncer ו-HighContrast.

מידע נוסף על כל השירותים האחרים ש-@angular/cdk/a11y מספקת זמין במאמר בנושא נגישות.

10. שליטה במיקוד באמצעות FocusTrap

כשתיבת דו-שיח או חלון מודאלי פתוחים, המשתמש יכול לבצע אינטראקציה רק בתוכם. אם מאפשרים למיקוד לצאת מתיבת הדו-שיח, ההקשרים מתערבבים ונוצר מצב שבו המשתמש לא יודע איפה הוא נמצא בדף.

ב-Angular, ההוראה cdkTrapFocus traps tab-key focus בתוך אלמנט. התכונה הזו מיועדת ליצירת חוויה נגישה לרכיבים כמו תיבות דו-שיח מודאליות, שבהן צריך להגביל את המיקוד.

בסיום הקטע הזה, האפליקציה שלכם תעבור את הביקורת הבאה:

  • ‫🛑 המיקוד של קורא המסך בכלי לבחירת צבעים יוצא מתיבת הדו-שיח

השלבים האלה מופיעים מתחת לתגובות: TODO: #10. Control focus with FocusTrap.

זיהוי הבעיה

כדי לזהות את הבעיה הזו, מפעילים את קורא המסך ופותחים את תיבת הדו-שיח של בוחר הצבעים.

  1. מפעילים את VoiceOver.
  2. כדי לשנות את הצבע, משתמשים בניווט באמצעות מקש Tab.
  3. בודקים את סדר המיקוד האינטואיטיבי ואת נעילת המיקוד בבורר הצבעים.

אתר החנות של Dumpling Time בעיצוב סגול וירוק, עם תיבת דו-שיח פתוחה לבחירת צבע העטיפה של הכיסונים

הוספת FocusTrap

cdkFocusTrap אפשר להשתמש ב- כדי ללכוד ולשלוט בסדר המיקוד ברכיבים מותאמים אישית. שימוש ב-mat-dialog-content מספיק כדי לפתור את רוב הבעיות על ידי לכידת המיקוד בתיבת דו-שיח. מוסיפים את המאפיין cdkFocusInitial כדי להגדיר את אזור המיקוד הראשוני בצבע של עטיפת ה-dumpling <mat-selection-list> בתיבת הדו-שיח של בוחר הצבעים.

src/app/shop/color-picker/color-picker-dialog/color-picker-dialog.component.html

<mat-selection-list #colors aria-label="Dumpling wrapper color" multiple="false" cdkFocusInitial>
  ...
</mat-selection-list>

אימות השינויים

מפעילים שוב את קורא המסך ובודקים שהשינויים שביצעתם פתרו את הבעיה. המיקוד הראשוני מוצב עכשיו על שינוי הצבע בתיבת הדו-שיח.

ביקורת נגישות:

  • לכל הדפים יש כותרות ייחודיות
  • יש יחס ניגודיות מספיק בין הצבעים
  • HTML סמנטי מבטיח אינטראקציה לוגית
  • קוראי המסך יכולים להגיע לכל אמצעי הבקרה
  • הרכיב Slider משתמש במאפייני ARIA כדי לספק תווית
  • הכלי לבחירת צבעים כולל לכידת מיקוד נכונה
  • 🛑 לא מתקבלות הודעות על שינויים, שגיאות והתראות
  • ‫🛑 מצב הניגודיות הגבוהה לא מופעל

11. הכרזה על שינויים באמצעות LiveAnnouncer

צריך לשלוח הודעה לקוראי מסך כשמשהו בדף משתנה. תארו לעצמכם שאתם מנסים לשלוח טופס או להשלים רכישה, ולא יודעים שקפצה שגיאה שמונעת את שליחת הטופס. זה מתסכל!

התכונה LiveAnnouncer משמשת להכרזת הודעות למשתמשים בקורא מסך באמצעות אזור aria-live, כדי להבטיח שקוראי המסך יקבלו התראות על עדכונים ושינויים בדף בזמן אמת. מידע נוסף על אזורי aria-live זמין במאמר WAI-ARIA של W3C. ב-Angular, הפעלת LiveAnnouncer כשירות היא פתרון שקל יותר לבדוק מאשר מאפייני aria-live.

בסיום הקטע הזה, האפליקציה שלכם תעבור את הביקורת הבאה:

  • 🛑 לא מתקבלות הודעות על שינויים, שגיאות והתראות

השלבים האלה מופיעים מתחת לתגובות: TODO: #11. Announce changes with LiveAnnouncer.

זיהוי הבעיה

כדי לזהות את הבעיה הזו, מפעילים את קורא המסך ובוחרים באפשרות רכישה בלי למלא את השדות בטופס:

  1. מפעילים את VoiceOver.
  2. משתמשים בניווט באמצעות מקש Tab כדי לשנות את הצבע ולבצע רכישה מזויפת.
  3. שימו לב שלא מופיע שום סימן לצבע שנבחר כשיוצאים מתיבת הדו-שיח, והרכישה לא נקראת.

אתר החנות של Dumpling Time בעיצוב ורוד ואדום, עם תיבת דו-שיח פתוחה לבחירת צבע העטיפה של הכיסונים

הוספת LiveAnnouncer לקוד

מוסיפים את LiveAnnouncer, ומכריזים על בחירת הצבע ועל הרכישה המזויפת כמחרוזת. ביישום אמיתי, יכול להיות שהערך הזה ייקרא כשעוברים למערכת תשלומים של צד שלישי או כשמופיעות שגיאות בטופס.

  1. להוסיף הודעה כשבוחרים צבע:

src/app/shop/color-picker/color-picker-dialog/color-picker-dialog.component.ts

import { LiveAnnouncer } from '@angular/cdk/a11y';

@Component(...)
export class ColorPickerDialogComponent implements OnInit {
  constructor(
    public dialogRef: MatDialogRef<ColorPickerDialogComponent>,
    @Inject(MAT_DIALOG_DATA) public data: ColorDialogData,
    private liveAnnouncer: LiveAnnouncer) { }

  public changeColor(color: string): void {
    this.liveAnnouncer.announce(`Select color: ${color}`);
    this.dialogRef.close();
  }
}
  1. הוספת הודעה כשמתבצעת רכישה מזויפת:

src/app/shop/shop.component.ts

import { LiveAnnouncer } from '@angular/cdk/a11y';

@Component(...)
export class ShopComponent implements OnInit {

  constructor(private liveAnnouncer: LiveAnnouncer) { }

  fauxPurchase(): void {
    let flavor = '...';
    const fakePurchase = `Purchase ${this.quantity} ${flavor}dumplings in the color ${this.color}!`;

    this.liveAnnouncer.announce(fakePurchase);
  }
}

אימות השינויים

מפעילים שוב את קורא המסך ובודקים שהשינויים שביצעתם פתרו את הבעיה. מעכשיו תקבלו התראות על שגיאות.

ביקורת נגישות:

  • לכל הדפים יש כותרות ייחודיות
  • יש יחס ניגודיות מספיק בין הצבעים
  • HTML סמנטי מבטיח אינטראקציה לוגית
  • קוראי המסך יכולים להגיע לכל אמצעי הבקרה
  • הרכיב Slider משתמש במאפייני ARIA כדי לספק תווית
  • הכלי לבחירת צבעים כולל לכידת מיקוד נכונה
  • הודעות על שינויים, שגיאות והתראות
  • ‫🛑 מצב הניגודיות הגבוהה לא מופעל

12. הפעלת מצב ניגודיות גבוהה

מערכת ההפעלה Microsoft Windows תומכת בתכונת נגישות שנקראת 'מצב ניגודיות גבוהה'. במצב הזה, המראה של כל האפליקציות, כולל אפליקציות אינטרנט, משתנה כדי להגדיל באופן משמעותי את הניגודיות. ב-Angular, חשוב לכבד את ההעדפות של המשתמשים באפליקציה.

המאפיין HighContrastModeDetector מאפשר לקבוע אם הדפדפן נמצא כרגע בסביבה של מצב ניגודיות גבוהה.

הדפדפנים Internet Explorer,‏ Microsoft Edge ו-Firefox תומכים במצב הזה. ‫Google Chrome לא תומך במצב ניגודיות גבוהה ב-Windows. השירות הזה לא מזהה מצב ניגודיות גבוהה שנוסף באמצעות התוסף 'ניגודיות גבוהה' לדפדפן Chrome.

בסיום הקטע הזה, האפליקציה שלכם תעבור את הביקורת הבאה:

  • ‫🛑 מצב הניגודיות הגבוהה לא מופעל

השלבים האלה מופיעים מתחת לתגובות: TODO: #12. Enable HighContrast mode.

זיהוי הבעיה

כדי לזהות את הבעיה הזו, פותחים את האפליקציה ב-Internet Explorer, ב-Microsoft Edge או ב-Firefox, מפעילים את מצב הניגודיות הגבוהה ורואים שלא חל שינוי:

  1. פותחים את האפליקציה ב-Internet Explorer, ב-Microsoft Edge או ב-Firefox.
  2. מפעילים את מצב הניגודיות הגבוהה.
  3. שימו לב שהאפליקציה לא השתנתה.

הוספת תמיכה במצב ניגודיות גבוהה

ב-styles.scss, משתמשים ב-mixin‏ cdk-high-contrast שמופיע ב-@angular/cdk/a11y כדי להוסיף קו מתאר לכפתורים במצב ניגודיות גבוהה:

src/app/shop/shop.component.scss

@use '@angular/cdk';

.purchase-button {
    border-radius: 5px;
    background-color: mat.get-color-from-palette(mat.$pink-palette, A100);

    @include cdk-high-contrast {
      outline: solid 1px;
      background-color: mat.get-color-from-palette(mat.$pink-palette, 50);
    }
}

:host-context(.dark-theme) {
  .purchase-button {
    background-color: mat.get-color-from-palette(mat.$light-green-palette, A100);

    @include cdk-high-contrast {
      outline: solid 1px;
      background-color: mat.get-color-from-palette(mat.$light-green-palette, 50);
    }
  }
}

אימות השינויים

מרעננים את האפליקציה ובודקים את השינויים. הוספת קו מתאר לכפתור במצב ניגודיות גבוהה!

אתר החנות של Dumpling Time עם עיצוב אדום וורוד, מצב ניגודיות גבוהה מופעל וכפתור הרכישה מודגש עכשיו עם קו מתאר אדום עבה אתר החנות של Dumpling Time עם עיצוב כחול וירוק, מצב ניגודיות גבוהה מופעל והכפתור לרכישה מודגש מאוד עם קו מתאר כחול עבה

ביקורת נגישות:

  • לכל הדפים יש כותרות ייחודיות
  • יש יחס ניגודיות מספיק בין הצבעים
  • HTML סמנטי מבטיח אינטראקציה לוגית
  • קוראי המסך יכולים להגיע לכל אמצעי הבקרה
  • הרכיב Slider משתמש במאפייני ARIA כדי לספק תווית
  • הכלי לבחירת צבעים כולל לכידת מיקוד נכונה
  • הודעות על שינויים, שגיאות והתראות
  • מצב ניגודיות גבוהה מופעל

13. מעולה!

מזל טוב, טיפלת בבעיות נפוצות של נגישות לאתרים באפליקציית Angular שלך! 🎉

כדי לראות את כל הפתרונות, אפשר לעיין בענף main.

אתר החנות של Dumpling Time בעיצוב אדום וורוד, עם כל השינויים שבוצעו ב-codelab הזה אתר החנות של Dumpling Time בעיצוב כחול וירוק, עם כל השינויים שבוצעו ב-codelab הזה ביקורת Lighthouse בכלי הפיתוח ל-Chrome עם ציון של 100/100

עכשיו אתם יודעים מהם השלבים העיקריים שצריך לבצע כדי לפתור שמונה בעיות נפוצות של נגישות באפליקציית Angular.

מידע נוסף

כדאי לנסות את ה-Codelabs הבאים:

מומלץ לקרוא את החומרים הבאים: