Skip to content

Commit 1222ac9

Browse files
committed
feat(admin,ui): improve accessibility and testability
Add ARIA attributes, semantic roles, and proper label linkage across 21 components to enable reliable semantic locators and improve screen reader support. Form fields: - DitoTypeMultiselect: add id and aria-label to VueMultiselect - DitoTypeRadio: add role="radiogroup" and aria-label - DitoTypeCheckboxes: add role="group" and aria-label - DitoSwitch (UI): add role="switch" and aria-checked Navigation & landmarks: - DitoTabs: add role="tablist", role="tab", aria-selected, tabindex - DitoTrail: add aria-label="Breadcrumb" and aria-current="page" - DitoMenu: add aria-current="page" on active links - DitoPagination (UI): use nav element, add aria-label, aria-current - DitoHeader: add aria-busy when loading Interactive elements: - DitoTreeItem: add role="button", aria-expanded, keyboard support - DitoScopes: add aria-pressed on active scope buttons - DitoAccount: add role="button", pulldown trigger attrs from mixin - DitoCreateButton: add pulldown trigger attrs, role="menu/menuitem" - PulldownMixin: centralize aria-haspopup and aria-expanded Feedback & status: - DitoErrors: add role="alert" - DitoNotifications: add aria-live="polite" - DitoSpinner: add role="status" and aria-label="Loading" - DitoDialog: add aria-label Tables: - DitoTableHead: add scope="col" and aria-sort on sortable columns - DitoTypeUpload: add scope="col" on table headers
1 parent 360bd6a commit 1222ac9

22 files changed

Lines changed: 82 additions & 13 deletions

packages/admin/src/components/DitoAccount.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
<template lang="pug">
22
.dito-account
33
a(
4+
role="button"
5+
v-bind="pulldownTriggerAttributes"
46
@mousedown.stop="onPulldownMouseDown()"
57
)
68
span {{ user.username }}
7-
ul.dito-pulldown(:class="{ 'dito-pulldown--open': pulldown.open }")
9+
ul.dito-pulldown(
10+
role="menu"
11+
:class="{ 'dito-pulldown--open': pulldown.open }"
12+
)
813
li(
914
v-for="(label, value) of items"
1015
)
1116
a.dito-pulldown__item(
17+
role="menuitem"
1218
@mousedown.stop="onPulldownMouseDown(value)"
1319
@mouseup="onPulldownMouseUp(value)"
1420
) {{ label }}

packages/admin/src/components/DitoCreateButton.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,19 @@
1313
button.dito-button(
1414
type="button"
1515
:disabled="disabled"
16-
v-bind="getButtonAttributes(verb)"
16+
v-bind="{ ...pulldownTriggerAttributes, ...getButtonAttributes(verb) }"
1717
@mousedown.stop="onPulldownMouseDown()"
1818
) {{ text }}
19-
ul.dito-pulldown(:class="{ 'dito-pulldown--open': pulldown.open }")
19+
ul.dito-pulldown(
20+
role="menu"
21+
:class="{ 'dito-pulldown--open': pulldown.open }"
22+
)
2023
li(
2124
v-for="(form, type) in creatableForms"
2225
v-show="shouldShowSchema(form)"
2326
)
2427
a.dito-pulldown__item(
28+
role="menuitem"
2529
:class=`{
2630
'dito-pulldown__item--disabled': shouldDisableSchema(form)
2731
}`

packages/admin/src/components/DitoDialog.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
.dito-dialog(
33
ref="dialog"
44
role="dialog"
5-
aria-expanded="true"
5+
:aria-label="schema.label || 'Dialog'"
66
aria-modal="true"
77
:style="{ '--width': settings.width ? `${settings.width}px` : null }"
88
@mouseup="onMouseUp"

packages/admin/src/components/DitoErrors.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<template lang="pug">
22
.dito-errors(
33
v-if="errors"
4+
role="alert"
45
)
56
ul
67
li(

packages/admin/src/components/DitoHeader.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template lang="pug">
2-
nav.dito-header
2+
nav.dito-header(:aria-busy="isLoading")
33
DitoTrail
44
DitoSpinner(
55
v-if="isLoading"

packages/admin/src/components/DitoMenu.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ ul.dito-menu(
1212
a.dito-menu__link(
1313
:href="getItemHref(item)"
1414
:class="{ 'dito-menu__link--active': isActiveItem(item) }"
15+
:aria-current="isActiveItem(item) ? 'page' : null"
1516
@click.prevent.stop="onClickItem(item)"
1617
) {{ getLabel(item) }}
1718
DitoMenu.dito-menu__sub(

packages/admin/src/components/DitoNotifications.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template lang="pug">
2-
.dito-notifications
2+
.dito-notifications(aria-live="polite")
33
.dito-header
44
span
55
.dito-notifications__inner

packages/admin/src/components/DitoScopes.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
button.dito-button(
1111
type="button"
1212
:class="{ 'dito-button--selected': scope.name === query.scope }"
13+
:aria-pressed="scope.name === query.scope"
1314
:title="scope.hint || getLabel(scope)"
1415
@click="navigate"
1516
) {{ getLabel(scope) }}

packages/admin/src/components/DitoSpinner.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<template lang="pug">
22
.dito-spinner(
33
v-show="loading"
4+
role="status"
5+
aria-label="Loading"
46
:style="{ '--color': color, '--size': size, '--margin': margin }"
57
)
68
.dito-spinner__pulse.dito-spinner__pulse1

packages/admin/src/components/DitoTableHead.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ thead.dito-table-head
66
)
77
th(
88
v-if="shouldRenderSchema(column)"
9+
scope="col"
910
:class="getColumnClass(column)"
1011
)
1112
RouterLink(
@@ -17,6 +18,7 @@ thead.dito-table-head
1718
button.dito-button(
1819
type="button"
1920
:class="getSortClass(column)"
21+
:aria-sort="getSortState(column)"
2022
@click="navigate"
2123
)
2224
.dito-button__order-arrows
@@ -64,6 +66,14 @@ export default DitoComponent.component('DitoTableHead', {
6466
: null
6567
},
6668
69+
getSortState(column) {
70+
const states = { asc: 'ascending', desc: 'descending' }
71+
return (
72+
states[this.sort.name === column.name && this.sort.order] ||
73+
'none'
74+
)
75+
},
76+
6777
getSortLink(column) {
6878
// Toggle order if the same column is clicked again.
6979
const order =

0 commit comments

Comments
 (0)