Skip to content

Commit c384f69

Browse files
Princesseuhdelucis
andauthoredDec 20, 2023
fix(a11y): Fix some audit false positives (#9483)
* fix(a11y): Fix some audit false positives * chore: changeset * Update packages/astro/src/runtime/client/dev-overlay/plugins/audit/a11y.ts Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> * fix: apply feedback * nit: add comment --------- Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
1 parent f6714f6 commit c384f69

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed
 

‎.changeset/thirty-panthers-repeat.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Fix some false positive in the audit logic of the dev toolbar

‎packages/astro/src/runtime/client/dev-overlay/plugins/audit/a11y.ts

+20-10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ const a11y_required_attributes = {
3838

3939
const interactiveElements = ['button', 'details', 'embed', 'iframe', 'label', 'select', 'textarea'];
4040

41+
const labellableElements = ['input', 'meter', 'output', 'progress', 'select', 'textarea'];
42+
4143
const aria_non_interactive_roles = [
4244
'alert',
4345
'alertdialog',
@@ -217,7 +219,7 @@ export const a11y: AuditRuleWithSelector[] = [
217219
code: 'a11y-aria-activedescendant-has-tabindex',
218220
title: 'Elements with attribute `aria-activedescendant` must be tabbable',
219221
message:
220-
'This element must either have an inherent `tabindex` or declare `tabindex` as an attribute.',
222+
'Element with the `aria-activedescendant` attribute must either have an inherent `tabindex` or declare `tabindex` as an attribute.',
221223
selector: '[aria-activedescendant]',
222224
match(element) {
223225
if (!(element as HTMLElement).tabIndex && !element.hasAttribute('tabindex')) return true;
@@ -280,14 +282,20 @@ export const a11y: AuditRuleWithSelector[] = [
280282
selector: 'a[href]:is([href=""], [href="#"], [href^="javascript:" i])',
281283
},
282284
{
283-
code: 'a11y-label-has-associated-control',
284-
title: '`label` tag should have an associated control and a text content.',
285+
code: 'a11y-invalid-label',
286+
title: '`label` element should have an associated control and a text content.',
285287
message:
286-
'The `label` tag must be associated with a control using either `for` or having a nested input. Additionally, the `label` tag must have text content.',
287-
selector: 'label:not([for])',
288-
match(element) {
289-
const inputChild = element.querySelector('input');
290-
if (!inputChild?.textContent) return true;
288+
'The `label` element must be associated with a control either by using the `for` attribute or by containing a nested form element. Additionally, the `label` element must have text content.',
289+
selector: 'label',
290+
match(element: HTMLLabelElement) {
291+
// Label must be associated with a control, either using `for` or having a nested valid element
292+
const hasFor = element.hasAttribute('for');
293+
const nestedLabellableElement = element.querySelector(`${labellableElements.join(', ')}`);
294+
if (!hasFor && !nestedLabellableElement) return true;
295+
296+
// Label must have text content, using innerText to ignore hidden text
297+
const innerText = element.innerText.trim();
298+
if (innerText === '') return true;
291299
},
292300
},
293301
{
@@ -347,8 +355,10 @@ export const a11y: AuditRuleWithSelector[] = [
347355
title: 'Missing content on element important for accessibility',
348356
message: 'Headings and anchors must have content to be accessible.',
349357
selector: a11y_required_content.join(','),
350-
match(element) {
351-
if (!element.textContent) return true;
358+
match(element: HTMLElement) {
359+
// innerText is used to ignore hidden text
360+
const innerText = element.innerText.trim();
361+
if (innerText === '') return true;
352362
},
353363
},
354364
{

0 commit comments

Comments
 (0)
Please sign in to comment.