Skip to content

Commit c0287d2

Browse files
rtibblesbotclaude
andcommitted
Fix label-has-for violations: associate labels with form controls
Wire label for/id pairs in device settings, facility import, setup wizard, and user auth forms. Add a visible label to the SearchBox input to satisfy vuejs-accessibility/label-has-for. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent a4db8c3 commit c0287d2

6 files changed

Lines changed: 47 additions & 41 deletions

File tree

kolibri/plugins/device/frontend/views/DeviceSettingsPage/index.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
</div>
4444

4545
<div class="fieldset">
46-
<label class="fieldset-label">{{ $tr('externalDeviceSettings') }}</label>
46+
<span class="fieldset-label">{{ $tr('externalDeviceSettings') }}</span>
4747
<KCheckbox
4848
:label="$tr('unlistedChannels')"
4949
:checked="allowPeerUnlistedChannelImport"
@@ -68,7 +68,7 @@
6868
</div>
6969

7070
<div class="fieldset">
71-
<label class="fieldset-label">{{ $tr('landingPageLabel') }}</label>
71+
<span class="fieldset-label">{{ $tr('landingPageLabel') }}</span>
7272
<KRadioButtonGroup>
7373
<KRadioButton
7474
data-testid="landingPageButton"
@@ -119,7 +119,7 @@
119119
class="fieldset"
120120
>
121121
<h2>
122-
<label>{{ $tr('allowDownloadOnMeteredConnection') }}</label>
122+
{{ $tr('allowDownloadOnMeteredConnection') }}
123123
</h2>
124124
<p :class="InfoDescriptionColor">
125125
{{ $tr('DownloadOnMeteredConnectionDescription') }}
@@ -205,7 +205,7 @@
205205

206206
<div class="fieldset">
207207
<h2>
208-
<label>{{ $tr('autoDownload') }}</label>
208+
{{ $tr('autoDownload') }}
209209
</h2>
210210
<KCheckbox
211211
:label="$tr('enableAutoDownload')"

kolibri/plugins/device/frontend/views/lodUsers/importUser/SelectFacilityPage.vue

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,10 @@
2121
:itemValue="x => x.id"
2222
/>
2323

24-
<label
25-
class="select-button-label"
26-
for="select-address-button"
27-
>
24+
<span class="select-button-label">
2825
{{ selectDifferentDeviceLabel$() }}
29-
</label>
26+
</span>
3027
<KButton
31-
id="select-address-button"
3228
appearance="basic-link"
3329
:text="getCommonSyncString('addNewAddressAction')"
3430
@click="showSelectAddressModal = true"

kolibri/plugins/facility/frontend/views/ImportCsvPage/Init.vue

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@
3333
{{ $tr('beforeCommitting') }}
3434
</p>
3535
<p>
36-
<label for="csv-file"> {{ $tr('proceed') }}</label>
37-
</p>
38-
<p>
39-
<input
40-
id="csv-file"
41-
ref="fileInput"
42-
type="file"
43-
accept=".csv"
44-
name="csv-file"
45-
@change="filesChanged"
46-
>
36+
<label for="csv-file">
37+
{{ $tr('proceed') }}
38+
<input
39+
id="csv-file"
40+
ref="fileInput"
41+
type="file"
42+
accept=".csv"
43+
name="csv-file"
44+
@change="filesChanged"
45+
>
46+
</label>
4747
</p>
4848
<!-- Temporarily remove this functionality for MVP -->
4949
<p v-if="false">

kolibri/plugins/setup_wizard/frontend/views/SelectFacilityForm.vue

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,10 @@
3333
:disabled="formDisabled"
3434
/>
3535

36-
<label
37-
class="select-button-label"
38-
for="select-address-button"
39-
>
36+
<span class="select-button-label">
4037
{{ selectDifferentDeviceLabel$() }}
41-
</label>
38+
</span>
4239
<KButton
43-
id="select-address-button"
4440
appearance="basic-link"
4541
:text="getCommonSyncString('addNewAddressAction')"
4642
@click="showSelectAddressModal = true"

kolibri/plugins/user_auth/frontend/views/SignInPage/PictureSignIn/PicturePasswordOption.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
option region clickable/activatable while keeping a single focusable element.
77
-->
88
<label
9+
:for="checkboxId"
910
class="option-label"
1011
:class="[
1112
$computedClass(optionLabelStyles),
@@ -20,6 +21,7 @@
2021
`aria-disabled` communicates the disabled state to assistive technology.
2122
-->
2223
<input
24+
:id="checkboxId"
2325
type="checkbox"
2426
class="visuallyhidden"
2527
:checked="isSelected"
@@ -79,6 +81,9 @@
7981
const $themeTokens = themeTokens();
8082
const $themePalette = themePalette();
8183
84+
// Unique per page because the parent (PicturePasswordGrid) renders each icon exactly once.
85+
const checkboxId = `picture-password-option-${props.icon}`;
86+
8287
const isSelected = computed(() => props.sequencePosition !== null);
8388
8489
// Colorful icons have a fixed colour built into the icon itself, so applying
@@ -149,6 +154,7 @@
149154
};
150155
151156
return {
157+
checkboxId,
152158
isSelected,
153159
iconColor,
154160
optionLabelStyles,

packages/kolibri-common/components/SearchBox.vue

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,37 @@
22

33
<form
44
class="search-box"
5+
role="search"
56
@submit.prevent="updateSearchQuery"
6-
@keydown.esc.prevent="handleEscKey"
77
>
88
<div
99
class="search-box-row"
10+
role="presentation"
1011
:style="{
1112
backgroundColor: $themeTokens.surface,
1213
borderColor: $themePalette.grey.v_400,
1314
maxWidth: maxWidth,
1415
fontSize: '16px',
1516
}"
17+
@keydown.esc.prevent="handleEscKey"
1618
>
1719
<label
18-
class="visuallyhidden"
19-
for="searchfield"
20-
>{{ coreString('searchLabel') }}</label>
21-
<input
22-
:id="id"
23-
ref="searchInput"
24-
v-model.trim="newSearchTerm"
25-
type="search"
26-
:disabled="disabled"
27-
class="search-input"
28-
:class="$computedClass(searchInputStyle)"
29-
dir="auto"
30-
:placeholder="computedPlaceholder"
20+
:for="id"
21+
class="search-label"
3122
>
23+
<span class="visuallyhidden">{{ coreString('searchLabel') }}</span>
24+
<input
25+
:id="id"
26+
ref="searchInput"
27+
v-model.trim="newSearchTerm"
28+
type="search"
29+
:disabled="disabled"
30+
class="search-input"
31+
:class="$computedClass(searchInputStyle)"
32+
dir="auto"
33+
:placeholder="computedPlaceholder"
34+
>
35+
</label>
3236
<div class="search-buttons-wrapper">
3337
<KIconButton
3438
icon="clear"
@@ -203,6 +207,10 @@
203207
border-radius: $radius;
204208
}
205209
210+
.search-label {
211+
display: contents;
212+
}
213+
206214
.search-input {
207215
display: table-cell;
208216
width: 100%;

0 commit comments

Comments
 (0)