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

Color accessibility tests #342

Merged
merged 11 commits into from
Mar 19, 2018
22 changes: 18 additions & 4 deletions source/pages/colors.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Heading from '@atoms/Heading/Heading';
import Rhythm from '@atoms/Rhythm/Rhythm';
import SgPageWrapper from '@sg-atoms/SgPageWrapper/SgPageWrapper';
import SgColorSwatch from '@sg-molecules/SgColorSwatch/SgColorSwatch';
import { SgColorSwatch, SgColorSwatch__search } from '@sg-molecules/SgColorSwatch/SgColorSwatch';
import {
SgPageShell,
SgPageShell__header,
Expand All @@ -26,9 +26,23 @@ const page = () => (
<Rhythm>
<Heading>Fuzzy Chainsaw Colors</Heading>
<p>
We run two accessibility tests based on the <a href="https://www.w3.org/TR/WCAG20/">WCAG 2.0 Standards</a> for web content.
For each font color defined within the project, we test color contrast to the AA Standard for the defined “normal” (14pt/18px) and “large” (18pt/24px) font sizes.
We run 2 Accessibility tests based on the <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast">WCAG 2.0 contrast ratio formula</a>. The WCAG 2.0 formula differentiates between text smaller than 18pt/24px, text larger than 18pt (or text that is bold and larger than 14pt/19px).
</p>
<p>For AA compliance, text should have a ratio of at least 4.5:1 (larger text, at least 3:1). For AAA compliance, text should have a ratio of at least 7:1 (larger text, at least 4.5:1).
For each font color in the project, we test to the AA Standard for &#34;normal&#34; and &#34;large&#34; font size categories.
</p>
</Rhythm>
<Rhythm>
<select className="SgColorSwatch__controls SgColorSwatch__controls--level">
<option value=".SgColorSwatch__accessibility--double" defaultValue>AA</option>
<option value=".SgColorSwatch__accessibility--triple">AAA</option>
</select>
<select className="SgColorSwatch__controls SgColorSwatch__controls--weight">
<option value=".SgColorSwatch__accessibility__badge--normal" defaultValue>normal (14pt)</option>
<option value=".SgColorSwatch__accessibility__badge--large--bold">large-bold (18pt)</option>
<option value=".SgColorSwatch__accessibility__badge--large">large (18pt)</option>
</select>
<SgColorSwatch__search type="search" name="ColorSearch" placeholder="Search for colors(s)" />
</Rhythm>
<br />
<SgColorSwatch />
Expand All @@ -39,6 +53,6 @@ const page = () => (
);

page.pageTitle = 'Style Guide | Colors';
page.pageType = 'styleguide';
page.pageType = 'index';

export default page;
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ const runWCAGTest = (ratio, size, level) => {
case 'AA':
if (size === 'large' && ratio > 3) {
return 'PASS';
} else if (size === 'large--bold' && ratio > 3) {
return 'PASS';
} else if (size === 'normal' && ratio > 4.5) {
return 'PASS';
}
Expand All @@ -77,6 +79,8 @@ const runWCAGTest = (ratio, size, level) => {
case 'AAA':
if (size === 'large' && ratio > 4.5) {
return 'PASS';
} else if (size === 'large--bold' && ratio > 4.5) {
return 'PASS';
} else if (size === 'normal' && ratio > 7) {
return 'PASS';
}
Expand All @@ -92,5 +96,84 @@ const runWCAGTest = (ratio, size, level) => {
}
};

/* Binds the events to UI controls for color accessibility testing. */
const initControls = () => {
const level = document.querySelector('.SgColorSwatch__controls--level');
const weight = document.querySelector('.SgColorSwatch__controls--weight');

const double = document.querySelectorAll('.SgColorSwatch__accessibility--double');
const triple = document.querySelectorAll('.SgColorSwatch__accessibility--triple');
const normal = document.querySelectorAll('.SgColorSwatch__accessibility__badge--normal');
const largeBold = document.querySelectorAll('.SgColorSwatch__accessibility__badge--large--bold');
const large = document.querySelectorAll('.SgColorSwatch__accessibility__badge--large');

module.exports = { createObject, getContrast, runWCAGTest };
const search = document.querySelector('.SgColorSwatch__search');

let i = double.length;
let j = largeBold.length;

while (i--) {
triple[i].style.display = 'none';
}

while (j--) {
largeBold[j].style.display = 'none';
large[j].style.display = 'none';
}

const churn = () => {
const weightSelector = document.querySelectorAll(weight.options[weight.options.selectedIndex].value);
const levelSelector = document.querySelectorAll(level.options[level.options.selectedIndex].value);

let m = weightSelector.length;
while (m--) {
normal[m].style.display = 'none';
largeBold[m].style.display = 'none';
large[m].style.display = 'none';
weightSelector[m].removeAttribute('style');
}

let l = levelSelector.length;
while (l--) {
double[l].style.display = 'none';
triple[l].style.display = 'none';
levelSelector[l].removeAttribute('style');
}
};

level.addEventListener('change', () => {
churn();
});

weight.addEventListener('change', () => {
churn();
});

search.addEventListener('keyup', (e) => {
const query = e.target.value;
const colors = document.querySelectorAll('.SgColorSwatch');
let o = colors.length;
// unable to consolidate to single loop
if (query.length === 0) {
while (o--) {
colors[o].style.display = '';
}
} else {
while (o--) {
if (!colors[o].dataset.colorName.toLowerCase().match(query.toLowerCase())) {
colors[o].style.display = 'none';
} else {
colors[o].style.display = '';
}
}
}
});
};


module.exports = {
createObject,
getContrast,
runWCAGTest,
initControls
};
41 changes: 27 additions & 14 deletions source/styleguide/molecules/SgColorSwatch/SgColorSwatch.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,45 @@
border: 1px solid var(--sg-color-gray);
box-shadow: 1px 0.25em 1em -0.33em color(var(--sg-color-black) alpha(15%));
display: flex;
flex-basis: 300px;
flex-basis: 200px;
flex-direction: column;
justify-content: flex-end;
margin: 0 0.5rem 2rem 3rem;
min-height: 300px;

&__controls {
padding: 0.5rem;

+ .SgColorSwatch__controls {
margin-left: 0.5rem;
}

&.SgColorSwatch__search {
max-width: 250px;
width: 100%;
}
}
}

.SgColorSwatch__panel {
background-color: var(--sg-color-white);
border-top: 1px solid var(--sg-color-gray);
display: flex;
flex-wrap: wrap;
font-size: 0.85rem;
flex-direction: column;
padding: 2rem;

& > * {
padding: 0.5rem 1rem 0 0;
}

&__title {
width: 60%;
}

&__hex {
width: 40%;
}

&__rgb {
width: 100%;
}
}

.SgColorSwatch__wrapper {
align-items: flex-start;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
justify-content: space-between;
}

.SgColorSwatch__accessibility {
Expand Down Expand Up @@ -74,16 +77,26 @@
}

&--normal {
&::before {
font-size: 12pt;
left: calc(50% - 5px);
}
}

&--large--bold {
&::before {
font-size: 14pt;
font-weight: bold;
left: calc(50% - 5px);
top: -1.45em;
}
}

&--large {
&::before {
font-size: 18pt;
left: calc(50% - 8px);
top: -1.35em;
}
}
}
Expand Down
22 changes: 20 additions & 2 deletions source/styleguide/molecules/SgColorSwatch/SgColorSwatch.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import SgHeading from '@sg-atoms/SgHeading/SgHeading';
import { createObject, getContrast, runWCAGTest } from './SgColorSwatch.Container';
import { createObject, getContrast, runWCAGTest, initControls } from './SgColorSwatch.Container';
import colorVars from './SgColorSwatch__Colors.json';

export const SgColorSwatch = (props) => {
Expand Down Expand Up @@ -27,15 +27,20 @@ export const SgColorSwatch = (props) => {
const contrastPrimary = getContrast(obj.hex, colorVars.colorTextPrimary);
const contrastSecondary = getContrast(obj.hex, colorVars.colorTextSecondary);

setTimeout(() => {
initControls();
});

return (
<Tag
key={i}
className={classStack}
{...attrs}
data-color-name={title}
style={{ backgroundColor: obj.hex }}
>
<SgColorSwatch__accessibility contrastPrimary={contrastPrimary} contrastSecondary={contrastSecondary} level="AA" />
<SgColorSwatch__accessibility variant="no-badge" contrastPrimary={contrastPrimary} contrastSecondary={contrastSecondary} level="AAA" />
<SgColorSwatch__accessibility contrastPrimary={contrastPrimary} contrastSecondary={contrastSecondary} level="AAA" />

<SgColorSwatch__panel>
<div className="SgColorSwatch__panel__title">
Expand Down Expand Up @@ -103,12 +108,18 @@ const SgColorSwatch__accessibility = (props) => {
<div className="SgColorSwatch__accessibility__badge SgColorSwatch__accessibility__badge--primary SgColorSwatch__accessibility__badge--normal">
{runWCAGTest(contrastPrimary, 'normal', level)}
</div>
<div className="SgColorSwatch__accessibility__badge SgColorSwatch__accessibility__badge--primary SgColorSwatch__accessibility__badge--large--bold">
{runWCAGTest(contrastPrimary, 'large--bold', level)}
</div>
<div className="SgColorSwatch__accessibility__badge SgColorSwatch__accessibility__badge--primary SgColorSwatch__accessibility__badge--large">
{runWCAGTest(contrastPrimary, 'large', level)}
</div>
<div className="SgColorSwatch__accessibility__badge SgColorSwatch__accessibility__badge--secondary SgColorSwatch__accessibility__badge--normal">
{runWCAGTest(contrastSecondary, 'normal', level)}
</div>
<div className="SgColorSwatch__accessibility__badge SgColorSwatch__accessibility__badge--secondary SgColorSwatch__accessibility__badge--large--bold">
{runWCAGTest(contrastSecondary, 'large--bold', level)}
</div>
<div className="SgColorSwatch__accessibility__badge SgColorSwatch__accessibility__badge--secondary SgColorSwatch__accessibility__badge--large">
{runWCAGTest(contrastSecondary, 'large', level)}
</div>
Expand Down Expand Up @@ -149,4 +160,11 @@ const SgColorSwatch__panel = FcUtils.createBasicComponent({
}
});

export const SgColorSwatch__search = FcUtils.createBasicComponent({
name: 'SgColorSwatch__controls SgColorSwatch__search',
defaultProps: {
tagName: 'input'
}
});

export default SgColorSwatch;