summaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-05-17 18:31:21 +0200
committerArmand Philippot <git@armandphilippot.com>2022-05-17 18:31:21 +0200
commit9a186b357b32325cf77fdce39a6c6c9aff76d8a5 (patch)
treebfeb790f3cc82f753ac74c9b0130f43189502803 /src/components
parentc77c58e18143233be042c4980a6ed08ae9beac52 (diff)
chore: listen scroll to hide/show back to top button
Diffstat (limited to 'src/components')
-rw-r--r--src/components/molecules/buttons/back-to-top.module.scss4
-rw-r--r--src/components/organisms/layout/footer.stories.tsx21
-rw-r--r--src/components/organisms/layout/footer.tsx21
-rw-r--r--src/components/templates/layout/layout.module.scss14
-rw-r--r--src/components/templates/layout/layout.tsx19
5 files changed, 64 insertions, 15 deletions
diff --git a/src/components/molecules/buttons/back-to-top.module.scss b/src/components/molecules/buttons/back-to-top.module.scss
index 9721bff..77ee97b 100644
--- a/src/components/molecules/buttons/back-to-top.module.scss
+++ b/src/components/molecules/buttons/back-to-top.module.scss
@@ -2,8 +2,8 @@
.wrapper {
.link {
- width: clamp(#{fun.convert-px(44)}, 6vw, #{fun.convert-px(55)});
- height: clamp(#{fun.convert-px(44)}, 6vw, #{fun.convert-px(55)});
+ width: clamp(#{fun.convert-px(48)}, 8vw, #{fun.convert-px(55)});
+ height: clamp(#{fun.convert-px(48)}, 8vw, #{fun.convert-px(55)});
svg {
width: 100%;
diff --git a/src/components/organisms/layout/footer.stories.tsx b/src/components/organisms/layout/footer.stories.tsx
index 06819da..bd5a744 100644
--- a/src/components/organisms/layout/footer.stories.tsx
+++ b/src/components/organisms/layout/footer.stories.tsx
@@ -1,5 +1,4 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';
-import { IntlProvider } from 'react-intl';
import FooterComponent from './footer';
/**
@@ -9,6 +8,19 @@ export default {
title: 'Organisms/Layout',
component: FooterComponent,
argTypes: {
+ backToTopClassName: {
+ control: {
+ type: 'text',
+ },
+ description: 'Set additional classnames to the back to top button.',
+ table: {
+ category: 'Styles',
+ },
+ type: {
+ name: 'string',
+ required: false,
+ },
+ },
className: {
control: {
type: 'text',
@@ -53,13 +65,6 @@ export default {
},
},
},
- decorators: [
- (Story) => (
- <IntlProvider locale="en">
- <Story />
- </IntlProvider>
- ),
- ],
} as ComponentMeta<typeof FooterComponent>;
const Template: ComponentStory<typeof FooterComponent> = (args) => (
diff --git a/src/components/organisms/layout/footer.tsx b/src/components/organisms/layout/footer.tsx
index 1426e96..c60afec 100644
--- a/src/components/organisms/layout/footer.tsx
+++ b/src/components/organisms/layout/footer.tsx
@@ -1,7 +1,9 @@
import Copyright, {
type CopyrightProps,
} from '@components/atoms/layout/copyright';
-import BackToTop from '@components/molecules/buttons/back-to-top';
+import BackToTop, {
+ type BackToTopProps,
+} from '@components/molecules/buttons/back-to-top';
import Nav, { type NavItem } from '@components/molecules/nav/nav';
import { FC } from 'react';
import { useIntl } from 'react-intl';
@@ -9,6 +11,10 @@ import styles from './footer.module.scss';
export type FooterProps = {
/**
+ * Set additional classnames to the back to top button.
+ */
+ backToTopClassName?: BackToTopProps['className'];
+ /**
* Set additional classnames to the footer element.
*/
className?: string;
@@ -31,7 +37,13 @@ export type FooterProps = {
*
* Renders a footer with copyright and nav;
*/
-const Footer: FC<FooterProps> = ({ className, copyright, navItems, topId }) => {
+const Footer: FC<FooterProps> = ({
+ backToTopClassName,
+ className = '',
+ copyright,
+ navItems,
+ topId,
+}) => {
const intl = useIntl();
const ariaLabel = intl.formatMessage({
defaultMessage: 'Footer',
@@ -54,7 +66,10 @@ const Footer: FC<FooterProps> = ({ className, copyright, navItems, topId }) => {
className={styles.nav}
/>
)}
- <BackToTop target={topId} className={styles['back-to-top']} />
+ <BackToTop
+ target={topId}
+ className={`${styles['back-to-top']} ${backToTopClassName}`}
+ />
</footer>
);
};
diff --git a/src/components/templates/layout/layout.module.scss b/src/components/templates/layout/layout.module.scss
index 806d2d7..09904dc 100644
--- a/src/components/templates/layout/layout.module.scss
+++ b/src/components/templates/layout/layout.module.scss
@@ -13,6 +13,20 @@
border-top: fun.convert-px(3) solid var(--color-border-light);
}
+.back-to-top {
+ &--hidden {
+ opacity: 0;
+ transform: translateY(calc(var(--button-size) + var(--spacing-md)));
+ visibility: hidden;
+ }
+
+ &--visible {
+ opacity: 1;
+ transform: translateY(0);
+ visibility: visible;
+ }
+}
+
.noscript-spacing {
width: 100%;
height: fun.convert-px(75);
diff --git a/src/components/templates/layout/layout.tsx b/src/components/templates/layout/layout.tsx
index 9e9282b..3eb02ee 100644
--- a/src/components/templates/layout/layout.tsx
+++ b/src/components/templates/layout/layout.tsx
@@ -7,11 +7,12 @@ import Home from '@components/atoms/icons/home';
import PostsStack from '@components/atoms/icons/posts-stack';
import Main from '@components/atoms/layout/main';
import NoScript from '@components/atoms/layout/no-script';
-import Footer, { FooterProps } from '@components/organisms/layout/footer';
+import Footer, { type FooterProps } from '@components/organisms/layout/footer';
import Header, { type HeaderProps } from '@components/organisms/layout/header';
+import useScrollPosition from '@utils/hooks/use-scroll-position';
import useSettings from '@utils/hooks/use-settings';
import Script from 'next/script';
-import { FC, ReactNode } from 'react';
+import { FC, ReactNode, useState } from 'react';
import { useIntl } from 'react-intl';
import {
BreadcrumbList,
@@ -162,6 +163,19 @@ const Layout: FC<LayoutProps> = ({
subjectOf: { '@id': `${url}` },
};
+ const [backToTopClassName, setBackToTopClassName] = useState<string>(
+ styles['back-to-top--hidden']
+ );
+ const updateBackToTopClassName = () => {
+ setBackToTopClassName(
+ window.scrollY > 300
+ ? styles['back-to-top--visible']
+ : styles['back-to-top--hidden']
+ );
+ };
+
+ useScrollPosition(updateBackToTopClassName);
+
return (
<>
<Script
@@ -203,6 +217,7 @@ const Layout: FC<LayoutProps> = ({
copyright={copyrightData}
navItems={footerNav}
topId="top"
+ backToTopClassName={backToTopClassName}
className={styles.footer}
/>
<noscript>