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

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

לוגו שחור של זווית

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

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

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

במאמר נגישות מוסבר בהרחבה על בעיות וטכניקות לעיצוב אפליקציות נגישות.

מה תפַתחו

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

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

מה תלמדו

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

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

מה צריך להכין

2. להגדרה

קבלת הקוד

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

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

מומלץ להשתמש ב-VSCode או בסביבת פיתוח משולבת (IDE) מקומית כדי לעבוד עם הקוד במסגרת הקודלאב הזה.

  1. פותחים כרטיסייה חדשה בדפדפן ועוברים לכתובת https://github.com/googlecodelabs/angular-accessibility.
  2. מקשרים את המאגר, משכפלים אותו ומעבירים את 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. בוחרים באפשרות Purchase כדי לתעד את ההזמנה בהתאמה אישית במסוף.

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

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

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

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

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

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

בדיקה ידנית

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

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

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

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

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

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

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

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

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

גרזן

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

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

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

ב-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 צריך להיות סדר לוגי, שם ותפקיד
  • 🛑 תיבות סימון מקוננות שלא ניתן לבחור בקוראי מסך
  • 🛑 קורא המסך לא קורא את הערכים של פס ההזזה
  • 🛑 המיקוד של קורא המסך בחלונית לבחירת הצבעים יוצא מתיבת הדו-שיח
  • 🛑 לא מתפרסמים הודעות על שינויים, שגיאות והתראות
  • 🛑 מצב HighContrast לא מופעל

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

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

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

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

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

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

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

זיהוי הבעיה

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

  1. מפעילים את VoiceOver.
  2. אפשר להשתמש בניווט באמצעות כרטיסיות כדי לנווט בין דפים.
  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 צריך להיות סדר לוגי, שם ותפקיד
  • 🛑 תיבות סימון מקוננות שלא ניתן לבחור בקוראי מסך
  • 🛑 קורא המסך לא קורא את הערכים של פס ההזזה
  • 🛑 המיקוד של קורא המסך בחלונית לבחירת הצבעים יוצא מתיבת הדו-שיח
  • 🛑 לא מתפרסמים הודעות על שינויים, שגיאות והתראות
  • 🛑 מצב HighContrast לא מופעל

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

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

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

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

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

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

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

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

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

  1. כדאי להריץ את בדיקת הנגישות בסריקה של Lighthouse או של גרזן כדי לראות את הבעיות האלה ביחס לניגודיות.

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

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

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

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

src/styles.scss

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

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

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

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

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

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

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

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

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

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

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

  • 🛑 ל-HTML צריך להיות סדר לוגי, שם ותפקיד

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

זיהוי הבעיה

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

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

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

מחליפים את <div> המותאם אישית בלחצן 'חומר':

src/app/shop/shop.component.html

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

שימוש ברכיבי כותרת ברצף

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

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 סמנטי מבטיח אינטראקציה לוגית
  • 🛑 קורא המסך לא יכול לבחור תיבות סימון בתצוגת עץ
  • 🛑 קורא המסך לא קורא את הערכים של פס ההזזה
  • 🛑 המיקוד של קורא המסך בחלונית לבחירת הצבעים יוצא מתיבת הדו-שיח
  • 🛑 לא מתפרסמים הודעות על שינויים, שגיאות והתראות
  • 🛑 מצב HighContrast לא מופעל

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

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

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

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

  • 🛑 לא ניתן לבחור תיבות סימון בתצוגת עץ בקוראי מסך

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

זיהוי הבעיה

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

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

תפריט תיבות סימון של מילויים עם האפשרויות הבאות: מילויים טבעוניים, כרוב סיני, טופו ובשר פטריות שיטאקי, עוף, בשר Impossible

נגישות ב-Angular Material

מחליפים את התיבה הסמנטית בתיבה של Angular 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 מאפשרות לכם גם לראות איפה אפשר להסיר חלק מה-Sass שלא בשימוש ב-src/app/shop/shop.component.scss כדי לנקות את הסגנון.

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

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

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

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

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

8. הוספת תוויות לפקדים באמצעות ARIA

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

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

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

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

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

זיהוי הבעיה

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

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

תוצאות הביקורת של Lighthouse ב-Chrome DevTools עם השגיאה:  לשדות הזנת קלט של 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 סמנטי מבטיח אינטראקציה לוגית
  • אפשר לגשת לכל הפקדים באמצעות קוראי מסך
  • פס ההזזה משתמש במאפייני ARIA כדי לספק תווית
  • 🛑 המיקוד של קורא המסך בחלונית לבחירת הצבעים יוצא מתיבת הדו-שיח
  • 🛑 לא מתפרסמים הודעות על שינויים, שגיאות והתראות
  • 🛑 מצב HighContrast לא מופעל

9. הוספת העוצמה של @angular/cdk/a11y

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

עד סוף החלק הזה, תמשיכו את הקורס הזה עם כלים של Angular a11y.

השלבים האלה יופיעו מתחת לתגובה: 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' עושה?

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

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

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

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

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

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

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

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

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

זיהוי הבעיה

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

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

אתר של חנות &#39;זמן כופתאות&#39; בעיצוב סגול וירוק עם תיבת דו-שיח פתוחה לבחירת צבע האריזה של הכופתאות

הוספת FocusTrap

אפשר להשתמש ב-cdkFocusTrap כדי ללכוד ולשלוט בסדר ההתמקדות ברכיבים מותאמים אישית. שימוש ב-mat-dialog-content מספיק כדי לפתור את רוב הבעיות על ידי נעילה של המיקוד בתיבת דו-שיח. מוסיפים את המאפיין cdkFocusInitial כדי להגדיר את אזור המיקוד הראשוני בצבע ה-wrapper של הכופתאות <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 סמנטי מבטיח אינטראקציה לוגית
  • אפשר לגשת לכל הפקדים באמצעות קוראי מסך
  • פס ההזזה משתמש במאפייני ARIA כדי לספק תווית
  • בוחר הצבעים כולל טראפפוקוס תקין
  • 🛑 לא מתפרסמים הודעות על שינויים, שגיאות והתראות
  • 🛑 מצב HighContrast לא מופעל

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

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

אפליקציית LiveEmailr מכריזה על הודעות למשתמשים בקורא מסך שמשתמשים באזור בשידור חי באמצעות ARIA, כדי לוודא שקוראי המסך מקבלים התראות על התראות ושינויים בדפים בזמן אמת. מידע נוסף על אזורים מסוג 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 סמנטי מבטיח אינטראקציה לוגית
  • אפשר לגשת לכל הפקדים באמצעות קוראי מסך
  • פס ההזזה משתמש במאפייני ARIA כדי לספק תווית
  • בוחר הצבעים כולל טראפפוקוס תקין
  • הודעות על שינויים, שגיאות והתראות
  • 🛑 מצב HighContrast לא מופעל

12. הפעלת מצב HighContrast

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

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

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

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

  • 🛑 מצב HighContrast לא מופעל

השלבים האלה מופיעים מתחת לתגובות: 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 סמנטי מבטיח אינטראקציה לוגית
  • אפשר לגשת לכל הפקדים באמצעות קוראי מסך
  • פס ההזזה משתמש במאפייני ARIA כדי לספק תווית
  • בוחר הצבעים כולל טראפפוקוס תקין
  • הודעות על שינויים, שגיאות והתראות
  • מצב הניגודיות הגבוהה מופעל

13. מעולה!

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

כדי לראות את כל הפתרונות, צריך לבדוק את ההסתעפות main.

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

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

מידע נוסף

כדאי לעיין בהדרכות הבאות ב-Codelab:

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