diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-10-25 18:33:22 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-11 18:15:27 +0100 |
| commit | 9aeb82269d7c74c4566b7ca254782a4dfbd69a6e (patch) | |
| tree | e2ab930204cbcf20cebaa6125ea022f050d973af /src/components/templates/layout | |
| parent | c21a137e1991af1331fe5768fc6bac15ea9230b1 (diff) | |
refactor(components): remove SiteHeader and SiteFooter components
They do not help to make the layout more readable (on the contrary I
think...) so the props drilling is useless.
Diffstat (limited to 'src/components/templates/layout')
| -rw-r--r-- | src/components/templates/layout/layout.module.scss | 65 | ||||
| -rw-r--r-- | src/components/templates/layout/layout.tsx | 151 |
2 files changed, 151 insertions, 65 deletions
diff --git a/src/components/templates/layout/layout.module.scss b/src/components/templates/layout/layout.module.scss index 4f00742..4695948 100644 --- a/src/components/templates/layout/layout.module.scss +++ b/src/components/templates/layout/layout.module.scss @@ -33,7 +33,22 @@ } .header { + display: grid; + grid-template-columns: + minmax(0, 1fr) min(calc(100vw - calc(var(--spacing-md) * 2)), 100ch) + minmax(0, 1fr); + align-items: center; + padding: var(--spacing-md) 0 var(--spacing-lg); border-bottom: fun.convert-px(3) solid var(--color-border-light); + + &__body { + grid-column: 2; + display: flex; + flex-flow: row wrap; + align-items: center; + justify-content: space-between; + gap: var(--spacing-md); + } } .brand { @@ -62,6 +77,36 @@ } } +.toolbar { + justify-content: space-around; + position: fixed; + bottom: 0; + left: 0; + z-index: 5; + background: var(--color-bg); + border-top: fun.convert-px(4) solid; + border-image: radial-gradient( + ellipse at top, + var(--color-primary-lighter) 20%, + var(--color-primary) 100% + ) + 1; + box-shadow: 0 fun.convert-px(-2) fun.convert-px(3) fun.convert-px(-1) + var(--color-shadow-dark); + + @include mix.media("screen") { + @include mix.dimensions("sm") { + justify-content: flex-end; + width: auto; + position: relative; + left: unset; + background: inherit; + border: none; + box-shadow: none; + } + } +} + .main { flex: 1; } @@ -80,10 +125,30 @@ } .footer { + display: flex; + flex-flow: column wrap; + gap: var(--spacing-xs); + place-items: center; + place-content: center; + padding: var(--spacing-md) 0 calc(var(--toolbar-size) + var(--spacing-md)); border-top: fun.convert-px(3) solid var(--color-border-light); + + @include mix.media("screen") { + @include mix.dimensions("sm") { + --toolbar-size: 0px; + + flex-flow: row wrap; + font-size: var(--font-size-sm); + } + } } .back-to-top { + position: fixed; + bottom: calc(var(--toolbar-size, 0px) + var(--spacing-md)); + right: var(--spacing-md); + transition: all 0.4s ease-in 0s; + &--hidden { opacity: 0; transform: translateY(calc(var(--button-height) + var(--spacing-md))); diff --git a/src/components/templates/layout/layout.tsx b/src/components/templates/layout/layout.tsx index 2369669..bf9629c 100644 --- a/src/components/templates/layout/layout.tsx +++ b/src/components/templates/layout/layout.tsx @@ -18,15 +18,25 @@ import { useScrollPosition, useSettings, } from '../../../utils/hooks'; -import { ButtonLink, Heading, Icon, Logo, Main } from '../../atoms'; import { - SiteFooter, - type SiteFooterProps, - SiteHeader, - type SiteHeaderProps, -} from '../../organisms'; + ButtonLink, + Footer, + Header, + Heading, + Icon, + Logo, + Main, +} from '../../atoms'; +import { + BackToTop, + Branding, + Colophon, + type ColophonLink, + Copyright, + FlippingLogo, +} from '../../molecules'; +import { type MainNavItem, Toolbar } from '../../organisms'; import styles from './layout.module.scss'; -import { FlippingLogo } from 'src/components/molecules'; export type QueryAction = SearchAction & { 'query-input': string; @@ -87,12 +97,6 @@ export const Layout: FC<LayoutProps> = ({ id: 'yB1SPF', }); - const copyrightData = { - from: copyright.start, - owner: name, - to: copyright.end, - }; - const homeLabel = intl.formatMessage({ defaultMessage: 'Home', description: 'Layout: main nav - home link', @@ -134,8 +138,13 @@ export const Layout: FC<LayoutProps> = ({ }, { website: name } ); + const backToTop = intl.formatMessage({ + defaultMessage: 'Back to top', + description: 'Layout: an accessible name for the back to top button', + id: 'Kjj1Zk', + }); - const mainNav: SiteHeaderProps['nav'] = [ + const mainNav: MainNavItem[] = [ { id: 'home', label: homeLabel, @@ -174,7 +183,7 @@ export const Layout: FC<LayoutProps> = ({ id: 'nwbzKm', }); - const footerNav: SiteFooterProps['navItems'] = [ + const footerNav: ColophonLink[] = [ { id: 'legal-notice', label: legalNoticeLabel, href: ROUTES.LEGAL_NOTICE }, ]; @@ -215,14 +224,14 @@ export const Layout: FC<LayoutProps> = ({ }; const [backToTopClassName, setBackToTopClassName] = useState<string>( - styles['back-to-top--hidden'] + `${styles['back-to-top']} ${styles['back-to-top--hidden']}` ); const updateBackToTopClassName = () => { const visibleBreakpoint = 300; setBackToTopClassName( window.scrollY > visibleBreakpoint - ? styles['back-to-top--visible'] - : styles['back-to-top--hidden'] + ? `${styles['back-to-top']} ${styles['back-to-top--visible']}` + : `${styles['back-to-top']} ${styles['back-to-top--hidden']}` ); }; @@ -265,48 +274,54 @@ export const Layout: FC<LayoutProps> = ({ <ButtonLink className="screen-reader-text" to="#main"> {skipToContent} </ButtonLink> - <SiteHeader - // eslint-disable-next-line react/jsx-no-literals -- Storage key allowed - ackeeStorageKey="ackee-tracking" - baseline={ - <div - className={styles.brand__baseline} - style={brandingBaselineStyles} - > - {baseline} - </div> - } - className={styles.header} - logo={ - <FlippingLogo - back={<Logo heading={logoTitle} />} - className={styles.brand__logo} - front={ - <NextImage - alt={photoAltText} - height={120} - src="/armand-philippot.jpg" - width={120} + <Header className={styles.header}> + <div className={styles.header__body}> + <Branding + baseline={ + <div + className={styles.brand__baseline} + style={brandingBaselineStyles} + > + {baseline} + </div> + } + logo={ + <FlippingLogo + back={<Logo heading={logoTitle} />} + className={styles.brand__logo} + front={ + <NextImage + alt={photoAltText} + height={120} + src="/armand-philippot.jpg" + width={120} + /> + } /> } + name={ + <Heading + className={styles.brand__title} + isFake={!isHome} + level={1} + style={brandingTitleStyles} + > + {name} + </Heading> + } + url="/" /> - } - // eslint-disable-next-line react/jsx-no-literals -- Storage key allowed - motionStorageKey="reduced-motion" - name={ - <Heading - className={styles.brand__title} - isFake={!isHome} - level={1} - style={brandingTitleStyles} - > - {name} - </Heading> - } - nav={mainNav} - searchPage={ROUTES.SEARCH} - url="/" - /> + <Toolbar + // eslint-disable-next-line react/jsx-no-literals -- Storage key allowed + ackeeStorageKey="ackee-tracking" + className={styles.toolbar} + // eslint-disable-next-line react/jsx-no-literals -- Storage key allowed + motionStorageKey="reduced-motion" + nav={mainNav} + searchPage={ROUTES.SEARCH} + /> + </div> + </Header> <Main id="main" className={styles.main}> <article className={`${styles[articleGridClass]} ${styles[articleCommentsClass]}`} @@ -314,14 +329,20 @@ export const Layout: FC<LayoutProps> = ({ {children} </article> </Main> - <SiteFooter - backToTopClassName={backToTopClassName} - className={styles.footer} - copyright={copyrightData} - license={<Icon heading={copyrightTitle} shape="cc-by-sa" size="lg" />} - navItems={footerNav} - topId="top" - /> + <Footer className={styles.footer}> + <Colophon + copyright={ + <Copyright from={copyright.start} owner={name} to={copyright.end} /> + } + license={<Icon heading={copyrightTitle} shape="cc-by-sa" size="lg" />} + links={footerNav} + /> + <BackToTop + anchor="#top" + className={backToTopClassName} + label={backToTop} + /> + </Footer> <noscript> <div className={styles.noscript}>{noScript}</div> </noscript> |
