aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/templates/layout/site-footer/site-footer.tsx
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-11-21 19:01:18 +0100
committerArmand Philippot <git@armandphilippot.com>2023-11-22 12:52:35 +0100
commitd4045fbcbfa8208ec31539744417f315f1f6fad8 (patch)
tree54746d3e28cc6e4a2d7d1e54a4b2e3e1e74a6896 /src/components/templates/layout/site-footer/site-footer.tsx
parentc6212f927daf3c928f479afa052e4772216a2d8a (diff)
refactor(components): split Layout component in smaller components
The previous component was too long and hardly readable. So I splitted it in different part and added tests.
Diffstat (limited to 'src/components/templates/layout/site-footer/site-footer.tsx')
-rw-r--r--src/components/templates/layout/site-footer/site-footer.tsx93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/components/templates/layout/site-footer/site-footer.tsx b/src/components/templates/layout/site-footer/site-footer.tsx
new file mode 100644
index 0000000..b852b32
--- /dev/null
+++ b/src/components/templates/layout/site-footer/site-footer.tsx
@@ -0,0 +1,93 @@
+import { type ForwardRefRenderFunction, forwardRef } from 'react';
+import { useIntl } from 'react-intl';
+import { CONFIG } from '../../../../utils/config';
+import { ROUTES } from '../../../../utils/constants';
+import { useScrollPosition } from '../../../../utils/hooks';
+import { Footer, type FooterProps, Icon } from '../../../atoms';
+import {
+ BackToTop,
+ Colophon,
+ type ColophonLink,
+ Copyright,
+} from '../../../molecules';
+import styles from './site-footer.module.scss';
+
+export type SiteFooterProps = Omit<FooterProps, 'children'> & {
+ /**
+ * An id that will be use as anchor for the back to top button.
+ */
+ topId?: string;
+};
+
+const SiteFooterWithRef: ForwardRefRenderFunction<
+ HTMLElement,
+ SiteFooterProps
+> = ({ className = '', topId, ...props }, ref) => {
+ const footerClass = `${styles.footer} ${className}`;
+ const intl = useIntl();
+ const licenseName = intl.formatMessage({
+ defaultMessage: 'CC BY SA',
+ description: 'SiteFooter: the license name',
+ id: 'iTLvLX',
+ });
+ const backToTop = intl.formatMessage({
+ defaultMessage: 'Back to top',
+ description: 'SiteFooter: an accessible name for the back to top button',
+ id: 'OHvb01',
+ });
+ const footerNav: ColophonLink[] = [
+ {
+ id: 'legal-notice',
+ label: intl.formatMessage({
+ defaultMessage: 'Legal notice',
+ description: 'SiteFooter: Legal notice link label',
+ id: 'lsmD4c',
+ }),
+ href: ROUTES.LEGAL_NOTICE,
+ },
+ ];
+ const scrollPos = useScrollPosition();
+ const backToTopVisibilityBreakpoint = 300;
+ const backToTopClassName = [
+ styles['back-to-top'],
+ styles[
+ scrollPos.y > backToTopVisibilityBreakpoint
+ ? 'back-to-top--visible'
+ : 'back-to-top--hidden'
+ ],
+ ].join(' ');
+ const backToTopAnchor = topId ? `#${topId}` : undefined;
+
+ return (
+ <Footer {...props} className={footerClass} ref={ref}>
+ <Colophon
+ copyright={
+ <Copyright
+ from={CONFIG.copyright.startYear}
+ owner={CONFIG.name}
+ to={CONFIG.copyright.endYear}
+ />
+ }
+ license={
+ <Icon
+ heading={licenseName}
+ // eslint-disable-next-line react/jsx-no-literals
+ shape="cc-by-sa"
+ // eslint-disable-next-line react/jsx-no-literals
+ size="lg"
+ />
+ }
+ links={footerNav}
+ />
+ {backToTopAnchor ? (
+ <BackToTop
+ anchor={backToTopAnchor}
+ className={backToTopClassName}
+ label={backToTop}
+ />
+ ) : null}
+ </Footer>
+ );
+};
+
+export const SiteFooter = forwardRef(SiteFooterWithRef);