diff --git a/cfgov/tccp/jinja2/tccp/includes/card_list.html b/cfgov/tccp/jinja2/tccp/includes/card_list.html
index d9eb192df1c..a697155ad82 100644
--- a/cfgov/tccp/jinja2/tccp/includes/card_list.html
+++ b/cfgov/tccp/jinja2/tccp/includes/card_list.html
@@ -51,9 +51,23 @@
Account fee
- {{ currency(card.annual_fee_estimated, default=('See details' if card.annual_fee_estimated is none and card.periodic_fee_type else '$0')) }}
+ {{ card_account_fee }}
diff --git a/cfgov/unprocessed/apps/tccp/css/main.less b/cfgov/unprocessed/apps/tccp/css/main.less
index dc59233037a..e8b7cdd7664 100644
--- a/cfgov/unprocessed/apps/tccp/css/main.less
+++ b/cfgov/unprocessed/apps/tccp/css/main.less
@@ -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%;
}
diff --git a/cfgov/unprocessed/apps/tccp/css/tooltip.less b/cfgov/unprocessed/apps/tccp/css/tooltip.less
index 8fb2d61db9c..7b0923d7f9d 100644
--- a/cfgov/unprocessed/apps/tccp/css/tooltip.less
+++ b/cfgov/unprocessed/apps/tccp/css/tooltip.less
@@ -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 {
diff --git a/cfgov/unprocessed/apps/tccp/js/index.js b/cfgov/unprocessed/apps/tccp/js/index.js
index 86600419fa8..8da2b8ab029 100644
--- a/cfgov/unprocessed/apps/tccp/js/index.js
+++ b/cfgov/unprocessed/apps/tccp/js/index.js
@@ -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);
+ },
+ };
+ },
+ },
+ ],
});
}
diff --git a/npm-packages-offline-cache/axe-core-4.9.1.tgz b/npm-packages-offline-cache/axe-core-4.9.1.tgz
new file mode 100644
index 00000000000..71bf23cd5ec
Binary files /dev/null and b/npm-packages-offline-cache/axe-core-4.9.1.tgz differ
diff --git a/npm-packages-offline-cache/cypress-axe-1.5.0.tgz b/npm-packages-offline-cache/cypress-axe-1.5.0.tgz
new file mode 100644
index 00000000000..fcd3a10b09f
Binary files /dev/null and b/npm-packages-offline-cache/cypress-axe-1.5.0.tgz differ
diff --git a/package.json b/package.json
index 6e5c856e2ce..2cf4a5d74b0 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/test/cypress/integration/consumer-tools/credit-cards/explore-cards-helpers.cy.js b/test/cypress/integration/consumer-tools/credit-cards/explore-cards-helpers.cy.js
index 5fae2ea32bb..c889308bba1 100644
--- a/test/cypress/integration/consumer-tools/credit-cards/explore-cards-helpers.cy.js
+++ b/test/cypress/integration/consumer-tools/credit-cards/explore-cards-helpers.cy.js
@@ -79,4 +79,9 @@ export class ExploreCreditCards {
selectCheckboxFilter(name, value) {
cy.get(`input[name=${name}]`).check(value, { force: true });
}
+
+ checkA11y() {
+ cy.injectAxe();
+ cy.checkA11y();
+ }
}
diff --git a/test/cypress/integration/consumer-tools/credit-cards/explore-cards.cy.js b/test/cypress/integration/consumer-tools/credit-cards/explore-cards.cy.js
index d17363eb3c4..82adada82f5 100644
--- a/test/cypress/integration/consumer-tools/credit-cards/explore-cards.cy.js
+++ b/test/cypress/integration/consumer-tools/credit-cards/explore-cards.cy.js
@@ -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", () => {
@@ -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');
@@ -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();
@@ -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');
@@ -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();
diff --git a/test/cypress/support/e2e.js b/test/cypress/support/e2e.js
index dc37e4f826a..b123d3832c4 100644
--- a/test/cypress/support/e2e.js
+++ b/test/cypress/support/e2e.js
@@ -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';
diff --git a/yarn.lock b/yarn.lock
index 14054623637..5b67d2741fa 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -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==
+axe-core@4.9.1:
+ 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"
@@ -1952,6 +1957,11 @@ cssstyle@^2.3.0:
dependencies:
cssom "~0.3.6"
+cypress-axe@1.5.0:
+ 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==
+
cypress-fail-fast@7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/cypress-fail-fast/-/cypress-fail-fast-7.1.0.tgz#36e28e39fffaacf852b4866c8459e5274eb8326d"