Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixrule(element_tabbable_visible): Reduce "Needs review" on custom checkbox and radio buttons #1848

Merged
merged 7 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export let element_tabbable_visible: Rule = {
"en-US": {
"group": "A tabbable element should be visible on the screen when it has keyboard focus",
"pass": "The tabbable element is visible on the screen",
"potential_visible": "Confirm the element should be tabbable, and is visible on the screen when it has keyboard focus"
"potential_visible": "Confirm the element should be tabbable and if so, it becomes visible when it has keyboard focus"
}
},
rulesets: [{
Expand All @@ -58,11 +58,32 @@ export let element_tabbable_visible: Rule = {
const defined_styles = getDefinedStyles(ruleContext);
const onfocus_styles = getDefinedStyles(ruleContext, ":focus");

if (bounds['height'] === 0 || bounds['width'] === 0
|| (defined_styles['position']==='absolute' && defined_styles['clip'] && defined_styles['clip'].replaceAll(' ', '')==='rect(0px,0px,0px,0px)'
&& !onfocus_styles['clip']))
if (bounds['height'] === 0 || bounds['width'] === 0)
return RulePotential("potential_visible", []);

if (defined_styles['position']==='absolute' && defined_styles['clip'] && defined_styles['clip'].replaceAll(' ', '')==='rect(0px,0px,0px,0px)'
&& !onfocus_styles['clip']) {
/**
* note that A user can select a checkbox and radio button by selecting the button or the label text.
* When a checkbox or radio button is clipped to 0 size, it is still available to a keyboard or a screen reader.
* The rule should be passed if the label text exists and the button on-focus style is defined by the user,
* which likely incurs the changes of the label style.
*/
if (nodeName === 'input' && (ruleContext.getAttribute('type')==='checkbox' || ruleContext.getAttribute('type')==='radio')) {
const label = RPTUtil.getLabelForElement(ruleContext);
if (label && !RPTUtil.isInnerTextEmpty(label)) {
const focus_styles = getDefinedStyles(ruleContext, ":focus");
const focus_visible_styles = getDefinedStyles(ruleContext, ":focus-visible");
const focus_within_styles = getDefinedStyles(ruleContext, ":focus-within");
const checked_styles = getDefinedStyles(ruleContext, ":checked");

if (focus_styles || focus_visible_styles || focus_within_styles || checked_styles)
return RulePass("pass");
}
}
return RulePotential("potential_visible", []);
}

if (bounds['top'] >= 0 && bounds['left'] >= 0)
return RulePass("pass");

Expand Down
5 changes: 4 additions & 1 deletion accessibility-checker-engine/src/v4/util/CSSUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,14 @@ export function getComputedStyle(elem: HTMLElement, pseudoElt?: PseudoClass) {
* for example, for 'transform: rotate(2.5deg);', the computed style returns 'matrix(-0.0436194, 0.999048, -0.999048, -0.0436194, 0, 0)'
* and the defined style returns 'rotate(2.5deg)'
*
* change the type of the parameter pseudoClass from PseudoClass to string to include both pseudo classes (e.g., :focus, :checked)
* and pseudo elements (e.g., ::before, ::after).
*
* @param {HTMLElement} elem
* @param {string} [pseudoClass] If specified, will return values that are different
* than when the pseudoClass does not match.
*/
export function getDefinedStyles(elem: HTMLElement, pseudoClass?: PseudoClass) {
export function getDefinedStyles(elem: HTMLElement, pseudoClass?: string ) {
// console.log("Function: getDefinedStyles");
let definedStyles = {};
let definedStylePseudo = {};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<!--
/******************************************************************************
Copyright:: 2020- IBM, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*****************************************************************************/
-->

<html lang="en">

<head>
<title>Test Example</title>
<style>
.catalog--checkbox {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
white-space: nowrap;
border: 1px;
visibility: inherit;
clip: rect(0,0,0,0);
display: block;

}

.catalog--checkbox-label-text::before {
position: absolute;
top: 0.125rem;
left: 0;
width: 1rem;
height: 1rem;
border: 1px solid var(--cds-icon-01, #161616);
margin: 0.125rem 0.125rem 0.125rem 0.1875rem;
background-color: rgba(0,0,0,0);
border-radius: 1px;
display:block;
content: "";
}

</style>
</head>

<body>

<div>
<input type="checkbox" class="catalog--checkbox" id="catalog">
<label for="catalog" class="catalog--checkbox-label-text">iOS</label>
</div>
<script>
UnitTest = {
ruleIds: ["element_tabbable_visible"],
results: [
{
"ruleId": "element_tabbable_visible",
"value": [
"INFORMATION",
"PASS"
],
"path": {
"dom": "/html[1]/body[1]/div[1]/input[1]",
"aria": "/document[1]/checkbox[1]"
},
"reasonId": "pass",
"message": "The tabbable element is visible on the screen",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
}
]
}
</script>

</body>

</html>
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"aria": "/document[1]/button[1]"
},
"reasonId": "potential_visible",
"message": "Confirm the element should be tabbable, and is visible on the screen when it has keyboard focus",
"message": "Confirm the element should be tabbable and if so, it becomes visible when it has keyboard focus",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
Expand All @@ -78,7 +78,7 @@
"aria": "/document[1]/link[1]"
},
"reasonId": "potential_visible",
"message": "Confirm the element should be tabbable, and is visible on the screen when it has keyboard focus",
"message": "Confirm the element should be tabbable and if so, it becomes visible when it has keyboard focus",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ <h3>Elements Tests</h3>
"aria": "/document[1]/button[1]"
},
"reasonId": "potential_visible",
"message": "Confirm the element should be tabbable, and is visible on the screen when it has keyboard focus",
"message": "Confirm the element should be tabbable and if so, it becomes visible when it has keyboard focus",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
Expand All @@ -65,7 +65,7 @@ <h3>Elements Tests</h3>
"aria": "/document[1]/link[1]"
},
"reasonId": "potential_visible",
"message": "Confirm the element should be tabbable, and is visible on the screen when it has keyboard focus",
"message": "Confirm the element should be tabbable and if so, it becomes visible when it has keyboard focus",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"aria": "/document[1]/link[1]"
},
"reasonId": "potential_visible",
"message": "Confirm the element should be tabbable, and is visible on the screen when it has keyboard focus",
"message": "Confirm the element should be tabbable and if so, it becomes visible when it has keyboard focus",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
UnitTest = {
ruleIds: ["element_tabbable_visible"],
results: [
{
{
"ruleId": "element_tabbable_visible",
"value": [
"INFORMATION",
Expand All @@ -58,11 +58,11 @@
"aria": "/document[1]/link[1]"
},
"reasonId": "potential_visible",
"message": "Confirm the element should be tabbable, and is visible on the screen when it has keyboard focus",
"message": "Confirm the element should be tabbable and if so, it becomes visible when it has keyboard focus",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
}
}
]
}
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ <h3>Elements Tests</h3>
"aria": "/document[1]/button[1]"
},
"reasonId": "potential_visible",
"message": "Confirm the element should be tabbable, and is visible on the screen when it has keyboard focus",
"message": "Confirm the element should be tabbable and if so, it becomes visible when it has keyboard focus",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
Expand All @@ -81,7 +81,7 @@ <h3>Elements Tests</h3>
"aria": "/document[1]/button[2]"
},
"reasonId": "potential_visible",
"message": "Confirm the element should be tabbable, and is visible on the screen when it has keyboard focus",
"message": "Confirm the element should be tabbable and if so, it becomes visible when it has keyboard focus",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<!--
/******************************************************************************
Copyright:: 2020- IBM, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*****************************************************************************/
-->

<html lang="en">

<head>
<title>Test Example</title>
<style>
.catalog--radio {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;

}

.catalog--radio-label-text {
flex: auto;
background-color: #FFF;
color: #1E69A6;
text-align: center;
padding: 4px 8px;
border: 1px solid #999CA0;
border-radius: 0;
transition: all 0.2s ease-in-out;
}

</style>
</head>

<body>

<div>
<input type="radio" class="catalog--radio" id="catalog">
<label for="catalog" class="catalog--radio-label-text">iOS</label>
</div>
<script>
UnitTest = {
ruleIds: ["element_tabbable_visible"],
results: [
{
"ruleId": "element_tabbable_visible",
"value": [
"INFORMATION",
"PASS"
],
"path": {
"dom": "/html[1]/body[1]/div[1]/input[1]",
"aria": "/document[1]/radio[1]"
},
"reasonId": "pass",
"message": "The tabbable element is visible on the screen",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
}
]
}
</script>

</body>

</html>
Loading