Skip to content

Commit 088c4a0

Browse files
committed
feat(accessibility): use correct aria properties
Based on [aXe](https://www.deque.com/axe/) recommendations, fix accessibility: - Use proper roles for the various components (ex: role="button" not needed on buttons). - Reorder navigation and pagination to better match the tabbing order. - Make navigation accessible by tabbing. - Change the HTML elements to better match [W3's recommended organization](https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-1/tabs.html)
1 parent 5804502 commit 088c4a0

File tree

7 files changed

+204
-272
lines changed

7 files changed

+204
-272
lines changed

src/Carousel.vue

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
'VueCarousel-inner',
1414
{ 'VueCarousel-inner--center': isCenterModeEnabled }
1515
]"
16-
role="listbox"
1716
:style="{
1817
'transform': `translate(${currentOffset}px, 0)`,
1918
'transition': dragging ? 'none' : transitionStyle,
@@ -30,10 +29,6 @@
3029
</div>
3130
</div>
3231

33-
<slot name="pagination" v-if="paginationEnabled">
34-
<pagination @paginationclick="goToPage($event, 'pagination')"/>
35-
</slot>
36-
3732
<slot name="navigation" v-if="navigationEnabled">
3833
<navigation
3934
v-if="isNavigationRequired"
@@ -43,6 +38,10 @@
4338
@navigationclick="handleNavigation"
4439
/>
4540
</slot>
41+
42+
<slot name="pagination" v-if="paginationEnabled">
43+
<pagination @paginationclick="goToPage($event, 'pagination')"/>
44+
</slot>
4645
</section>
4746
</template>
4847
<script>

src/Navigation.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<button
44
type="button"
55
aria-label="Previous page"
6-
role="button"
6+
:tabindex="canAdvanceBackward ? 0 : -1"
77
class="VueCarousel-navigation-button VueCarousel-navigation-prev"
88
v-on:click.prevent="triggerPageAdvance('backward')"
99
v-bind:class="{ 'VueCarousel-navigation--disabled': !canAdvanceBackward }"
@@ -12,7 +12,7 @@
1212
<button
1313
type="button"
1414
aria-label="Next page"
15-
role="button"
15+
:tabindex="canAdvanceForward ? 0 : -1"
1616
class="VueCarousel-navigation-button VueCarousel-navigation-next"
1717
v-on:click.prevent="triggerPageAdvance()"
1818
v-bind:class="{ 'VueCarousel-navigation--disabled': !canAdvanceForward }"
@@ -94,6 +94,10 @@ export default {
9494
outline: none;
9595
}
9696
97+
.VueCarousel-navigation-button:focus {
98+
outline: 1px solid lightblue;
99+
}
100+
97101
.VueCarousel-navigation-next {
98102
right: 0;
99103
transform: translateY(-50%) translateX(100%);

src/Pagination.vue

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,28 @@
44
class="VueCarousel-pagination"
55
v-bind:class="{ [`VueCarousel-pagination--${paginationPositionModifierName}`]: paginationPositionModifierName }"
66
>
7-
<ul class="VueCarousel-dot-container" role="tablist">
8-
<li
7+
<div class="VueCarousel-dot-container" role="tablist" :style="`margin-top: ${carousel.paginationPadding * 2}px;`">
8+
<button
9+
v-for="(page, index) in paginationCount"
10+
:key="`${page}_${index}`"
911
class="VueCarousel-dot"
1012
aria-hidden="false"
11-
role="presentation"
13+
role="tab"
14+
:title="`Item ${index}`"
15+
:value="`Item ${index}`"
16+
:aria-label="`Item ${index}`"
1217
:aria-selected="isCurrentDot(index) ? 'true' : 'false'"
1318
v-bind:class="{ 'VueCarousel-dot--active': isCurrentDot(index) }"
14-
v-for="(page, index) in paginationCount"
15-
:key="`${page}_${index}`"
1619
v-on:click="goToPage(index)"
1720
:style="`
1821
margin-${paginationPropertyBasedOnPosition}: ${carousel.paginationPadding * 2}px;
1922
padding: ${carousel.paginationPadding}px;
23+
width: ${carousel.paginationSize}px;
24+
height: ${carousel.paginationSize}px;
25+
background-color: ${isCurrentDot(index) ? carousel.paginationActiveColor : carousel.paginationColor};
2026
`"
21-
>
22-
<button
23-
type="button"
24-
role="button"
25-
aria-label="`Item ${index}`"
26-
:title="`Item ${index}`"
27-
class="VueCarousel-dot-button"
28-
:tabindex="0"
29-
:style="`
30-
width: ${carousel.paginationSize}px;
31-
height: ${carousel.paginationSize}px;
32-
background: ${isCurrentDot(index) ? carousel.paginationActiveColor : carousel.paginationColor};
33-
`"
34-
></button>
35-
</li>
36-
</ul>
27+
></button>
28+
</div>
3729
</div>
3830
</template>
3931

@@ -112,19 +104,16 @@ export default {
112104
.VueCarousel-dot {
113105
display: inline-block;
114106
cursor: pointer;
115-
}
116-
117-
.VueCarousel-dot-button {
118107
appearance: none;
119108
border: none;
120-
background-color: transparent;
109+
background-clip: content-box;
110+
box-sizing: content-box;
121111
padding: 0;
122112
border-radius: 100%;
123113
outline: none;
124-
cursor: pointer;
125114
}
126115
127-
.VueCarousel-dot-button:focus {
116+
.VueCarousel-dot:focus {
128117
outline: 1px solid lightblue;
129118
}
130119
</style>

src/Slide.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
<div
33
class="VueCarousel-slide"
44
tabindex="-1"
5+
:aria-hidden="!isActive"
6+
role="tabpanel"
57
:class="{
68
'VueCarousel-slide-active': isActive,
79
'VueCarousel-slide-center': isCenter,

0 commit comments

Comments
 (0)