From c121f71e3c8aaa64e8a7dd2c0e06672f48a521eb Mon Sep 17 00:00:00 2001 From: A Cottrill Date: Mon, 5 Aug 2024 14:31:56 -0400 Subject: [PATCH 01/14] feat(UI): create night mode --- config/i18n/locales/english/links.json | 7 + config/i18n/locales/english/translations.json | 11 +- package-lock.json | 35 +++ package.json | 3 + src/_includes/assets/css/global.css | 284 +++++++++++++++++- src/_includes/assets/css/screen.css | 34 +-- src/_includes/assets/css/search-bar.css | 2 +- src/_includes/assets/js/dark-mode.js | 32 ++ src/_includes/assets/js/dropdown.js | 17 ++ src/_includes/layouts/default.njk | 4 + src/_includes/partials/site-nav.njk | 89 ++++-- 11 files changed, 477 insertions(+), 41 deletions(-) create mode 100644 src/_includes/assets/js/dark-mode.js create mode 100644 src/_includes/assets/js/dropdown.js diff --git a/config/i18n/locales/english/links.json b/config/i18n/locales/english/links.json index 8e31b3b5a..e2378fa36 100644 --- a/config/i18n/locales/english/links.json +++ b/config/i18n/locales/english/links.json @@ -13,5 +13,12 @@ "support": "https://www.freecodecamp.org/news/support/", "honesty": "https://www.freecodecamp.org/news/academic-honesty-policy/", "coc": "https://www.freecodecamp.org/news/code-of-conduct/" + }, + "nav": { + "contribute": "https://contribute.freecodecamp.org/#/", + "forum": "https://forum.freecodecamp.org/", + "learn": "https://www.freecodecamp.org/learn", + "news": "https://freecodecamp.org/news/", + "podcast": "https://freecodecamp.libsyn.com/" } } diff --git a/config/i18n/locales/english/translations.json b/config/i18n/locales/english/translations.json index 826f3ea6d..c7927bd31 100644 --- a/config/i18n/locales/english/translations.json +++ b/config/i18n/locales/english/translations.json @@ -2,7 +2,11 @@ "buttons": { "forum": "Forum", "donate": "Donate", - "load-more-articles": "Load More Articles" + "menu": "Menu", + "news": "News", + "curriculum": "Curriculum", + "load-more-articles": "Load More Articles", + "toggle-dark-mode": "Night Mode" }, "search": { "label": "Search", @@ -94,5 +98,8 @@ "audio": "audio", "video": "video" }, - "ad-text": "Advertisement" + "ad-text": "Advertisement", + "aria": { + "opens-new-window": "Opens in new window" + } } diff --git a/package-lock.json b/package-lock.json index a6cee097c..c2992e40f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "eleventy-news", "version": "1.0.0", "license": "BSD-3-Clause", + "dependencies": { + "@fortawesome/free-solid-svg-icons": "^6.6.0" + }, "devDependencies": { "@11ty/eleventy": "2.0.1", "@11ty/eleventy-plugin-rss": "1.2.0", @@ -1177,6 +1180,25 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.6.0.tgz", + "integrity": "sha512-xyX0X9mc0kyz9plIyryrRbl7ngsA9jz77mCZJsUkLl+ZKs0KWObgaEBoSgQiYWAsSmjz/yjl0F++Got0Mdp4Rw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.6.0.tgz", + "integrity": "sha512-IYv/2skhEDFc2WGUcqvFJkeK39Q+HyPf5GHUrT/l2pKbtgEIv1al1TKd6qStR5OIwQdN1GZP54ci3y4mroJWjA==", + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.6.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@glimmer/env": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/@glimmer/env/-/env-0.1.7.tgz", @@ -13295,6 +13317,19 @@ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true }, + "@fortawesome/fontawesome-common-types": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.6.0.tgz", + "integrity": "sha512-xyX0X9mc0kyz9plIyryrRbl7ngsA9jz77mCZJsUkLl+ZKs0KWObgaEBoSgQiYWAsSmjz/yjl0F++Got0Mdp4Rw==" + }, + "@fortawesome/free-solid-svg-icons": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.6.0.tgz", + "integrity": "sha512-IYv/2skhEDFc2WGUcqvFJkeK39Q+HyPf5GHUrT/l2pKbtgEIv1al1TKd6qStR5OIwQdN1GZP54ci3y4mroJWjA==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.6.0" + } + }, "@glimmer/env": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/@glimmer/env/-/env-0.1.7.tgz", diff --git a/package.json b/package.json index 556d054e4..339ef1f04 100644 --- a/package.json +++ b/package.json @@ -105,5 +105,8 @@ }, "lint-staged": { "**/*": "prettier --write --ignore-unknown" + }, + "dependencies": { + "@fortawesome/free-solid-svg-icons": "^6.6.0" } } diff --git a/src/_includes/assets/css/global.css b/src/_includes/assets/css/global.css index 465def02f..4c7616919 100644 --- a/src/_includes/assets/css/global.css +++ b/src/_includes/assets/css/global.css @@ -4,7 +4,6 @@ :root { /* Colours */ --dark-blue: #002ead; - --theme-color: #0a0a23; --gray90: #0a0a23; --gray85: #1b1b32; --gray80: #2a2a40; @@ -15,7 +14,28 @@ --gray05: #eeeef0; --gray00: #fff; --header-height: 38px; - --blue-dark: #002ead; +} + +body { + --primary-color: var(--gray90); + --secondary-color: var(--gray85); + --tertiary-color: var(--gray80); + --quaternary-color: var(--gray75); + --quaternary-background: var(--gray15); + --tertiary-background: var(--gray10); + --secondary-background: var(--gray05); + --primary-background: var(--gray00); +} + +body.dark-mode { + --primary-color: var(--gray00); + --secondary-color: var(--gray05); + --tertiary-color: var(--gray10); + --quaternary-color: var(--gray15); + --quaternary-background: var(--gray75); + --tertiary-background: var(--gray80); + --secondary-background: var(--gray85); + --primary-background: var(--gray90); } /* Fonts @@ -295,7 +315,7 @@ body { font-style: normal; letter-spacing: 0; text-rendering: optimizeLegibility; - background: #fff; + background: var(--primary-background); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; @@ -494,3 +514,261 @@ h6 { font-size: 1.4rem; font-weight: 500; } + +/** + * Site header menu list + */ +.nav-list { + background-color: var(--gray90); + display: none; + justify-content: flex-end; + list-style: none; + padding: 0; + position: absolute; + right: 0; + width: 100%; +} + +@media (min-width: 980px) { + .nav-list { + max-width: 15rem; + } +} + +/** + * Site header language list + */ +.lang-button-nav[aria-expanded='true'] + .nav-list { + -ms-overflow-style: none; + display: block; + max-height: calc(100vh - var(--header-height)); + overflow-y: auto; + scrollbar-width: none; + top: calc(var(--header-height)); +} + +.lang-button-nav[aria-expanded='true'] + .nav-list::-webkit-scrollbar { + display: none; +} + +@media (min-width: 601px) { + [dir='rtl'] .nav-list { + right: auto; + left: 0; + } +} + +/** + * Site header language list + */ +.lang-button-nav[aria-expanded='true'] + .nav-list { + -ms-overflow-style: none; + display: block; + max-height: calc(100vh - var(--header-height)); + overflow-y: auto; + scrollbar-width: none; + top: calc(var(--header-height)); +} + +.lang-button-nav[aria-expanded='true'] + .nav-list::-webkit-scrollbar { + display: none; +} + +/* WCAG fix */ +.sr-only { + color: white; + background-color: black; +} + +/** + * Site header sub menu items + */ +.nav-link { + padding: 2px 15px 0; + display: flex; + align-items: center; + color: var(--gray00); + background-color: var(--gray90); + white-space: normal; + min-height: var(--header-sub-element-size); + width: 100%; + border: none; + height: 100%; +} + +.nav-link:focus { + outline-offset: -3px; +} + +.nav-link:focus:not(:focus-visible) { + background-color: inherit; + color: inherit; +} + +.nav-link:not([aria-disabled='true']):hover, +.nav-link:focus-visible { + color: var(--gray90); + background-color: var(--gray10); +} + +.nav-link:not([aria-disabled='true']):hover { + text-decoration: none; + cursor: pointer; + outline-color: transparent !important; +} + +button.nav-link[aria-disabled='true'] { + background-color: inherit; +} + +li > button.nav-link-signout:not([aria-disabled='true']):is(:hover, :focus) { + background-color: var(--danger-background); + color: var(--danger-color); +} + +.nav-link .fa-external-link-alt { + color: var(--gray45); +} + +.nav-link-supporter { + color: var(--yellow-light); + background: var(--yellow-dark); +} + +.nav-link-supporter:hover, +.nav-link-supporter:active, +.nav-link-supporter:focus, +.nav-link-supporter:focus-visible { + color: var(--yellow-dark) !important; + background: var(--yellow-light) !important; +} + +.nav-link-supporter svg { + height: auto; + width: 1em; +} + +/** + * Check mark for current language + */ +.nav-lang-list-option[aria-current='true'] { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='32' height='32' preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16'%3E%3Cg fill='white'%3E%3Cpath d='M12.736 3.97a.733.733 0 0 1 1.047 0c.286.289.29.756.01 1.05L7.88 12.01a.733.733 0 0 1-1.065.02L3.217 8.384a.757.757 0 0 1 0-1.06a.733.733 0 0 1 1.047 0l3.052 3.093l5.4-6.425a.247.247 0 0 1 .02-.022z'%3E%3C/path%3E%3C/g%3E%3C/svg%3E"); + background-size: 1.2rem; + background-position: calc(100% - 10px) center; + background-repeat: no-repeat; +} + +.nav-lang-list-option[aria-current='true']:hover, +.nav-lang-list-option[aria-current='true']:focus-visible { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='32' height='32' preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16'%3E%3Cg fill='currentColor'%3E%3Cpath d='M12.736 3.97a.733.733 0 0 1 1.047 0c.286.289.29.756.01 1.05L7.88 12.01a.733.733 0 0 1-1.065.02L3.217 8.384a.757.757 0 0 1 0-1.06a.733.733 0 0 1 1.047 0l3.052 3.093l5.4-6.425a.247.247 0 0 1 .02-.022z'%3E%3C/path%3E%3C/g%3E%3C/svg%3E") !important; +} + +/** + * Site navigation first level CTA's + */ +.exposed-button-nav, +.lang-button-nav { + align-items: center; + background-color: var(--gray90); + border: 1px solid var(--gray00); + color: var(--gray00); + display: flex; + font-size: 18px; + height: var(--header-element-size); + justify-content: center; + min-width: var(--header-element-size); + padding: 0 4px; +} + +@media (min-width: 601px) { + .exposed-button-nav { + padding-inline: 12px; + } +} + +.exposed-button-nav:hover, +.exposed-button-nav:hover:focus { + border: 1px solid var(--gray00); +} + +.exposed-button-nav:is( + :hover, + :hover:focus, + [aria-expanded='true'], + [aria-expanded='true']:hover + ), +.lang-button-nav:is( + :hover, + :hover:focus, + [aria-expanded='true'], + [aria-expanded='false'].force-show + ) { + background-color: var(--gray00); + color: var(--gray90); +} + +/** + * Text and icon handling for first level CTA's + * + * Login btn icon is used in other places different from the site navigation + * and is expected to not to be displayed. The default is to hide the element + * but on the site navigation display it only on small viewports. + */ +.login-btn-icon { + display: none; +} + +#toggle-button-nav .menu-btn-text, +#universal-nav .login-btn-text { + display: none; +} + +@media (min-width: 601px) { + #toggle-button-nav .menu-btn-text, + #universal-nav .login-btn-text { + display: inline-block; + } +} + +#toggle-button-nav .menu-btn-icon, +#universal-nav .login-btn-icon { + display: inline-block; +} + +@media (min-width: 601px) { + #toggle-button-nav .menu-btn-icon, + #universal-nav .login-btn-icon { + display: none; + } +} + +/** + * Link items with icon or checkboxes + */ +.nav-link-flex { + display: flex; + justify-content: space-between; +} + +.display-menu { + -ms-overflow-style: none; + display: block; + max-height: calc( + 100vh - var(--header-height) - var(--header-sub-element-size) + ); + overflow-y: auto; + scrollbar-width: none; + text-align: left; + top: calc(var(--header-height) + var(--header-sub-element-size)); +} + +@media (min-width: 980px) { + .display-menu { + max-height: calc(100vh - var(--header-height)); + top: var(--header-height); + } +} + +.display-menu::-webkit-scrollbar { + display: none; +} diff --git a/src/_includes/assets/css/screen.css b/src/_includes/assets/css/screen.css index 8401de3b6..a3f035af6 100644 --- a/src/_includes/assets/css/screen.css +++ b/src/_includes/assets/css/screen.css @@ -34,7 +34,7 @@ on every page through _includes/layouts/default.njk /* ---------------------------------------------------------- */ body { - background: #fff; + background: var(--primary-background); } .img { @@ -104,7 +104,7 @@ body { z-index: 1000; color: #fff; width: 100%; - background: var(--theme-color); + background: var(--gray90); font-family: 'Lato', sans-serif; font-display: swap; } @@ -180,7 +180,7 @@ body { font-family: Lato, sans-serif; font-display: swap; height: var(--header-height); - background: var(--theme-color); + background: var(--gray90); position: fixed; z-index: 1000; color: #fff; @@ -263,7 +263,7 @@ a.nav-forum, a.nav-forum:hover, .nav li a:hover { background: white; - color: var(--theme-color); + color: var(--primary-color); text-decoration: none; } @@ -302,7 +302,7 @@ a.nav-forum { background-color: #feac32; background-image: linear-gradient(#fecc4c, #ffac33); border: 3px solid #feac32; - color: var(--theme-color); + color: var(--primary-color); } .toggle-button-nav:hover, @@ -312,7 +312,7 @@ a.nav-forum { border-width: 3px; border-color: #f1a02a; background-image: none; - color: var(--theme-color); + color: var(--primary-color); text-decoration: none; } @@ -378,7 +378,7 @@ a.nav-forum { .rss-button svg { margin-bottom: 1px; height: 2.1rem; - fill: #fff; + fill: var(--primary-background); } @media (max-width: 999px) { @@ -442,7 +442,7 @@ a.nav-forum { overflow: hidden; margin: 0 20px 50px; min-height: 100px; - background: #fff center center; + background: var(--primary-background) center center; background-size: cover; } @@ -474,7 +474,7 @@ a.nav-forum { .post-card-tags a { margin-bottom: 1.3rem; - color: var(--gray75); + color: var(--quaternary-color); font-size: 1.5rem; line-height: 1.15em; font-weight: 500; @@ -583,7 +583,7 @@ a.nav-forum { margin: 0 -5px; width: 34px; height: 34px; - border: #fff 2px solid; + border: var(--primary-background) 2px solid; } .moving-avatar { @@ -592,7 +592,7 @@ a.nav-forum { margin: 0 -6px; width: 56px; height: 56px; - border: #fff 2px solid; + border: var(--primary-background) 2px solid; transition: all 0.5s cubic-bezier(0.4, 0.01, 0.165, 0.99) 0.7s; } @@ -614,7 +614,7 @@ a.nav-forum { .reading-time { flex-shrink: 0; margin-left: 20px; - color: var(--gray75); + color: var(--quaternary-color); font-size: 1.2rem; line-height: 20px; font-weight: 500; @@ -722,7 +722,7 @@ make sure this only happens on large viewports / desktop-ish devices. .post-template.site-main, .page-template.site-main { padding-bottom: 4vw; - background: #fff; + background: var(--primary-background); } .post-full { @@ -1954,8 +1954,8 @@ p:has(mjx-container.MathJax) { /* ---------------------------------------------------------- */ .site-footer { - color: var(--gray85); - background: var(--gray05); + color: var(--secondary-color); + background: var(--primary-background); line-height: 1.6; padding: 40px 15px; font-size: 16px; @@ -1985,7 +1985,7 @@ p:has(mjx-container.MathJax) { } .site-footer a { - color: var(--gray85); + color: var(--secondary-color); text-decoration: none; padding: 2px; } @@ -2271,7 +2271,7 @@ a.cta-button { a.banner { position: fixed; top: var(--header-height); - background-color: var(--blue-dark); + background-color: var(--dark-blue); align-items: center; justify-content: center; font-size: 14px; diff --git a/src/_includes/assets/css/search-bar.css b/src/_includes/assets/css/search-bar.css index 240ae920f..a124e40a0 100644 --- a/src/_includes/assets/css/search-bar.css +++ b/src/_includes/assets/css/search-bar.css @@ -205,7 +205,7 @@ a:active { /* Show default colors if disabled */ .disabled:hover { - background: #eeeef0; + background: var(--secondary-background); color: #0a0a23; } diff --git a/src/_includes/assets/js/dark-mode.js b/src/_includes/assets/js/dark-mode.js new file mode 100644 index 000000000..43d45dd64 --- /dev/null +++ b/src/_includes/assets/js/dark-mode.js @@ -0,0 +1,32 @@ +function loadDarkModePreference() { + const darkMode = localStorage.getItem('fcc-dark-mode'); + if ( + darkMode === 'enabled' || + window.matchMedia('(prefers-color-scheme: dark)').matches + ) { + document.body.classList.add('dark-mode'); + document + .getElementById('dark-mode-enabled') + .classList.replace('fa-square', 'fa-square-check'); + } +} + +document.addEventListener('DOMContentLoaded', () => { + loadDarkModePreference(); + document + .getElementById('toggle-dark-mode') + .addEventListener('click', function () { + document.body.classList.toggle('dark-mode'); + if (document.body.classList.contains('dark-mode')) { + document + .getElementById('dark-mode-enabled') + .classList.replace('fa-square', 'fa-square-check'); + localStorage.setItem('fcc-dark-mode', 'enabled'); + } else { + document + .getElementById('dark-mode-enabled') + .classList.replace('fa-square-check', 'fa-square'); + localStorage.setItem('fcc-dark-mode', 'disabled'); + } + }); +}); diff --git a/src/_includes/assets/js/dropdown.js b/src/_includes/assets/js/dropdown.js new file mode 100644 index 000000000..c5de13edd --- /dev/null +++ b/src/_includes/assets/js/dropdown.js @@ -0,0 +1,17 @@ +let displayMenu = false; + +document.addEventListener('DOMContentLoaded', () => { + document + .getElementById('toggle-button-nav') + .addEventListener('click', function () { + document.getElementById('nav-list').classList.toggle('display-menu'); + document.getElementById('nav-list').ariaExpanded = String(displayMenu); + }); + + /* + document.getElementById('toggle-button-nav').addEventListener('blur', function () { + document.getElementById('nav-list')?.classList.remove("display-menu"); + document.getElementById('nav-list').ariaExpanded = "false"; + }); + */ +}); diff --git a/src/_includes/layouts/default.njk b/src/_includes/layouts/default.njk index c40e9b444..52fa20ab4 100644 --- a/src/_includes/layouts/default.njk +++ b/src/_includes/layouts/default.njk @@ -33,6 +33,8 @@ + {# Font Awesome assets #} + {# Day.js and plugins for localization and formatting #} @@ -48,6 +50,8 @@ {% include "assets/js/search-bar.js" %} {% include "assets/js/client-dayjs.js" %} {% include "assets/js/cookie-checker.js" %} + {% include "assets/js/dark-mode.js" %} + {% include "assets/js/dropdown.js" %} {% endset %} diff --git a/src/_includes/partials/site-nav.njk b/src/_includes/partials/site-nav.njk index bafbe7344..9f6c358a5 100644 --- a/src/_includes/partials/site-nav.njk +++ b/src/_includes/partials/site-nav.njk @@ -6,23 +6,76 @@ + From dcee346a932d07cbff3b5b167dccb8ec14e291d1 Mon Sep 17 00:00:00 2001 From: A Cottrill Date: Wed, 7 Aug 2024 13:38:37 -0400 Subject: [PATCH 02/14] feat: convert Cypress tests to Typescript --- .../landing/{landing.cy.js => landing.cy.ts} | 0 .../e2e/chinese/post/{ads.cy.js => ads.cy.ts} | 0 .../chinese/post/{post.cy.js => post.cy.ts} | 0 .../e2e/english/404/{404.cy.js => 404.cy.ts} | 0 .../english/404/{i18n.cy.js => i18n.cy.ts} | 0 .../author/{author.cy.js => author.cy.ts} | 0 .../english/author/{i18n.cy.js => i18n.cy.ts} | 0 .../english/author/{meta.cy.js => meta.cy.ts} | 0 .../english/author/{rss.cy.js => rss.cy.ts} | 0 ...tured-data.cy.js => structured-data.cy.ts} | 0 .../landing/{i18n.cy.js => i18n.cy.ts} | 0 .../landing/{landing.cy.js => landing.cy.ts} | 2 +- .../landing/{meta.cy.js => meta.cy.ts} | 0 ...cy.js => original-author-translator.cy.ts} | 0 .../english/landing/{rss.cy.js => rss.cy.ts} | 0 ...tured-data.cy.js => structured-data.cy.ts} | 0 .../english/page/{meta.cy.js => meta.cy.ts} | 0 .../english/page/{page.cy.js => page.cy.ts} | 0 ...tured-data.cy.js => structured-data.cy.ts} | 0 .../e2e/english/post/{ads.cy.js => ads.cy.ts} | 0 .../english/post/{i18n.cy.js => i18n.cy.ts} | 0 .../english/post/{meta.cy.js => meta.cy.ts} | 0 ...cy.js => original-author-translator.cy.ts} | 0 .../english/post/{post.cy.js => post.cy.ts} | 8 ++-- ...tured-data.cy.js => structured-data.cy.ts} | 0 .../search-results/{meta.cy.js => meta.cy.ts} | 0 ...rch-results.cy.js => search-results.cy.ts} | 2 +- .../english/tag/{i18n.cy.js => i18n.cy.ts} | 0 .../english/tag/{meta.cy.js => meta.cy.ts} | 0 .../e2e/english/tag/{rss.cy.js => rss.cy.ts} | 0 ...tured-data.cy.js => structured-data.cy.ts} | 0 .../e2e/english/tag/{tag.cy.js => tag.cy.ts} | 0 .../landing/{landing.cy.js => landing.cy.ts} | 0 ...cy.js => original-author-translator.cy.ts} | 0 cypress/support/{commands.js => commands.ts} | 0 cypress/support/{e2e.js => e2e.ts} | 0 .../utils/{post-cards.js => post-cards.ts} | 0 cypress/support/utils/{rss.js => rss.ts} | 0 package-lock.json | 46 ++++++++++++++----- package.json | 4 +- tsconfig.json | 13 ++++++ 41 files changed, 57 insertions(+), 18 deletions(-) rename cypress/e2e/chinese/landing/{landing.cy.js => landing.cy.ts} (100%) rename cypress/e2e/chinese/post/{ads.cy.js => ads.cy.ts} (100%) rename cypress/e2e/chinese/post/{post.cy.js => post.cy.ts} (100%) rename cypress/e2e/english/404/{404.cy.js => 404.cy.ts} (100%) rename cypress/e2e/english/404/{i18n.cy.js => i18n.cy.ts} (100%) rename cypress/e2e/english/author/{author.cy.js => author.cy.ts} (100%) rename cypress/e2e/english/author/{i18n.cy.js => i18n.cy.ts} (100%) rename cypress/e2e/english/author/{meta.cy.js => meta.cy.ts} (100%) rename cypress/e2e/english/author/{rss.cy.js => rss.cy.ts} (100%) rename cypress/e2e/english/author/{structured-data.cy.js => structured-data.cy.ts} (100%) rename cypress/e2e/english/landing/{i18n.cy.js => i18n.cy.ts} (100%) rename cypress/e2e/english/landing/{landing.cy.js => landing.cy.ts} (98%) rename cypress/e2e/english/landing/{meta.cy.js => meta.cy.ts} (100%) rename cypress/e2e/english/landing/{original-author-translator.cy.js => original-author-translator.cy.ts} (100%) rename cypress/e2e/english/landing/{rss.cy.js => rss.cy.ts} (100%) rename cypress/e2e/english/landing/{structured-data.cy.js => structured-data.cy.ts} (100%) rename cypress/e2e/english/page/{meta.cy.js => meta.cy.ts} (100%) rename cypress/e2e/english/page/{page.cy.js => page.cy.ts} (100%) rename cypress/e2e/english/page/{structured-data.cy.js => structured-data.cy.ts} (100%) rename cypress/e2e/english/post/{ads.cy.js => ads.cy.ts} (100%) rename cypress/e2e/english/post/{i18n.cy.js => i18n.cy.ts} (100%) rename cypress/e2e/english/post/{meta.cy.js => meta.cy.ts} (100%) rename cypress/e2e/english/post/{original-author-translator.cy.js => original-author-translator.cy.ts} (100%) rename cypress/e2e/english/post/{post.cy.js => post.cy.ts} (97%) rename cypress/e2e/english/post/{structured-data.cy.js => structured-data.cy.ts} (100%) rename cypress/e2e/english/search-results/{meta.cy.js => meta.cy.ts} (100%) rename cypress/e2e/english/search-results/{search-results.cy.js => search-results.cy.ts} (97%) rename cypress/e2e/english/tag/{i18n.cy.js => i18n.cy.ts} (100%) rename cypress/e2e/english/tag/{meta.cy.js => meta.cy.ts} (100%) rename cypress/e2e/english/tag/{rss.cy.js => rss.cy.ts} (100%) rename cypress/e2e/english/tag/{structured-data.cy.js => structured-data.cy.ts} (100%) rename cypress/e2e/english/tag/{tag.cy.js => tag.cy.ts} (100%) rename cypress/e2e/espanol/landing/{landing.cy.js => landing.cy.ts} (100%) rename cypress/e2e/espanol/landing/{original-author-translator.cy.js => original-author-translator.cy.ts} (100%) rename cypress/support/{commands.js => commands.ts} (100%) rename cypress/support/{e2e.js => e2e.ts} (100%) rename cypress/support/utils/{post-cards.js => post-cards.ts} (100%) rename cypress/support/utils/{rss.js => rss.ts} (100%) create mode 100644 tsconfig.json diff --git a/cypress/e2e/chinese/landing/landing.cy.js b/cypress/e2e/chinese/landing/landing.cy.ts similarity index 100% rename from cypress/e2e/chinese/landing/landing.cy.js rename to cypress/e2e/chinese/landing/landing.cy.ts diff --git a/cypress/e2e/chinese/post/ads.cy.js b/cypress/e2e/chinese/post/ads.cy.ts similarity index 100% rename from cypress/e2e/chinese/post/ads.cy.js rename to cypress/e2e/chinese/post/ads.cy.ts diff --git a/cypress/e2e/chinese/post/post.cy.js b/cypress/e2e/chinese/post/post.cy.ts similarity index 100% rename from cypress/e2e/chinese/post/post.cy.js rename to cypress/e2e/chinese/post/post.cy.ts diff --git a/cypress/e2e/english/404/404.cy.js b/cypress/e2e/english/404/404.cy.ts similarity index 100% rename from cypress/e2e/english/404/404.cy.js rename to cypress/e2e/english/404/404.cy.ts diff --git a/cypress/e2e/english/404/i18n.cy.js b/cypress/e2e/english/404/i18n.cy.ts similarity index 100% rename from cypress/e2e/english/404/i18n.cy.js rename to cypress/e2e/english/404/i18n.cy.ts diff --git a/cypress/e2e/english/author/author.cy.js b/cypress/e2e/english/author/author.cy.ts similarity index 100% rename from cypress/e2e/english/author/author.cy.js rename to cypress/e2e/english/author/author.cy.ts diff --git a/cypress/e2e/english/author/i18n.cy.js b/cypress/e2e/english/author/i18n.cy.ts similarity index 100% rename from cypress/e2e/english/author/i18n.cy.js rename to cypress/e2e/english/author/i18n.cy.ts diff --git a/cypress/e2e/english/author/meta.cy.js b/cypress/e2e/english/author/meta.cy.ts similarity index 100% rename from cypress/e2e/english/author/meta.cy.js rename to cypress/e2e/english/author/meta.cy.ts diff --git a/cypress/e2e/english/author/rss.cy.js b/cypress/e2e/english/author/rss.cy.ts similarity index 100% rename from cypress/e2e/english/author/rss.cy.js rename to cypress/e2e/english/author/rss.cy.ts diff --git a/cypress/e2e/english/author/structured-data.cy.js b/cypress/e2e/english/author/structured-data.cy.ts similarity index 100% rename from cypress/e2e/english/author/structured-data.cy.js rename to cypress/e2e/english/author/structured-data.cy.ts diff --git a/cypress/e2e/english/landing/i18n.cy.js b/cypress/e2e/english/landing/i18n.cy.ts similarity index 100% rename from cypress/e2e/english/landing/i18n.cy.js rename to cypress/e2e/english/landing/i18n.cy.ts diff --git a/cypress/e2e/english/landing/landing.cy.js b/cypress/e2e/english/landing/landing.cy.ts similarity index 98% rename from cypress/e2e/english/landing/landing.cy.js rename to cypress/e2e/english/landing/landing.cy.ts index 5de3d7926..e6194dbde 100644 --- a/cypress/e2e/english/landing/landing.cy.js +++ b/cypress/e2e/english/landing/landing.cy.ts @@ -48,7 +48,7 @@ describe('Landing', () => { 'Learn Responsive Web Design by Building 20 Projects – a Major freeCodeCamp Curriculum Update' ) .parentsUntil('article') - .find(selectors.authorProfileImage) + .find(selectors.authorProfileImage) .then($el => expect($el[0].alt).to.equal('Quincy Larson')); }); diff --git a/cypress/e2e/english/landing/meta.cy.js b/cypress/e2e/english/landing/meta.cy.ts similarity index 100% rename from cypress/e2e/english/landing/meta.cy.js rename to cypress/e2e/english/landing/meta.cy.ts diff --git a/cypress/e2e/english/landing/original-author-translator.cy.js b/cypress/e2e/english/landing/original-author-translator.cy.ts similarity index 100% rename from cypress/e2e/english/landing/original-author-translator.cy.js rename to cypress/e2e/english/landing/original-author-translator.cy.ts diff --git a/cypress/e2e/english/landing/rss.cy.js b/cypress/e2e/english/landing/rss.cy.ts similarity index 100% rename from cypress/e2e/english/landing/rss.cy.js rename to cypress/e2e/english/landing/rss.cy.ts diff --git a/cypress/e2e/english/landing/structured-data.cy.js b/cypress/e2e/english/landing/structured-data.cy.ts similarity index 100% rename from cypress/e2e/english/landing/structured-data.cy.js rename to cypress/e2e/english/landing/structured-data.cy.ts diff --git a/cypress/e2e/english/page/meta.cy.js b/cypress/e2e/english/page/meta.cy.ts similarity index 100% rename from cypress/e2e/english/page/meta.cy.js rename to cypress/e2e/english/page/meta.cy.ts diff --git a/cypress/e2e/english/page/page.cy.js b/cypress/e2e/english/page/page.cy.ts similarity index 100% rename from cypress/e2e/english/page/page.cy.js rename to cypress/e2e/english/page/page.cy.ts diff --git a/cypress/e2e/english/page/structured-data.cy.js b/cypress/e2e/english/page/structured-data.cy.ts similarity index 100% rename from cypress/e2e/english/page/structured-data.cy.js rename to cypress/e2e/english/page/structured-data.cy.ts diff --git a/cypress/e2e/english/post/ads.cy.js b/cypress/e2e/english/post/ads.cy.ts similarity index 100% rename from cypress/e2e/english/post/ads.cy.js rename to cypress/e2e/english/post/ads.cy.ts diff --git a/cypress/e2e/english/post/i18n.cy.js b/cypress/e2e/english/post/i18n.cy.ts similarity index 100% rename from cypress/e2e/english/post/i18n.cy.js rename to cypress/e2e/english/post/i18n.cy.ts diff --git a/cypress/e2e/english/post/meta.cy.js b/cypress/e2e/english/post/meta.cy.ts similarity index 100% rename from cypress/e2e/english/post/meta.cy.js rename to cypress/e2e/english/post/meta.cy.ts diff --git a/cypress/e2e/english/post/original-author-translator.cy.js b/cypress/e2e/english/post/original-author-translator.cy.ts similarity index 100% rename from cypress/e2e/english/post/original-author-translator.cy.js rename to cypress/e2e/english/post/original-author-translator.cy.ts diff --git a/cypress/e2e/english/post/post.cy.js b/cypress/e2e/english/post/post.cy.ts similarity index 97% rename from cypress/e2e/english/post/post.cy.js rename to cypress/e2e/english/post/post.cy.ts index 0f98da40e..fb04e3e1b 100644 --- a/cypress/e2e/english/post/post.cy.js +++ b/cypress/e2e/english/post/post.cy.ts @@ -114,7 +114,7 @@ describe('Post', () => { }); it('posts with no feature image should fall back to the default fCC indigo image', () => { - cy.get(selectors.featureImage) + cy.get(selectors.featureImage) .should('exist') .then($el => expect($el[0].src).to.equal( @@ -226,14 +226,14 @@ describe('Post', () => { }); it("should show a default image from Hashnode's CDN in the bylines at the top and bottom of the article", () => { - cy.get(selectors.authorProfileImage).then($el => { + cy.get(selectors.authorProfileImage).then($el => { expect($el[0].src).to.include('cdn.hashnode.com'); expect($el[0].tagName.toLowerCase()).to.equal('img'); }); }); it("the default image in the bylines at the top and bottom of the article should contain an `alt` attribute with the author's name", () => { - cy.get(selectors.authorProfileImage).then($el => + cy.get(selectors.authorProfileImage).then($el => expect($el[0].alt).to.equal('Dionysia Lemonaki') ); }); @@ -245,7 +245,7 @@ describe('Post', () => { }); it('posts with no feature image should fall back to the default fCC indigo image', () => { - cy.get(selectors.featureImage) + cy.get(selectors.featureImage) .should('exist') .then($el => expect($el[0].src).to.equal( diff --git a/cypress/e2e/english/post/structured-data.cy.js b/cypress/e2e/english/post/structured-data.cy.ts similarity index 100% rename from cypress/e2e/english/post/structured-data.cy.js rename to cypress/e2e/english/post/structured-data.cy.ts diff --git a/cypress/e2e/english/search-results/meta.cy.js b/cypress/e2e/english/search-results/meta.cy.ts similarity index 100% rename from cypress/e2e/english/search-results/meta.cy.js rename to cypress/e2e/english/search-results/meta.cy.ts diff --git a/cypress/e2e/english/search-results/search-results.cy.js b/cypress/e2e/english/search-results/search-results.cy.ts similarity index 97% rename from cypress/e2e/english/search-results/search-results.cy.js rename to cypress/e2e/english/search-results/search-results.cy.ts index ba7d4ecdf..e4accd1e5 100644 --- a/cypress/e2e/english/search-results/search-results.cy.js +++ b/cypress/e2e/english/search-results/search-results.cy.ts @@ -37,7 +37,7 @@ describe('Search results', () => { 'freeCodeCamp Just Got a Million Dollar Donation from an Alum to Build a Carbon-Neutral Web3 Curriculum' ) .parentsUntil('article') - .find(selectors.authorProfileImage) + .find(selectors.authorProfileImage) .then($el => expect($el[0].alt).to.equal('Quincy Larson')); }); diff --git a/cypress/e2e/english/tag/i18n.cy.js b/cypress/e2e/english/tag/i18n.cy.ts similarity index 100% rename from cypress/e2e/english/tag/i18n.cy.js rename to cypress/e2e/english/tag/i18n.cy.ts diff --git a/cypress/e2e/english/tag/meta.cy.js b/cypress/e2e/english/tag/meta.cy.ts similarity index 100% rename from cypress/e2e/english/tag/meta.cy.js rename to cypress/e2e/english/tag/meta.cy.ts diff --git a/cypress/e2e/english/tag/rss.cy.js b/cypress/e2e/english/tag/rss.cy.ts similarity index 100% rename from cypress/e2e/english/tag/rss.cy.js rename to cypress/e2e/english/tag/rss.cy.ts diff --git a/cypress/e2e/english/tag/structured-data.cy.js b/cypress/e2e/english/tag/structured-data.cy.ts similarity index 100% rename from cypress/e2e/english/tag/structured-data.cy.js rename to cypress/e2e/english/tag/structured-data.cy.ts diff --git a/cypress/e2e/english/tag/tag.cy.js b/cypress/e2e/english/tag/tag.cy.ts similarity index 100% rename from cypress/e2e/english/tag/tag.cy.js rename to cypress/e2e/english/tag/tag.cy.ts diff --git a/cypress/e2e/espanol/landing/landing.cy.js b/cypress/e2e/espanol/landing/landing.cy.ts similarity index 100% rename from cypress/e2e/espanol/landing/landing.cy.js rename to cypress/e2e/espanol/landing/landing.cy.ts diff --git a/cypress/e2e/espanol/landing/original-author-translator.cy.js b/cypress/e2e/espanol/landing/original-author-translator.cy.ts similarity index 100% rename from cypress/e2e/espanol/landing/original-author-translator.cy.js rename to cypress/e2e/espanol/landing/original-author-translator.cy.ts diff --git a/cypress/support/commands.js b/cypress/support/commands.ts similarity index 100% rename from cypress/support/commands.js rename to cypress/support/commands.ts diff --git a/cypress/support/e2e.js b/cypress/support/e2e.ts similarity index 100% rename from cypress/support/e2e.js rename to cypress/support/e2e.ts diff --git a/cypress/support/utils/post-cards.js b/cypress/support/utils/post-cards.ts similarity index 100% rename from cypress/support/utils/post-cards.js rename to cypress/support/utils/post-cards.ts diff --git a/cypress/support/utils/rss.js b/cypress/support/utils/rss.ts similarity index 100% rename from cypress/support/utils/rss.js rename to cypress/support/utils/rss.ts diff --git a/package-lock.json b/package-lock.json index c2992e40f..126b649db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@11ty/eleventy-plugin-rss": "1.2.0", "@tryghost/content-api": "1.11.21", "@tryghost/helpers": "1.1.90", + "@types/jest": "^29.5.12", "algoliasearch": "4.24.0", "clean-css": "5.3.3", "cross-env": "7.0.3", @@ -48,7 +49,8 @@ "prettier": "3.3.3", "probe-image-size": "7.2.3", "shx": "0.3.4", - "terser": "5.31.6" + "terser": "5.31.6", + "typescript": "^5.5.4" }, "engines": { "node": ">=18", @@ -1184,6 +1186,7 @@ "version": "6.6.0", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.6.0.tgz", "integrity": "sha512-xyX0X9mc0kyz9plIyryrRbl7ngsA9jz77mCZJsUkLl+ZKs0KWObgaEBoSgQiYWAsSmjz/yjl0F++Got0Mdp4Rw==", + "license": "MIT", "engines": { "node": ">=6" } @@ -1192,6 +1195,7 @@ "version": "6.6.0", "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.6.0.tgz", "integrity": "sha512-IYv/2skhEDFc2WGUcqvFJkeK39Q+HyPf5GHUrT/l2pKbtgEIv1al1TKd6qStR5OIwQdN1GZP54ci3y4mroJWjA==", + "license": "(CC-BY-4.0 AND MIT)", "dependencies": { "@fortawesome/fontawesome-common-types": "6.6.0" }, @@ -2016,6 +2020,17 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, "node_modules/@types/json-schema": { "version": "7.0.14", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", @@ -11883,17 +11898,17 @@ } }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, - "peer": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uc.micro": { @@ -14019,6 +14034,16 @@ "@types/istanbul-lib-report": "*" } }, + "@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "requires": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, "@types/json-schema": { "version": "7.0.14", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", @@ -21182,11 +21207,10 @@ } }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", - "dev": true, - "peer": true + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true }, "uc.micro": { "version": "1.0.6", diff --git a/package.json b/package.json index 339ef1f04..d2e7996b1 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "@11ty/eleventy-plugin-rss": "1.2.0", "@tryghost/content-api": "1.11.21", "@tryghost/helpers": "1.1.90", + "@types/jest": "^29.5.12", "algoliasearch": "4.24.0", "clean-css": "5.3.3", "cross-env": "7.0.3", @@ -101,7 +102,8 @@ "prettier": "3.3.3", "probe-image-size": "7.2.3", "shx": "0.3.4", - "terser": "5.31.6" + "terser": "5.31.6", + "typescript": "^5.5.4" }, "lint-staged": { "**/*": "prettier --write --ignore-unknown" diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..ea3aadd67 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es6", "dom"], + "allowJs": true, + "types": ["cypress", "node"], + "moduleDetection": "force", + "module": "commonjs", + "moduleResolution": "node", + "preserveValueImports": false + }, + "include": ["**/*.ts"] +} From 82bd5b4a5114a5de8a00744476704d78344a96b3 Mon Sep 17 00:00:00 2001 From: A Cottrill Date: Wed, 7 Aug 2024 16:27:28 -0400 Subject: [PATCH 03/14] cleanup --- cypress/e2e/english/landing/landing.cy.ts | 28 +++++++++++ src/_includes/assets/css/global.css | 59 ++++++++--------------- src/_includes/assets/css/screen.css | 3 +- src/_includes/partials/site-nav.njk | 1 + 4 files changed, 51 insertions(+), 40 deletions(-) diff --git a/cypress/e2e/english/landing/landing.cy.ts b/cypress/e2e/english/landing/landing.cy.ts index e6194dbde..4e73a73fa 100644 --- a/cypress/e2e/english/landing/landing.cy.ts +++ b/cypress/e2e/english/landing/landing.cy.ts @@ -7,11 +7,16 @@ const selectors = { authorList: "[data-test-label='author-list']", authorListItem: "[data-test-label='author-list-item']", authorProfileImage: "[data-test-label='profile-image']", + darkModeButton: "[data-test-label='dark-mode-button']", avatar: "[data-test-label='avatar']", siteNavLogo: "[data-test-label='site-nav-logo']", + menuButton: "[data-test-label='header-menu-button']", + menu: "[data-test-label='header-menu']", postPublishedTime: "[data-test-label='post-published-time']" }; +// header-menu-button + describe('Landing', () => { beforeEach(() => { cy.visit('/'); @@ -32,6 +37,29 @@ describe('Landing', () => { ); }); + it('Clicking the menu button should open the menu', function () { + const menuButton = cy.get(selectors.menuButton); + const menu = cy.get(selectors.menu); + expect(menuButton).to.be.visible(); + menuButton.click(); + expect(menu).to.be.visible(); + }); + + it('The menu should be able to change the theme', function () { + const menuButton = cy.get(selectors.menuButton); + const menu = cy.get(selectors.menu); + menuButton.click(); + expect(menuButton).to.be.visible(); + const themeButton = cy.get(selectors.darkModeButton); + themeButton.click(); + cy.get('body').should('have.class', 'dark-mode'); + expect(menu).to.be.hidden(); + menuButton.click(); + expect(menu).to.be.visible(); + themeButton.click(); + cy.get('body').should('not.have.class', 'dark-mode'); + }); + it("should show the author's profile image", () => { cy.get(selectors.postCard) .contains( diff --git a/src/_includes/assets/css/global.css b/src/_includes/assets/css/global.css index 4c7616919..312ba15d4 100644 --- a/src/_includes/assets/css/global.css +++ b/src/_includes/assets/css/global.css @@ -16,28 +16,6 @@ --header-height: 38px; } -body { - --primary-color: var(--gray90); - --secondary-color: var(--gray85); - --tertiary-color: var(--gray80); - --quaternary-color: var(--gray75); - --quaternary-background: var(--gray15); - --tertiary-background: var(--gray10); - --secondary-background: var(--gray05); - --primary-background: var(--gray00); -} - -body.dark-mode { - --primary-color: var(--gray00); - --secondary-color: var(--gray05); - --tertiary-color: var(--gray10); - --quaternary-color: var(--gray15); - --quaternary-background: var(--gray75); - --tertiary-background: var(--gray80); - --secondary-background: var(--gray85); - --primary-background: var(--gray90); -} - /* Fonts /*------------------------------------------------------------*/ /*@import url("https://fonts.googleapis.com/css?family=Lato:400,400i,700|Roboto+Mono:400,700");*/ @@ -305,7 +283,17 @@ html { -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } + body { + --primary-color: var(--gray90); + --secondary-color: var(--gray85); + --tertiary-color: var(--gray80); + --quaternary-color: var(--gray75); + --quaternary-background: var(--gray15); + --tertiary-background: var(--gray10); + --secondary-background: var(--gray05); + --primary-background: var(--gray00); + overflow-x: hidden; color: var(--gray90); font-family: 'Lato', sans-serif; @@ -323,6 +311,17 @@ body { font-feature-settings: 'liga1' on; } +body.dark-mode { + --primary-color: var(--gray00); + --secondary-color: var(--gray05); + --tertiary-color: var(--gray10); + --quaternary-color: var(--gray15); + --quaternary-background: var(--gray75); + --tertiary-background: var(--gray80); + --secondary-background: var(--gray85); + --primary-background: var(--gray90); +} + ::selection { text-shadow: none; background: var(--dark-blue); @@ -558,22 +557,6 @@ h6 { } } -/** - * Site header language list - */ -.lang-button-nav[aria-expanded='true'] + .nav-list { - -ms-overflow-style: none; - display: block; - max-height: calc(100vh - var(--header-height)); - overflow-y: auto; - scrollbar-width: none; - top: calc(var(--header-height)); -} - -.lang-button-nav[aria-expanded='true'] + .nav-list::-webkit-scrollbar { - display: none; -} - /* WCAG fix */ .sr-only { color: white; diff --git a/src/_includes/assets/css/screen.css b/src/_includes/assets/css/screen.css index a3f035af6..5a9da438a 100644 --- a/src/_includes/assets/css/screen.css +++ b/src/_includes/assets/css/screen.css @@ -171,7 +171,7 @@ body { /* ---------------------------------------------------------- */ .site-nav { - z-index: 300; + z-index: 1000; display: flex; justify-content: space-between; align-items: flex-start; @@ -182,7 +182,6 @@ body { height: var(--header-height); background: var(--gray90); position: fixed; - z-index: 1000; color: #fff; width: 100%; } diff --git a/src/_includes/partials/site-nav.njk b/src/_includes/partials/site-nav.njk index 9f6c358a5..8e10a2cce 100644 --- a/src/_includes/partials/site-nav.njk +++ b/src/_includes/partials/site-nav.njk @@ -46,6 +46,7 @@ class='nav-link nav-link-flex' target="_blank" href="{% t 'links:nav:forum' %}" + data-test-label="forum-button" > {% t 'buttons.forum' %} {% t 'aria.opens-new-window' %} From dc008d881ad1941bacbe4aac7866df079f682f50 Mon Sep 17 00:00:00 2001 From: A Cottrill Date: Thu, 8 Aug 2024 19:15:50 -0400 Subject: [PATCH 04/14] use Cypress test tools properly --- cypress/e2e/english/landing/landing.cy.ts | 48 +++++++++++++++-------- src/_includes/assets/js/dark-mode.js | 7 ++++ src/_includes/assets/js/dropdown.js | 7 ---- src/_includes/partials/site-nav.njk | 4 +- 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/cypress/e2e/english/landing/landing.cy.ts b/cypress/e2e/english/landing/landing.cy.ts index 4e73a73fa..541de9ee5 100644 --- a/cypress/e2e/english/landing/landing.cy.ts +++ b/cypress/e2e/english/landing/landing.cy.ts @@ -38,26 +38,40 @@ describe('Landing', () => { }); it('Clicking the menu button should open the menu', function () { - const menuButton = cy.get(selectors.menuButton); - const menu = cy.get(selectors.menu); - expect(menuButton).to.be.visible(); - menuButton.click(); - expect(menu).to.be.visible(); + cy.get(selectors.menuButton) + .should('be.visible') + .click() + .then(() => { + cy.get(selectors.menu).should('be.visible'); + }); }); it('The menu should be able to change the theme', function () { - const menuButton = cy.get(selectors.menuButton); - const menu = cy.get(selectors.menu); - menuButton.click(); - expect(menuButton).to.be.visible(); - const themeButton = cy.get(selectors.darkModeButton); - themeButton.click(); - cy.get('body').should('have.class', 'dark-mode'); - expect(menu).to.be.hidden(); - menuButton.click(); - expect(menu).to.be.visible(); - themeButton.click(); - cy.get('body').should('not.have.class', 'dark-mode'); + cy.get(selectors.menuButton) + .click() + .then(() => { + cy.get(selectors.menu).should('be.visible'); + cy.get(selectors.darkModeButton) + .click() + .then(() => { + cy.get('body').should('have.class', 'dark-mode'); + cy.get(selectors.siteNavLogo) + .click() + .then(() => { + cy.get(selectors.menu).should('not.be.visible'); + cy.get(selectors.menuButton) + .click() + .then(() => { + cy.get(selectors.menu).should('be.visible'); + cy.get(selectors.darkModeButton) + .click() + .then(() => { + cy.get('body').should('not.have.class', 'dark-mode'); + }); + }); + }); + }); + }); }); it("should show the author's profile image", () => { diff --git a/src/_includes/assets/js/dark-mode.js b/src/_includes/assets/js/dark-mode.js index 43d45dd64..154466462 100644 --- a/src/_includes/assets/js/dark-mode.js +++ b/src/_includes/assets/js/dark-mode.js @@ -29,4 +29,11 @@ document.addEventListener('DOMContentLoaded', () => { localStorage.setItem('fcc-dark-mode', 'disabled'); } }); + + document + .getElementById('toggle-dark-mode') + .addEventListener('blur', function () { + document.getElementById('nav-list')?.classList.remove('display-menu'); + document.getElementById('nav-list').ariaExpanded = 'false'; + }); }); diff --git a/src/_includes/assets/js/dropdown.js b/src/_includes/assets/js/dropdown.js index c5de13edd..1d0543b31 100644 --- a/src/_includes/assets/js/dropdown.js +++ b/src/_includes/assets/js/dropdown.js @@ -7,11 +7,4 @@ document.addEventListener('DOMContentLoaded', () => { document.getElementById('nav-list').classList.toggle('display-menu'); document.getElementById('nav-list').ariaExpanded = String(displayMenu); }); - - /* - document.getElementById('toggle-button-nav').addEventListener('blur', function () { - document.getElementById('nav-list')?.classList.remove("display-menu"); - document.getElementById('nav-list').ariaExpanded = "false"; - }); - */ }); diff --git a/src/_includes/partials/site-nav.njk b/src/_includes/partials/site-nav.njk index 8e10a2cce..ab3b500df 100644 --- a/src/_includes/partials/site-nav.njk +++ b/src/_includes/partials/site-nav.njk @@ -10,7 +10,7 @@ - - From f9c01e96078cf5a1506a096fea99c841848d6ad7 Mon Sep 17 00:00:00 2001 From: A Cottrill Date: Wed, 4 Sep 2024 09:38:19 -0400 Subject: [PATCH 12/14] use a local storage key --- src/_includes/assets/js/dark-mode.js | 8 +++++++- src/_includes/partials/site-nav.njk | 13 ++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/_includes/assets/js/dark-mode.js b/src/_includes/assets/js/dark-mode.js index 3d11bc1f7..e18fe16f9 100644 --- a/src/_includes/assets/js/dark-mode.js +++ b/src/_includes/assets/js/dark-mode.js @@ -1,5 +1,9 @@ function loadDarkModePreference() { - if (window.matchMedia('(prefers-color-scheme: dark)')?.matches) { + const theme = localStorage.getItem('theme'); + if ( + window.matchMedia('(prefers-color-scheme: dark)')?.matches || + theme == 'dark' + ) { document.body.classList.add('dark-mode'); document .getElementById('dark-mode-enabled') @@ -17,10 +21,12 @@ document.addEventListener('DOMContentLoaded', () => { document .getElementById('dark-mode-enabled') .classList.replace('fa-square', 'fa-square-check'); + localStorage.setItem('theme', 'dark'); } else { document .getElementById('dark-mode-enabled') .classList.replace('fa-square-check', 'fa-square'); + localStorage.setItem('theme', 'light'); } }); diff --git a/src/_includes/partials/site-nav.njk b/src/_includes/partials/site-nav.njk index ee9fcfc61..9a21807ee 100644 --- a/src/_includes/partials/site-nav.njk +++ b/src/_includes/partials/site-nav.njk @@ -40,7 +40,18 @@ - +