Skip to content

Commit d669a7c

Browse files
authored
small sortable table a11y fixes (rancher#13448)
* adds small fixes to sortable table a11y * make screen readers ignore the icons to get sorting indication as its present in th element * address pr comments * address pr comments
1 parent 6ca778b commit d669a7c

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

pkg/rancher-components/src/components/Form/Checkbox/Checkbox.vue

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { PropType, defineComponent } from 'vue';
33
import { _EDIT, _VIEW } from '@shell/config/query-params';
44
import { addObject, removeObject } from '@shell/utils/array';
55
import cloneDeep from 'lodash/cloneDeep';
6+
import { generateRandomAlphaString } from '@shell/utils/string';
67
78
export default defineComponent({
89
name: 'Checkbox',
@@ -37,7 +38,7 @@ export default defineComponent({
3738
*/
3839
id: {
3940
type: String,
40-
default: String(Math.random() * 1000)
41+
default: generateRandomAlphaString(12)
4142
},
4243
4344
/**
@@ -113,7 +114,16 @@ export default defineComponent({
113114
primary: {
114115
type: Boolean,
115116
default: false
116-
}
117+
},
118+
119+
/**
120+
* Use this for usage of checkboxes that don't present a label.
121+
* Used for cases such as table checkboxes (group or row)
122+
*/
123+
alternateLabel: {
124+
type: String,
125+
default: undefined
126+
},
117127
},
118128
119129
emits: ['update:value'],
@@ -143,6 +153,18 @@ export default defineComponent({
143153
hasTooltip(): boolean {
144154
return !!this.tooltip || !!this.tooltipKey;
145155
},
156+
157+
replacementLabel(): string | undefined {
158+
if (!this.label && !this.labelKey && this.alternateLabel) {
159+
return this.alternateLabel;
160+
}
161+
162+
return undefined;
163+
},
164+
165+
idForLabel():string {
166+
return `${ this.id }-label`;
167+
}
146168
},
147169
148170
methods: {
@@ -228,26 +250,26 @@ export default defineComponent({
228250
<label
229251
class="checkbox-container"
230252
:class="{ 'disabled': isDisabled}"
231-
:for="id"
232253
@keydown.enter.prevent="clicked($event)"
233254
@keydown.space.prevent="clicked($event)"
234255
@click="clicked($event)"
235256
>
236257
<input
258+
:id="id"
237259
:checked="isChecked"
238260
:value="valueWhenTrue"
239261
type="checkbox"
240262
tabindex="-1"
241-
:name="id"
242263
@click.stop.prevent
243264
@keyup.enter.stop.prevent
244265
>
245266
<span
246267
class="checkbox-custom"
247268
:class="{indeterminate: indeterminate}"
248269
:tabindex="isDisabled ? -1 : 0"
249-
:aria-label="label"
270+
:aria-label="replacementLabel"
250271
:aria-checked="!!value"
272+
:aria-labelledby="labelKey || label ? idForLabel : undefined"
251273
role="checkbox"
252274
/>
253275
<span
@@ -258,10 +280,14 @@ export default defineComponent({
258280
<slot name="label">
259281
<t
260282
v-if="labelKey"
283+
:id="idForLabel"
261284
:k="labelKey"
262285
:raw="true"
263286
/>
264-
<template v-else-if="label">{{ label }}</template>
287+
<span
288+
v-else-if="label"
289+
:id="idForLabel"
290+
>{{ label }}</span>
265291
<i
266292
v-if="tooltipKey"
267293
v-clean-tooltip="{content: t(tooltipKey), triggers: ['hover', 'touch', 'focus']}"

shell/assets/translations/en-us.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5401,6 +5401,8 @@ setup:
54015401
welcome: Welcome to {vendor}!
54025402

54035403
sortableTable:
5404+
genericGroupCheckbox: Table group selection checkbox
5405+
genericRowCheckbox: Table row selection checkbox for item {item}
54045406
tableActionsLabel: More actions - { resource }
54055407
tableActionsImgAlt: More actions icon
54065408
bulkActions:

shell/components/SortableTable/THead.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ export default {
230230
data-testid="sortable-table_check_select_all"
231231
:indeterminate="isIndeterminate"
232232
:disabled="noRows || noResults"
233+
:alternate-label="t('sortableTable.genericGroupCheckbox')"
233234
/>
234235
</th>
235236
<th
@@ -269,6 +270,7 @@ export default {
269270
<div
270271
v-if="col.sort"
271272
class="sort"
273+
aria-hidden="true"
272274
>
273275
<i
274276
v-show="hasAdvancedFiltering && !col.isFilter"

shell/components/SortableTable/index.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,7 @@ export default {
13851385
:data-node-id="row.key"
13861386
:data-testid="componentTestid + '-' + i + '-checkbox'"
13871387
:value="selectedRows.includes(row.row)"
1388+
:alternate-label="t('sortableTable.genericRowCheckbox', { item: row && row.row ? row.row.id : '' })"
13881389
/>
13891390
</td>
13901391
<td

0 commit comments

Comments
 (0)