mirror of
https://github.com/withastro/astro.git
synced 2025-03-03 22:57:08 -05:00
fix(toolbar): add anchor element to interactive elements (#10343)
* fix(toolbar): add anchor element to interactive elements * chore: apply better logic * add test
This commit is contained in:
parent
e88eeb0337
commit
f973aa9110
4 changed files with 57 additions and 1 deletions
5
.changeset/tough-moose-prove.md
Normal file
5
.changeset/tough-moose-prove.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"astro": patch
|
||||
---
|
||||
|
||||
Fixes some false positive in the dev toolbar a11y audits, by adding the `a` element to the list of interactive elements.
|
|
@ -43,4 +43,18 @@ test.describe('Dev Toolbar - Audits', () => {
|
|||
// Toggle app off
|
||||
await appButton.click();
|
||||
});
|
||||
|
||||
test('does not warn for non-interactive element', async ({ page, astro }) => {
|
||||
await page.goto(astro.resolveUrl('/a11y-exceptions'));
|
||||
|
||||
const toolbar = page.locator('astro-dev-toolbar');
|
||||
const appButton = toolbar.locator('button[data-app-id="astro:audit"]');
|
||||
await appButton.click();
|
||||
|
||||
const auditCanvas = toolbar.locator('astro-dev-toolbar-app-canvas[data-app-id="astro:audit"]');
|
||||
const auditHighlights = auditCanvas.locator('astro-dev-toolbar-highlight');
|
||||
|
||||
const count = await auditHighlights.count();
|
||||
expect(count).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
|
||||
---
|
||||
|
||||
|
||||
<input role="button" aria-label="Label"/>
|
|
@ -42,7 +42,25 @@ const a11y_required_attributes = {
|
|||
object: ['title', 'aria-label', 'aria-labelledby'],
|
||||
};
|
||||
|
||||
const interactiveElements = ['button', 'details', 'embed', 'iframe', 'label', 'select', 'textarea'];
|
||||
const MAYBE_INTERACTIVE = new Map([
|
||||
['a', 'href'],
|
||||
['input', 'type'],
|
||||
['audio', 'controls'],
|
||||
['img', 'usemap'],
|
||||
['object', 'usemap'],
|
||||
['video', 'controls'],
|
||||
]);
|
||||
|
||||
const interactiveElements = [
|
||||
'button',
|
||||
'details',
|
||||
'embed',
|
||||
'iframe',
|
||||
'label',
|
||||
'select',
|
||||
'textarea',
|
||||
...MAYBE_INTERACTIVE.keys(),
|
||||
];
|
||||
|
||||
const labellableElements = ['input', 'meter', 'output', 'progress', 'select', 'textarea'];
|
||||
|
||||
|
@ -187,6 +205,15 @@ const ariaRoles = new Set(
|
|||
)
|
||||
);
|
||||
|
||||
function isInteractive(element: Element): boolean {
|
||||
const attribute = MAYBE_INTERACTIVE.get(element.localName);
|
||||
if (attribute) {
|
||||
return element.hasAttribute(attribute);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export const a11y: AuditRuleWithSelector[] = [
|
||||
{
|
||||
code: 'a11y-accesskey',
|
||||
|
@ -434,6 +461,7 @@ export const a11y: AuditRuleWithSelector[] = [
|
|||
'Interactive HTML elements like `<a>` and `<button>` cannot use non-interactive roles like `heading`, `list`, `menu`, and `toolbar`.',
|
||||
selector: `[role]:is(${interactiveElements.join(',')})`,
|
||||
match(element) {
|
||||
if (!isInteractive(element)) return false;
|
||||
const role = element.getAttribute('role');
|
||||
if (!role) return false;
|
||||
if (!ariaRoles.has(role)) return false;
|
||||
|
@ -448,6 +476,7 @@ export const a11y: AuditRuleWithSelector[] = [
|
|||
'Interactive roles should not be used to convert a non-interactive element to an interactive element',
|
||||
selector: `[role]:not(${interactiveElements.join(',')})`,
|
||||
match(element) {
|
||||
if (!isInteractive(element)) return false;
|
||||
const role = element.getAttribute('role');
|
||||
if (!role) return false;
|
||||
if (!ariaRoles.has(role)) return false;
|
||||
|
@ -472,6 +501,8 @@ export const a11y: AuditRuleWithSelector[] = [
|
|||
element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
|
||||
if (isScrollable) return false;
|
||||
|
||||
if (!isInteractive(element)) return false;
|
||||
|
||||
if (!interactiveElements.includes(element.localName)) return true;
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue