diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-11-21 19:01:18 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-22 12:52:35 +0100 |
| commit | d4045fbcbfa8208ec31539744417f315f1f6fad8 (patch) | |
| tree | 54746d3e28cc6e4a2d7d1e54a4b2e3e1e74a6896 /src/components/templates/layout/site-footer/site-footer.tsx | |
| parent | c6212f927daf3c928f479afa052e4772216a2d8a (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.tsx | 93 |
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); |
