Skip to content

Commit e0a8138

Browse files
authored
fix(a11y): label form controls, scope table headers, make KPI tiles real links (#301)
Closes four accessibility gates measured at origin/development with hydra-gates 48c88ba (gate-32: 3, gate-40: 7, gate-43: 10, gate-44: 1). gate-32 semantic-controls — the two KPI tiles hung @click on a plain <div> and MyMandatoryTrainingWidget's "Start" was an <a> with no href, so none of the three was in the tab order. All three now render a real link: the tiles pass CnStatsBlock its `route` prop (which renders a <router-link>) instead of `clickable` + a manual $router.push, and "Start" is a <router-link>. Middle-click and open-in-new-tab now work, which they never did. gate-40 form-label-association — 7 controls had only a placeholder, which is not a label. The two textareas that already sit under a visible <h3> are now associated with it via aria-labelledby rather than growing a second, duplicate visible label; the three controls with no visible text (an option row inside a v-for, a per-row cohort input in a table) get an aria-label naming their row. gate-43 table-headers — 41 <th> across 10 tables were all column headers in <thead>; each gets scope="col". No table has row headers. gate-44 autocomplete-attr — recipient-email is declared autocomplete="off", NOT "email": it collects a third party's address (an employer, a receiving school), never the signed-in user's own, so offering the user's own address is the wrong suggestion. Comment records the reasoning. No waivers, no excludes, no threshold changes. Each of the four gates was re-run with one fix reverted and confirmed to return to FAIL naming that exact item, so none of these passes is a gate that simply stopped looking.
1 parent 7b2324c commit e0a8138

17 files changed

Lines changed: 119 additions & 85 deletions

src/views/ConferenceScheduleBoard.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@
6060
<table v-else-if="waitlisted.length > 0" class="conference-schedule-board__table">
6161
<thead>
6262
<tr>
63-
<th>{{ t('scholiq', 'Learner') }}</th>
64-
<th>{{ t('scholiq', 'Requested teachers') }}</th>
65-
<th>{{ t('scholiq', 'Unmet') }}</th>
66-
<th>{{ t('scholiq', 'Manual placement') }}</th>
63+
<th scope="col">{{ t('scholiq', 'Learner') }}</th>
64+
<th scope="col">{{ t('scholiq', 'Requested teachers') }}</th>
65+
<th scope="col">{{ t('scholiq', 'Unmet') }}</th>
66+
<th scope="col">{{ t('scholiq', 'Manual placement') }}</th>
6767
</tr>
6868
</thead>
6969
<tbody>

src/views/CoursePackageImportView.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,11 @@
104104
<table class="course-package-import__table">
105105
<thead>
106106
<tr>
107-
<th>{{ t('scholiq', 'Title') }}</th>
108-
<th>{{ t('scholiq', 'Resource type') }}</th>
109-
<th>{{ t('scholiq', 'Outcome') }}</th>
110-
<th>{{ t('scholiq', 'Target') }}</th>
111-
<th>{{ t('scholiq', 'Reason') }}</th>
107+
<th scope="col">{{ t('scholiq', 'Title') }}</th>
108+
<th scope="col">{{ t('scholiq', 'Resource type') }}</th>
109+
<th scope="col">{{ t('scholiq', 'Outcome') }}</th>
110+
<th scope="col">{{ t('scholiq', 'Target') }}</th>
111+
<th scope="col">{{ t('scholiq', 'Reason') }}</th>
112112
</tr>
113113
</thead>
114114
<tbody>

src/views/ItemAuthorView.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
v-model="choice.label"
156156
class="item-author__input"
157157
type="text"
158+
:aria-label="t('scholiq', 'Text of option {n}', { n: idx + 1 })"
158159
:placeholder="t('scholiq', 'Option {n}', { n: idx + 1 })">
159160
<button
160161
class="item-author__remove-btn"

src/views/LearningRecordImportView.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@
107107
<table class="learning-record-import__table">
108108
<thead>
109109
<tr>
110-
<th>{{ t('scholiq', 'Title') }}</th>
111-
<th>{{ t('scholiq', 'Source schema') }}</th>
112-
<th>{{ t('scholiq', 'Outcome') }}</th>
113-
<th>{{ t('scholiq', 'Reason') }}</th>
110+
<th scope="col">{{ t('scholiq', 'Title') }}</th>
111+
<th scope="col">{{ t('scholiq', 'Source schema') }}</th>
112+
<th scope="col">{{ t('scholiq', 'Outcome') }}</th>
113+
<th scope="col">{{ t('scholiq', 'Reason') }}</th>
114114
</tr>
115115
</thead>
116116
<tbody>

src/views/MarkSubmissionView.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,12 @@
160160

161161
<!-- Feedback text -->
162162
<section class="mark-submission-view__feedback">
163-
<h3>{{ t('scholiq', 'Teacher feedback') }}</h3>
163+
<h3 id="mark-submission-feedback-label">{{ t('scholiq', 'Teacher feedback') }}</h3>
164164
<textarea
165+
id="mark-submission-feedback"
165166
v-model="feedbackText"
166167
class="mark-submission-view__feedback-input"
168+
aria-labelledby="mark-submission-feedback-label"
167169
:placeholder="t('scholiq', 'Write feedback for the learner...')"
168170
:disabled="saving"
169171
rows="5" />

src/views/MyLearningRecordView.vue

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@
147147
<table v-if="latestExport.coverageReport && latestExport.coverageReport.length" class="my-learning-record__table">
148148
<thead>
149149
<tr>
150-
<th>{{ t('scholiq', 'Source') }}</th>
151-
<th>{{ t('scholiq', 'Outcome') }}</th>
152-
<th>{{ t('scholiq', 'Reason') }}</th>
150+
<th scope="col">{{ t('scholiq', 'Source') }}</th>
151+
<th scope="col">{{ t('scholiq', 'Outcome') }}</th>
152+
<th scope="col">{{ t('scholiq', 'Reason') }}</th>
153153
</tr>
154154
</thead>
155155
<tbody>
@@ -179,7 +179,14 @@
179179
<input id="recipient-name" v-model="newShare.recipientName" type="text">
180180

181181
<label for="recipient-email">{{ t('scholiq', 'Recipient email (optional)') }}</label>
182-
<input id="recipient-email" v-model="newShare.recipientEmail" type="email">
182+
<!-- autocomplete="off", not "email": this collects a THIRD PARTY's address
183+
(an employer, a receiving school), never the signed-in user's own, so
184+
offering the user's own email here would be the wrong suggestion. -->
185+
<input
186+
id="recipient-email"
187+
v-model="newShare.recipientEmail"
188+
type="email"
189+
autocomplete="off">
183190

184191
<label for="expires-at">{{ t('scholiq', 'Expires on') }}</label>
185192
<input id="expires-at" v-model="newShare.expiresAt" type="date">
@@ -202,11 +209,11 @@
202209
<table v-if="shares.length" class="my-learning-record__table">
203210
<thead>
204211
<tr>
205-
<th>{{ t('scholiq', 'Recipient') }}</th>
206-
<th>{{ t('scholiq', 'Expires') }}</th>
207-
<th>{{ t('scholiq', 'Status') }}</th>
208-
<th>{{ t('scholiq', 'Verification link') }}</th>
209-
<th>{{ t('scholiq', 'Action') }}</th>
212+
<th scope="col">{{ t('scholiq', 'Recipient') }}</th>
213+
<th scope="col">{{ t('scholiq', 'Expires') }}</th>
214+
<th scope="col">{{ t('scholiq', 'Status') }}</th>
215+
<th scope="col">{{ t('scholiq', 'Verification link') }}</th>
216+
<th scope="col">{{ t('scholiq', 'Action') }}</th>
210217
</tr>
211218
</thead>
212219
<tbody>

src/views/OrderPaymentPanel.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@
5151
<table class="order-payment-panel__lines">
5252
<thead>
5353
<tr>
54-
<th>{{ t('scholiq', 'Description') }}</th>
55-
<th>{{ t('scholiq', 'Quantity') }}</th>
56-
<th>{{ t('scholiq', 'Amount') }}</th>
54+
<th scope="col">{{ t('scholiq', 'Description') }}</th>
55+
<th scope="col">{{ t('scholiq', 'Quantity') }}</th>
56+
<th scope="col">{{ t('scholiq', 'Amount') }}</th>
5757
</tr>
5858
</thead>
5959
<tbody>

src/views/PeerReviewMarkingView.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,12 @@
119119
</section>
120120

121121
<section class="peer-review-marking-view__comments">
122-
<h3>{{ t('scholiq', 'Comments for the author') }}</h3>
122+
<h3 id="peer-review-comments-label">{{ t('scholiq', 'Comments for the author') }}</h3>
123123
<textarea
124+
id="peer-review-comments"
124125
v-model="comments"
125126
class="peer-review-marking-view__comments-input"
127+
aria-labelledby="peer-review-comments-label"
126128
:placeholder="t('scholiq', 'Write feedback for the author...')"
127129
:disabled="saving"
128130
rows="5" />

src/views/RapportvergaderingReviewView.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@
5252
<table class="rapportvergadering-review__table">
5353
<thead>
5454
<tr>
55-
<th>{{ t('scholiq', 'Learner') }}</th>
56-
<th v-for="plan in subjectColumns" :key="plan.id">
55+
<th scope="col">{{ t('scholiq', 'Learner') }}</th>
56+
<th v-for="plan in subjectColumns" :key="plan.id" scope="col">
5757
{{ plan.label }}
5858
</th>
59-
<th>{{ t('scholiq', 'Mentor comment') }}</th>
60-
<th>{{ t('scholiq', 'Status') }}</th>
61-
<th>{{ t('scholiq', 'Actions') }}</th>
59+
<th scope="col">{{ t('scholiq', 'Mentor comment') }}</th>
60+
<th scope="col">{{ t('scholiq', 'Status') }}</th>
61+
<th scope="col">{{ t('scholiq', 'Actions') }}</th>
6262
</tr>
6363
</thead>
6464
<tbody>

src/views/RolloverWizard.vue

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@
4242
<table v-else-if="mappings.length > 0" class="rollover-wizard__table">
4343
<thead>
4444
<tr>
45-
<th>{{ t('scholiq', 'From cohort') }}</th>
46-
<th>{{ t('scholiq', 'Action') }}</th>
47-
<th>{{ t('scholiq', 'To cohort') }}</th>
45+
<th scope="col">{{ t('scholiq', 'From cohort') }}</th>
46+
<th scope="col">{{ t('scholiq', 'Action') }}</th>
47+
<th scope="col">{{ t('scholiq', 'To cohort') }}</th>
4848
</tr>
4949
</thead>
5050
<tbody>
@@ -58,7 +58,11 @@
5858
:aria-label-combobox="t('scholiq', 'Action')" />
5959
</td>
6060
<td>
61-
<input v-model="m.toCohortName" type="text" :placeholder="t('scholiq', 'New cohort name')">
61+
<input
62+
v-model="m.toCohortName"
63+
type="text"
64+
:aria-label="t('scholiq', 'New cohort name for {from}', { from: m.fromCohortId })"
65+
:placeholder="t('scholiq', 'New cohort name')">
6266
</td>
6367
</tr>
6468
</tbody>

0 commit comments

Comments
 (0)