diff --git a/config/i18n/locales/english/translations.json b/config/i18n/locales/english/translations.json index c8600d910..fbb569eaa 100644 --- a/config/i18n/locales/english/translations.json +++ b/config/i18n/locales/english/translations.json @@ -2,7 +2,8 @@ "buttons": { "forum": "Forum", "donate": "Donate", - "load-more-articles": "Load More Articles" + "load-more-articles": "Load More Articles", + "scroll-to-top": "Scroll to Top" }, "search": { "label": "Search", diff --git a/cypress/e2e/english/landing/landing.cy.ts b/cypress/e2e/english/landing/landing.cy.ts index 85ca52d76..976a45197 100644 --- a/cypress/e2e/english/landing/landing.cy.ts +++ b/cypress/e2e/english/landing/landing.cy.ts @@ -10,7 +10,8 @@ const selectors = { avatar: "[data-test-label='avatar']", siteNavLogo: "[data-test-label='site-nav-logo']", postPublishedTime: "[data-test-label='post-published-time']", - banner: "[data-test-label='banner']" + banner: "[data-test-label='banner']", + scrollButton: "[data-test-label='scroll-to-top']" }; describe('Landing (Hashnode sourced)', () => { @@ -55,6 +56,15 @@ describe('Landing (Hashnode sourced)', () => { .should('equal', 'https://www.freecodecamp.org/'); }); + it('the scroll button should be initially hidden', function () { + cy.get(selectors.scrollButton).should('be.hidden'); + }); + + it('the scroll button should scroll into view', function () { + cy.scrollTo('bottom'); + cy.get(selectors.scrollButton).should('be.visible'); + }); + it('the authenticated banner text should tell people to donate', function () { cy.setCookie('jwt_access_token', 'dadadsdadsadasd'); cy.visit('/'); diff --git a/src/_includes/assets/css/screen.css b/src/_includes/assets/css/screen.css index 9c1c14bcb..de788472a 100644 --- a/src/_includes/assets/css/screen.css +++ b/src/_includes/assets/css/screen.css @@ -422,6 +422,26 @@ a.nav-forum { } } +#scrollToTop { + display: none; + position: fixed; + bottom: 20px; + right: 30px; + z-index: 99; + border: none; + outline: none; + color: var(--gray00); + background-color: var(--dark-blue); + cursor: pointer; + padding: 15px; + border-radius: 10px; + font-size: 18px; +} + +#scrollToTop:hover { + background-color: var(--gray75); +} + /* 6. Post Feed /* ---------------------------------------------------------- */ diff --git a/src/_includes/assets/js/scroll-button.js b/src/_includes/assets/js/scroll-button.js new file mode 100644 index 000000000..31f5a60b3 --- /dev/null +++ b/src/_includes/assets/js/scroll-button.js @@ -0,0 +1,22 @@ +// Get the button: +let goTopButton = document.getElementById('scrollToTop'); + +window.onscroll = function () { + scrollFunction(); +}; + +function scrollFunction() { + if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) { + // @ts-ignore + goTopButton.style.display = 'block'; + } else { + // @ts-ignore + goTopButton.style.display = 'none'; + } +} + +// eslint-disable-next-line no-unused-vars +function goToTop() { + document.body.scrollTop = 0; + document.documentElement.scrollTop = 0; +} diff --git a/src/_includes/layouts/default.njk b/src/_includes/layouts/default.njk index b69c7306b..5b5af080f 100644 --- a/src/_includes/layouts/default.njk +++ b/src/_includes/layouts/default.njk @@ -62,7 +62,7 @@ {% if secrets.eleventyEnv === 'prod' %} {% include "partials/gtm-head.njk" %} {% endif %} - + {# Dynamically load MathJax script #} {% block mathjax %} {% endblock %} @@ -138,6 +138,8 @@
{% endif %} + {% include "partials/scroll-button.njk" %} + {% if secrets.eleventyEnv === 'prod' %} {% include "partials/gtm-body.njk" %} {% endif %} diff --git a/src/_includes/partials/scroll-button.njk b/src/_includes/partials/scroll-button.njk new file mode 100644 index 000000000..c18d2219c --- /dev/null +++ b/src/_includes/partials/scroll-button.njk @@ -0,0 +1,8 @@ + + +{% block scripts %} + {% set js %} + {% include "assets/js/scroll-button.js" %} + {% endset %} + +{% endblock %}