aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/components/organisms/layout/index.ts2
-rw-r--r--src/components/organisms/layout/site-footer.module.scss26
-rw-r--r--src/components/organisms/layout/site-footer.stories.tsx92
-rw-r--r--src/components/organisms/layout/site-footer.test.tsx38
-rw-r--r--src/components/organisms/layout/site-footer.tsx78
-rw-r--r--src/components/organisms/layout/site-header.module.scss50
-rw-r--r--src/components/organisms/layout/site-header.stories.tsx162
-rw-r--r--src/components/organisms/layout/site-header.test.tsx59
-rw-r--r--src/components/organisms/layout/site-header.tsx47
-rw-r--r--src/components/templates/layout/layout.module.scss65
-rw-r--r--src/components/templates/layout/layout.tsx151
-rw-r--r--src/i18n/en.json8
-rw-r--r--src/i18n/fr.json8
13 files changed, 159 insertions, 627 deletions
diff --git a/src/components/organisms/layout/index.ts b/src/components/organisms/layout/index.ts
index 4593ccc..86670e3 100644
--- a/src/components/organisms/layout/index.ts
+++ b/src/components/organisms/layout/index.ts
@@ -3,6 +3,4 @@ export * from './comments-list';
export * from './no-results';
export * from './overview';
export * from './posts-list';
-export * from './site-footer';
-export * from './site-header';
export * from './summary';
diff --git a/src/components/organisms/layout/site-footer.module.scss b/src/components/organisms/layout/site-footer.module.scss
deleted file mode 100644
index 158c419..0000000
--- a/src/components/organisms/layout/site-footer.module.scss
+++ /dev/null
@@ -1,26 +0,0 @@
-@use "../../../styles/abstracts/mixins" as mix;
-
-.wrapper {
- 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));
-
- @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;
-}
diff --git a/src/components/organisms/layout/site-footer.stories.tsx b/src/components/organisms/layout/site-footer.stories.tsx
deleted file mode 100644
index 3f244b0..0000000
--- a/src/components/organisms/layout/site-footer.stories.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import type { ComponentMeta, ComponentStory } from '@storybook/react';
-import { Icon } from '../../atoms';
-import { SiteFooter as SiteFooterComponent } from './site-footer';
-
-/**
- * SiteFooter - Storybook Meta
- */
-export default {
- title: 'Organisms/Layout',
- component: SiteFooterComponent,
- 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',
- },
- description: 'Set additional classnames to the footer element.',
- table: {
- category: 'Styles',
- },
- type: {
- name: 'string',
- required: false,
- },
- },
- copyright: {
- description: 'The copyright information.',
- type: {
- name: 'object',
- required: true,
- value: {},
- },
- },
- navItems: {
- description: 'The footer nav items.',
- table: {
- category: 'Options',
- },
- type: {
- name: 'object',
- required: false,
- value: {},
- },
- },
- topId: {
- control: {
- type: 'text',
- },
- description:
- 'An element id (without hashtag) used as target by back to top button.',
- type: {
- name: 'string',
- required: true,
- },
- },
- },
-} as ComponentMeta<typeof SiteFooterComponent>;
-
-const Template: ComponentStory<typeof SiteFooterComponent> = (args) => (
- <SiteFooterComponent {...args} />
-);
-
-const copyright = {
- from: '2017',
- owner: 'Lorem ipsum',
- to: '2022',
-};
-
-const navItems = [{ id: 'legal-notice', href: '#', label: 'Legal notice' }];
-
-/**
- * Layout Stories - SiteFooter
- */
-export const SiteFooter = Template.bind({});
-SiteFooter.args = {
- copyright,
- license: <Icon shape="cc-by-sa" />,
- navItems,
- topId: 'top',
-};
diff --git a/src/components/organisms/layout/site-footer.test.tsx b/src/components/organisms/layout/site-footer.test.tsx
deleted file mode 100644
index 3ad4022..0000000
--- a/src/components/organisms/layout/site-footer.test.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { describe, expect, it } from '@jest/globals';
-import { render, screen as rtlScreen } from '../../../../tests/utils';
-import { SiteFooter, type SiteFooterProps } from './site-footer';
-
-const copyright: SiteFooterProps['copyright'] = {
- from: '2017',
- owner: 'Lorem ipsum',
-};
-
-const navItems = [
- { id: 'legal-notice', href: '#', label: 'Legal notice' },
-] satisfies SiteFooterProps['navItems'];
-
-describe('SiteFooter', () => {
- it('renders the website copyright', () => {
- render(<SiteFooter copyright={copyright} topId="top" />);
- expect(
- rtlScreen.getByText(new RegExp(copyright.owner))
- ).toBeInTheDocument();
- expect(rtlScreen.getByText(new RegExp(copyright.from))).toBeInTheDocument();
- });
-
- it('renders a back to top link', () => {
- render(<SiteFooter copyright={copyright} topId="top" />);
- expect(
- rtlScreen.getByRole('link', { name: 'Back to top' })
- ).toBeInTheDocument();
- });
-
- it('renders some nav items', () => {
- render(
- <SiteFooter copyright={copyright} navItems={navItems} topId="top" />
- );
- expect(
- rtlScreen.getByRole('link', { name: navItems[0].label })
- ).toBeInTheDocument();
- });
-});
diff --git a/src/components/organisms/layout/site-footer.tsx b/src/components/organisms/layout/site-footer.tsx
deleted file mode 100644
index ccab051..0000000
--- a/src/components/organisms/layout/site-footer.tsx
+++ /dev/null
@@ -1,78 +0,0 @@
-import type { FC, ReactNode } from 'react';
-import { useIntl } from 'react-intl';
-import { Footer } from '../../atoms';
-import {
- BackToTop,
- type BackToTopProps,
- Colophon,
- type ColophonLink,
- type CopyrightProps,
- Copyright,
-} from '../../molecules';
-import styles from './site-footer.module.scss';
-
-export type SiteFooterProps = {
- /**
- * Set additional classnames to the back to top button.
- */
- backToTopClassName?: BackToTopProps['className'];
- /**
- * Set additional classnames to the footer element.
- */
- className?: string;
- /**
- * Set the copyright information.
- */
- copyright: CopyrightProps;
- /**
- * The website license.
- */
- license?: ReactNode;
- /**
- * The footer nav items.
- */
- navItems?: ColophonLink[];
- /**
- * An element id (without hashtag) used as anchor for back to top button.
- */
- topId: string;
-};
-
-/**
- * SiteFooter component
- *
- * Renders a footer with copyright and nav;
- */
-export const SiteFooter: FC<SiteFooterProps> = ({
- backToTopClassName,
- className = '',
- copyright,
- license,
- navItems,
- topId,
-}) => {
- const intl = useIntl();
- const backToTop = intl.formatMessage({
- defaultMessage: 'Back to top',
- description: 'SiteFooter: an accessible name for the back to top button',
- id: 'OHvb01',
- });
- const backToTopAnchor = `#${topId}`;
- const footerClass = `${styles.wrapper} ${className}`;
- const btnClass = `${styles['back-to-top']} ${backToTopClassName}`;
-
- return (
- <Footer className={footerClass}>
- <Colophon
- copyright={<Copyright {...copyright} />}
- license={license}
- links={navItems}
- />
- <BackToTop
- anchor={backToTopAnchor}
- className={btnClass}
- label={backToTop}
- />
- </Footer>
- );
-};
diff --git a/src/components/organisms/layout/site-header.module.scss b/src/components/organisms/layout/site-header.module.scss
deleted file mode 100644
index 573d455..0000000
--- a/src/components/organisms/layout/site-header.module.scss
+++ /dev/null
@@ -1,50 +0,0 @@
-@use "../../../styles/abstracts/functions" as fun;
-@use "../../../styles/abstracts/mixins" as mix;
-
-.wrapper {
- 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);
-
- .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;
- }
- }
- }
-}
-
-.body {
- grid-column: 2;
- display: flex;
- flex-flow: row wrap;
- align-items: center;
- justify-content: space-between;
- gap: var(--spacing-md);
-}
diff --git a/src/components/organisms/layout/site-header.stories.tsx b/src/components/organisms/layout/site-header.stories.tsx
deleted file mode 100644
index e69ebfd..0000000
--- a/src/components/organisms/layout/site-header.stories.tsx
+++ /dev/null
@@ -1,162 +0,0 @@
-import type { ComponentMeta, ComponentStory } from '@storybook/react';
-import NextImage from 'next/image';
-import { Heading } from '../../atoms';
-import { SiteHeader as SiteHeaderComponent } from './site-header';
-
-/**
- * SiteHeader - Storybook Meta
- */
-export default {
- title: 'Organisms/Layout',
- component: SiteHeaderComponent,
- args: {
- ackeeStorageKey: 'ackee-tracking',
- isHome: false,
- motionStorageKey: 'reduced-motion',
- searchPage: '#',
- withLink: false,
- },
- argTypes: {
- ackeeStorageKey: {
- control: {
- type: 'text',
- },
- description: 'Set Ackee settings local storage key.',
- type: {
- name: 'string',
- required: true,
- },
- },
- baseline: {
- control: {
- type: 'text',
- },
- description: 'The branding baseline.',
- table: {
- category: 'Options',
- },
- type: {
- name: 'string',
- required: false,
- },
- },
- className: {
- control: {
- type: 'text',
- },
- description: 'Set additional classnames to the header wrapper.',
- table: {
- category: 'Styles',
- },
- type: {
- name: 'string',
- required: false,
- },
- },
- isHome: {
- control: {
- type: 'boolean',
- },
- description: 'Determine if the current page is homepage or not.',
- table: {
- category: 'Options',
- },
- type: {
- name: 'boolean',
- required: false,
- },
- },
- motionStorageKey: {
- control: {
- type: 'text',
- },
- description: 'Set Reduced motion settings local storage key.',
- type: {
- name: 'string',
- required: true,
- },
- },
- nav: {
- description: 'The main navigation items.',
- type: {
- name: 'object',
- required: true,
- value: {},
- },
- },
- photo: {
- control: {
- type: 'text',
- },
- description: 'The branding photo.',
- type: {
- name: 'string',
- required: true,
- },
- },
- searchPage: {
- control: {
- type: 'text',
- },
- description: 'The search results page url.',
- type: {
- name: 'string',
- required: true,
- },
- },
- title: {
- control: {
- type: 'text',
- },
- description: 'The website title.',
- type: {
- name: 'string',
- required: true,
- },
- },
- withLink: {
- control: {
- type: 'boolean',
- },
- description: 'Wrap the website title with a link to homepage.',
- table: {
- category: 'Options',
- },
- type: {
- name: 'boolean',
- required: false,
- },
- },
- },
- parameters: {
- layout: 'fullscreen',
- },
-} as ComponentMeta<typeof SiteHeaderComponent>;
-
-const Template: ComponentStory<typeof SiteHeaderComponent> = (args) => (
- <SiteHeaderComponent {...args} />
-);
-
-const nav = [
- { id: 'home-link', href: '#', label: 'Home' },
- { id: 'blog-link', href: '#', label: 'Blog' },
- { id: 'cv-link', href: '#', label: 'CV' },
- { id: 'contact-link', href: '#', label: 'Contact' },
-];
-
-/**
- * Layout Stories - SiteHeader
- */
-export const SiteHeader = Template.bind({});
-SiteHeader.args = {
- nav,
- logo: (
- <NextImage
- alt="A logo"
- height={100}
- src="https://picsum.photos/100"
- width={100}
- />
- ),
- name: <Heading level={1}>Website title</Heading>,
-};
diff --git a/src/components/organisms/layout/site-header.test.tsx b/src/components/organisms/layout/site-header.test.tsx
deleted file mode 100644
index fa1b7be..0000000
--- a/src/components/organisms/layout/site-header.test.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import { describe, expect, it } from '@jest/globals';
-import NextImage from 'next/image';
-import { render, screen as rtlScreen } from '../../../../tests/utils';
-import { SiteHeader } from './site-header';
-
-const nav = [
- { id: 'home-link', href: '#', label: 'Home' },
- { id: 'blog-link', href: '#', label: 'Blog' },
- { id: 'cv-link', href: '#', label: 'CV' },
- { id: 'contact-link', href: '#', label: 'Contact' },
-];
-
-const title = 'Assumenda quis quod';
-
-describe('SiteHeader', () => {
- it('renders the website title', () => {
- render(
- <SiteHeader
- ackeeStorageKey="ackee-tracking"
- logo={
- <NextImage
- alt="A logo"
- height={200}
- src="https://picsum.photos/200"
- width={200}
- />
- }
- motionStorageKey="reduced-motion"
- name={<h1>{title}</h1>}
- nav={nav}
- searchPage="#"
- />
- );
- expect(
- rtlScreen.getByRole('heading', { level: 1, name: title })
- ).toBeInTheDocument();
- });
-
- it('renders the main nav', () => {
- render(
- <SiteHeader
- ackeeStorageKey="ackee-tracking"
- logo={
- <NextImage
- alt="A photo"
- height={200}
- src="https://picsum.photos/200"
- width={200}
- />
- }
- motionStorageKey="reduced-motion"
- name={<div>{title}</div>}
- nav={nav}
- searchPage="#"
- />
- );
- expect(rtlScreen.getByRole('navigation')).toBeInTheDocument();
- });
-});
diff --git a/src/components/organisms/layout/site-header.tsx b/src/components/organisms/layout/site-header.tsx
deleted file mode 100644
index e8953c0..0000000
--- a/src/components/organisms/layout/site-header.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import type { FC } from 'react';
-import { Header } from '../../atoms';
-import { Branding, type BrandingProps } from '../../molecules';
-import { Toolbar, type ToolbarProps } from '../toolbar';
-import styles from './site-header.module.scss';
-
-export type SiteHeaderProps = BrandingProps &
- Pick<
- ToolbarProps,
- 'ackeeStorageKey' | 'motionStorageKey' | 'nav' | 'searchPage'
- > & {
- /**
- * Set additional classnames to the header element.
- */
- className?: string;
- };
-
-/**
- * SiteHeader component
- *
- * Render the website header.
- */
-export const SiteHeader: FC<SiteHeaderProps> = ({
- ackeeStorageKey,
- className,
- motionStorageKey,
- nav,
- searchPage,
- ...props
-}) => {
- const headerClass = `${styles.wrapper} ${className}`;
-
- return (
- <Header className={headerClass}>
- <div className={styles.body}>
- <Branding {...props} />
- <Toolbar
- ackeeStorageKey={ackeeStorageKey}
- className={styles.toolbar}
- motionStorageKey={motionStorageKey}
- nav={nav}
- searchPage={searchPage}
- />
- </div>
- </Header>
- );
-};
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>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 2fd2edf..5984b2d 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -291,6 +291,10 @@
"defaultMessage": "Other thematics",
"description": "ThematicPage: other thematics list widget title"
},
+ "Kjj1Zk": {
+ "defaultMessage": "Back to top",
+ "description": "Layout: an accessible name for the back to top button"
+ },
"KnWeKh": {
"defaultMessage": "Page not found",
"description": "Error404Page: page title"
@@ -331,10 +335,6 @@
"defaultMessage": "Github profile",
"description": "ProjectsPage: Github profile link"
},
- "OHvb01": {
- "defaultMessage": "Back to top",
- "description": "SiteFooter: an accessible name for the back to top button"
- },
"OL0Yzx": {
"defaultMessage": "Publish",
"description": "CommentForm: submit button"
diff --git a/src/i18n/fr.json b/src/i18n/fr.json
index bebfc47..2b20b14 100644
--- a/src/i18n/fr.json
+++ b/src/i18n/fr.json
@@ -291,6 +291,10 @@
"defaultMessage": "Autres thématiques",
"description": "ThematicPage: other thematics list widget title"
},
+ "Kjj1Zk": {
+ "defaultMessage": "Retour en haut de page",
+ "description": "Layout: an accessible name for the back to top button"
+ },
"KnWeKh": {
"defaultMessage": "Page non trouvée",
"description": "Error404Page: page title"
@@ -331,10 +335,6 @@
"defaultMessage": "Profil Github",
"description": "ProjectsPage: Github profile link"
},
- "OHvb01": {
- "defaultMessage": "Retour en haut de page",
- "description": "SiteFooter: an accessible name for the back to top button"
- },
"OL0Yzx": {
"defaultMessage": "Publier",
"description": "CommentForm: submit button"