Skip to content

Commit

Permalink
Merge pull request #8506 from cfpb/tccp/a11y
Browse files Browse the repository at this point in the history
TCCP: Tooltip accessibility improvements
  • Loading branch information
contolini authored Jul 15, 2024
2 parents 0448cfa + 359fdca commit c386919
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 54 deletions.
24 changes: 17 additions & 7 deletions cfgov/tccp/jinja2/tccp/includes/card_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,23 @@
<div class="o-card-group">
<div class="o-card-group__cards">
{%- for card in cards %}
{%- set card_purchase_apr = apr_range(
card.purchase_apr_for_tier_min,
card.purchase_apr_for_tier_max,
asterisk=true
) -%}
{%- set card_account_fee = currency(
card.annual_fee_estimated,
default=('See details' if card.annual_fee_estimated is none and card.periodic_fee_type else '$0')
) -%}
{%- set show_more = loop.index > 11 and ordering_by != 'product_name' -%}
<article class="m-card m-card--tabular{% if show_more %} u-show-more{% endif %}">
<a href="{{ card.url }}" data-js-hook="behavior_ignore-link-targets" data-ignore-link-targets="[data-tooltip]">
<a
href="{{ card.url }}"
data-js-hook="behavior_ignore-link-targets"
data-ignore-link-targets="[data-tooltip]"
aria-label="{{ card.product_name }} from {{ card.institution_name }} with {{ card_purchase_apr }} purchase APR, {{ card_account_fee }} account fee, {{ card_rewards(card) }} card rewards{%- if card.requirements_for_opening or card.issued_by_credit_union -%}, eligibility requirements{%- endif -%}"
>
<div class="m-card__heading-group">
<h2 class="h3 m-card__heading">{{ card.institution_name }}</h2>
<p class="m-card__subtitle">{{ card.product_name }}</p>
Expand Down Expand Up @@ -95,17 +109,13 @@ <h2 class="h3 m-card__heading">{{ card.institution_name }}</h2>
</div>
</dt>
<dd>
<strong>{{ apr_range(
card.purchase_apr_for_tier_min,
card.purchase_apr_for_tier_max,
asterisk=true
) }}</strong>
<strong>{{ card_purchase_apr }}</strong>
</dd>
</div>
<div class="m-data-spec m-data-spec--fee">
<dt><strong>Account fee</strong></dt>
<dd>
<strong>{{ currency(card.annual_fee_estimated, default=('See details' if card.annual_fee_estimated is none and card.periodic_fee_type else '$0')) }}</strong>
<strong>{{ card_account_fee }}</strong>
</dd>
</div>
<div class="m-data-spec m-data-spec--transfer">
Expand Down
5 changes: 5 additions & 0 deletions cfgov/unprocessed/apps/tccp/css/main.less
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@
padding: unit((20px / @base-font-size-px), rem);
background-color: var(--teal-10);

a {
border-color: var(--pacific-mid-dark);
color: var(--pacific-mid-dark);
}

p {
max-width: 100%;
}
Expand Down
50 changes: 4 additions & 46 deletions cfgov/unprocessed/apps/tccp/css/tooltip.less
Original file line number Diff line number Diff line change
@@ -1,58 +1,16 @@
@import (css) '../node_modules/tippy.js/dist/tippy.css';
@import (css) '../node_modules/tippy.js/dist/border.css';

// Custom theme, see https://kabbouchi.github.io/tippyjs-v4-docs/themes/
// Custom theme, see https://atomiks.github.io/tippyjs/v6/themes/
.tippy-box[data-theme='cfpb'] {
background-color: var(--gray-5);
background-clip: padding-box;
border: 1px solid var(--gray-40);
border-radius: 0;
color: var(--black);
padding: unit((15px / @base-font-size-px), rem);

&[data-placement^='top'] > .tippy-arrow {
&::before {
border-top-color: var(--white);
}
&::after {
border-top-color: rgba(0, 8, 16, 20%);
border-width: 7px 7px 0;
top: 17px;
left: 1px;
}
}

&[data-placement^='top'] > .tippy-svg-arrow > svg {
top: 16px;
}

&[data-placement^='top'] > .tippy-svg-arrow::after {
top: 17px;
}

> .tippy-backdrop {
background-color: var(--white);
}

> .tippy-arrow::after,
> .tippy-svg-arrow::after {
content: '';
position: absolute;
z-index: -1;
}

> .tippy-arrow::after {
border-color: transparent;
border-style: solid;
}

> .tippy-svg-arrow {
fill: var(--white);
&::after {
background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCA2czEuNzk2LS4wMTMgNC42Ny0zLjYxNUM1Ljg1MS45IDYuOTMuMDA2IDggMGMxLjA3LS4wMDYgMi4xNDguODg3IDMuMzQzIDIuMzg1QzE0LjIzMyA2LjAwNSAxNiA2IDE2IDZIMHoiIGZpbGw9InJnYmEoMCwgOCwgMTYsIDAuMikiLz48L3N2Zz4=');
background-size: 16px 6px;
width: 16px;
height: 6px;
}
.tippy-arrow {
color: var(--gray-5);
}

.tippy-heading {
Expand Down
22 changes: 22 additions & 0 deletions cfgov/unprocessed/apps/tccp/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,28 @@ function initializeTooltips() {
container.appendChild(node);
return container;
},
// See https://atomiks.github.io/tippyjs/v6/plugins/
plugins: [
{
name: 'hideOnEsc',
defaultValue: true,
fn({ hide }) {
function onKeyDown(event) {
if (event.keyCode === 27) {
hide();
}
}
return {
onShow() {
document.addEventListener('keydown', onKeyDown);
},
onHide() {
document.removeEventListener('keydown', onKeyDown);
},
};
},
},
],
});
}

