|
| 1 | +title: Accessibility Improvements: Final Changes and Modal Accessilibity |
| 2 | +--- |
| 3 | +categories: |
| 4 | +cc-search |
| 5 | +community |
| 6 | +gsoc |
| 7 | +open-source |
| 8 | + |
| 9 | +--- |
| 10 | +author: AyanChoudhary |
| 11 | +--- |
| 12 | +series: gsoc-2020-ccsearch-accessibility |
| 13 | +--- |
| 14 | +pub_date: 2020-08-12 |
| 15 | +--- |
| 16 | +body: |
| 17 | + |
| 18 | +These are the last two weeks of my internship with CC. I am working on improving the accessibility of cc-search and internationalizing it as well. |
| 19 | +This post contains details of my work done to make accessibility improvements to the search result page and the image detail page and also covers some advanced accessiblity improvement details. |
| 20 | + |
| 21 | +The topics included in this post cover: |
| 22 | + |
| 23 | +1. Tooltip accessibility and keyboard interactions |
| 24 | +2. Improve modal accessibility and implement trap focus |
| 25 | +3. Fix `<label>` for form elements |
| 26 | + |
| 27 | +The first stage involved fixing the license explanation tooltips. These tooltips worked fine on click but did not respond to keypress events. |
| 28 | +The solution to overcome this was to use an event listener on the element which would would execute the `showLicenseExplanation` function onClick. |
| 29 | +Luckily `VueJS` provides this function inbuilt via the `v-on:keyup` attribute. So after change the code looks as follows: |
| 30 | + |
| 31 | +```html |
| 32 | +<img |
| 33 | + :aria-label="$t('browse-page.aria.license-explanation')" |
| 34 | + tabindex="0" |
| 35 | + v-if="filterType == 'licenses'" |
| 36 | + src="@/assets/help_icon.svg" |
| 37 | + alt="help" |
| 38 | + class="license-help is-pulled-right padding-top-smallest padding-right-smaller" |
| 39 | + @click.stop="toggleLicenseExplanationVisibility(item.code)" |
| 40 | + v-on:keyup.enter="toggleLicenseExplanationVisibility(item.code)" |
| 41 | +/> |
| 42 | +``` |
| 43 | + |
| 44 | +Similar change was made to all the tooltips. The reason behind this error was that non-semantic element representation |
| 45 | +(i.e. using `<div>`, `<span>` or `<img>` instead of a `<button>`) does not register a keypress listener for these tags and hence they don't respond on keypress. |
| 46 | + |
| 47 | +The second change is related to modals. Modals have some stringent accessilibity parameters that have to be carefully handled. |
| 48 | +The criteria are: |
| 49 | + |
| 50 | +1. On opening the modal the remaining elements should get disabled. |
| 51 | +2. The modal should have trap-focus(the user should not exit the modal when using tab to navigate). |
| 52 | +3. The modal should close on pressing **esc** or on clicking the overlay. |
| 53 | + |
| 54 | +To meet the criteria we developed a new [modal component](https://github.com/creativecommons/cccatalog-frontend/blob/develop/src/components/AppModal.vue). |
| 55 | +This modal has an overlay and closes when we press the **esc** key or click on the overlay. The modal also disables other elements when it is opened. |
| 56 | + |
| 57 | +The final task achieved in the modal was the implementation of trap focus. For this we used the [vue-trap-focus library](https://github.com/posva/focus-trap-vue) |
| 58 | +The library exposes a `<focus-trap>` component which acts as wrapper to enable focus-trap. The implementation we used was: |
| 59 | + |
| 60 | +```html |
| 61 | +<focus-trap :active="true"> |
| 62 | + <div class="modal relative" aria-modal="true" role="dialog"> |
| 63 | + <header |
| 64 | + v-if="title" |
| 65 | + class="modal-header padding-top-bigger padding-left-bigger padding-right-normal padding-bottom-small" |
| 66 | + > |
| 67 | + <slot name="header"> |
| 68 | + <h3>{{ title }}</h3> |
| 69 | + </slot> |
| 70 | + <button |
| 71 | + type="button" |
| 72 | + class="close-button has-color-gray is-size-6 is-size-4-touch" |
| 73 | + @click="$emit('close')" |
| 74 | + :aria-label="$t('browse-page.aria.close')" |
| 75 | + > |
| 76 | + <i class="icon cross" /> |
| 77 | + </button> |
| 78 | + </header> |
| 79 | + <slot default /> |
| 80 | + </div> |
| 81 | +</focus-trap> |
| 82 | +``` |
| 83 | + |
| 84 | +Apart from these the modal also has the `aria-modal` attribute and the `role="dialog"` attribute. |
| 85 | +These attributes direct our screen readers to recognise this component as a modal and declare it whenever the modal opens. |
| 86 | + |
| 87 | +The last improvement involves using appropriate label tags for the form elements. A lot of elements did not have proper labels or were nested in wrong way. |
| 88 | +These elements were fixed and after the fixing the nestings the elements had proper labels which the screen readers were able to identify. |
| 89 | +An example a proper input elements with correct label nesting is: |
| 90 | + |
| 91 | +```html |
| 92 | +<label class="checkbox" :for="item.code" :disabled="block(item)"> |
| 93 | + <input |
| 94 | + type="checkbox" |
| 95 | + class="filter-checkbox margin-right-small" |
| 96 | + :id="item.code" |
| 97 | + :key="index" |
| 98 | + :checked="item.checked" |
| 99 | + :disabled="block(item)" |
| 100 | + @change="onValueChange" |
| 101 | + /> |
| 102 | + <license-icons v-if="filterType == 'licenses'" :license="item.code" /> |
| 103 | + {{ $t(item.name) }} |
| 104 | +</label> |
| 105 | +``` |
| 106 | +Notice how the input is a child of the `<label>` tag which has the `for` attribute to point which element it labels. |
| 107 | + |
| 108 | +Apart from these changes, the eslint configuration of the project were also changed to include a11y-linting for the elments. |
| 109 | +We used the [eslint-plugin-vue-a11y](https://github.com/maranran/eslint-plugin-vue-a11y) to enforce accessibility guidelines for our components via lint checks. |
| 110 | +Furthermore all the aria-labels were internationalized to enforce the i18n standard in our repo that we had setup earlier this summer. |
| 111 | + |
| 112 | +After all these changes we had the following inprovements in the accessibility scores(computed from lighthouse): |
| 113 | + |
| 114 | +1. Browse Page: 76 -> 98 | +22 |
| 115 | +2. Collections Browse Page: 86 -> 96 | +10 |
| 116 | +3. Photo Detail Page: 75 -> 95 | +20 |
| 117 | + |
| 118 | +And we are officially done with our work for the summer internship. The next blog will be the culmination of this series. |
| 119 | + |
| 120 | +You can track the work done for these weeks through these PRs: |
| 121 | + |
| 122 | +1. [Accessibility Improvements](https://github.com/creativecommons/cccatalog-frontend/pull/1072) |
| 123 | +2. [setup vue-a11y for eslint](https://github.com/creativecommons/cccatalog-frontend/pull/1121) |
| 124 | +3. [Aria labels and internationalization](https://github.com/creativecommons/cccatalog-frontend/pull/1123) |
| 125 | +4. [internationalize aria-labels for about page and feedback page](https://github.com/creativecommons/cccatalog-frontend/pull/1120) |
| 126 | +5. [add trap focus to modals](https://github.com/creativecommons/cccatalog-frontend/pull/1153) |
| 127 | + |
| 128 | +The progress of the project can be tracked on [cc-search](https://github.com/creativecommons/cccatalog-frontend) |
| 129 | + |
| 130 | +CC Search Accessiblity is my GSoC 2020 project under the guidance of [Zack Krida](https://creativecommons.org/author/zackcreativecommons-org/) and [Ari Madian](https://opensource.creativecommons.org/blog/authors/akmadian/), who is the primary mentor for this project, [Anna Tumadóttir](https://creativecommons.org/author/annacreativecommons-org/) for helping all along and engineering director [Kriti |
| 131 | +Godey](https://creativecommons.org/author/kriticreativecommons-org/), have been very supportive. |
0 commit comments