diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-05-17 18:31:21 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-05-17 18:31:21 +0200 |
| commit | 9a186b357b32325cf77fdce39a6c6c9aff76d8a5 (patch) | |
| tree | bfeb790f3cc82f753ac74c9b0130f43189502803 /src/components | |
| parent | c77c58e18143233be042c4980a6ed08ae9beac52 (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.scss | 4 | ||||
| -rw-r--r-- | src/components/organisms/layout/footer.stories.tsx | 21 | ||||
| -rw-r--r-- | src/components/organisms/layout/footer.tsx | 21 | ||||
| -rw-r--r-- | src/components/templates/layout/layout.module.scss | 14 | ||||
| -rw-r--r-- | src/components/templates/layout/layout.tsx | 19 |
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> |
