aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/templates/layout
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-10-25 18:33:22 +0200
committerArmand Philippot <git@armandphilippot.com>2023-11-11 18:15:27 +0100
commit9aeb82269d7c74c4566b7ca254782a4dfbd69a6e (patch)
treee2ab930204cbcf20cebaa6125ea022f050d973af /src/components/templates/layout
parentc21a137e1991af1331fe5768fc6bac15ea9230b1 (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.scss65
-rw-r--r--src/components/templates/layout/layout.tsx151
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>