Expand Down
Binary file added npm-packages-offline-cache/axe-core-4.9.1.tgz
Binary file not shown.
Binary file added npm-packages-offline-cache/cypress-axe-1.5.0.tgz
Binary file not shown.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
"@cfpb/cfpb-typography": "1.3.2",
"@cypress/skip-test": "2.6.1",
"autoprefixer": "10.4.19",
"axe-core": "4.9.1",
"cfpb-chart-builder": "6.5.0",
"cypress-axe": "1.5.0",
"esbuild": "0.23.0",
"fancy-log": "2.0.0",
"highcharts": "7.2.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,9 @@ export class ExploreCreditCards {
selectCheckboxFilter(name, value) {
cy.get(`input[name=${name}]`).check(value, { force: true });
}

checkA11y() {
cy.injectAxe();
cy.checkA11y();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('Explore credit cards landing page', () => {
exploreCards.openFilterExpandable();

cy.get('#id_rewards input').should('be.checked');
exploreCards.checkA11y();
});

it("should show an error message if a location isn't selected", () => {
Expand All @@ -24,6 +25,7 @@ describe('Explore credit cards landing page', () => {
exploreCards.clickSubmitButton();

cy.get('.a-form-alert__text').should('be.visible');
exploreCards.checkA11y();

exploreCards.selectLocation('NY');

Expand All @@ -45,13 +47,23 @@ describe('Explore credit cards results page', () => {
it('should not follow card links when tooltips are clicked', () => {
exploreCards.openResultsPage();

cy.get('.m-card--tabular [data-tooltip]').first().click();
cy.get('.m-card--tabular [data-tooltip]').first().trigger('mouseenter');

cy.get('h1').contains('Explore credit cards').should('exist');
cy.get('h2')
.contains('Purchase interest rate and fees')
.should('not.exist');
});
it('should close tooltips when escape key is pressed', () => {
exploreCards.openResultsPage();

cy.get('.m-card--tabular [data-tooltip]').first().trigger('mouseenter');
cy.get('div.tippy-heading').should('be.visible');

cy.get('.m-card--tabular [data-tooltip]').first().type('{esc}');
cy.wait(1000);
cy.get('div.tippy-heading').should('not.exist');
});
it('should not follow card links when tooltips are open', () => {
exploreCards.openResultsPage();

Expand Down Expand Up @@ -92,6 +104,7 @@ describe('Explore credit cards results page', () => {
exploreCards.selectOrdering('Purchase APR');
cy.get('.htmx-container.htmx-request').should('not.exist');
cy.get('#u-show-more-fade').should('be.visible');
exploreCards.checkA11y();

exploreCards.selectOrdering('Card name');
cy.get('.htmx-container.htmx-request').should('not.exist');
Expand Down Expand Up @@ -159,6 +172,7 @@ describe('Explore credit card details page', () => {
.and('contain', 'credit_tier=Credit+score+of+720+or+greater')
.and('contain', 'location=NY')
.and('contain', 'situations=Earn+rewards');
exploreCards.checkA11y();
});
it('should have a breadcrumb to full list if the user never filtered', () => {
exploreCards.openResultsPage();
Expand Down
3 changes: 3 additions & 0 deletions test/cypress/support/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ require('@cypress/skip-test/support');

// Fail Cypress tests fast on the first failure.
import 'cypress-fail-fast';

// Initialize a11y plugin https://github.com/component-driven/cypress-axe
import 'cypress-axe';
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1478,6 +1478,11 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==

[email protected]:
version "4.9.1"
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.9.1.tgz#fcd0f4496dad09e0c899b44f6c4bb7848da912ae"
integrity sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==

axe-core@=4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf"
Expand Down Expand Up @@ -1952,6 +1957,11 @@ cssstyle@^2.3.0:
dependencies:
cssom "~0.3.6"

[email protected]:
version "1.5.0"
resolved "https://registry.yarnpkg.com/cypress-axe/-/cypress-axe-1.5.0.tgz#95082734583da77b51ce9b7784e14a442016c7a1"
integrity sha512-Hy/owCjfj+25KMsecvDgo4fC/781ccL+e8p+UUYoadGVM2ogZF9XIKbiM6KI8Y3cEaSreymdD6ZzccbI2bY0lQ==

[email protected]:
version "7.1.0"
resolved "https://registry.yarnpkg.com/cypress-fail-fast/-/cypress-fail-fast-7.1.0.tgz#36e28e39fffaacf852b4866c8459e5274eb8326d"
Expand Down

0 comments on commit c386919

Please sign in to comment.