1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
import photo from '@assets/images/armand-philippot.jpg';
import ButtonLink from '@components/atoms/buttons/button-link';
import Career from '@components/atoms/icons/career';
import CCBySA from '@components/atoms/icons/cc-by-sa';
import ComputerScreen from '@components/atoms/icons/computer-screen';
import Envelop from '@components/atoms/icons/envelop';
import Home from '@components/atoms/icons/home';
import PostsStack from '@components/atoms/icons/posts-stack';
import Main from '@components/atoms/layout/main';
import NoScript from '@components/atoms/layout/no-script';
import Footer from '@components/organisms/layout/footer';
import Header, { HeaderProps } from '@components/organisms/layout/header';
import { settings } from '@utils/config';
import { FC, ReactNode } from 'react';
import { useIntl } from 'react-intl';
import styles from './layout.module.scss';
export type LayoutProps = Pick<HeaderProps, 'isHome'> & {
/**
* The layout main content.
*/
children: ReactNode;
/**
* Set additional classnames to the article element.
*/
className?: string;
};
/**
* Layout component
*
* Render the base layout used by all pages.
*/
const Layout: FC<LayoutProps> = ({ children, isHome, ...props }) => {
const intl = useIntl();
const skipToContent = intl.formatMessage({
defaultMessage: 'Skip to content',
description: 'Layout: Skip to content link',
id: 'K4rYdT',
});
const noScript = intl.formatMessage({
defaultMessage:
'Warning: If you want to benefit from all features (search for example), please activate Javascript.',
description: 'Layout: noscript message',
id: '7jVUT6',
});
const copyright = {
dates: {
start: settings.copyright.startYear,
end: settings.copyright.endYear,
},
owner: settings.name,
icon: <CCBySA />,
};
const homeLabel = intl.formatMessage({
defaultMessage: 'Home',
description: 'Layout: main nav - home link',
id: 'bojYF5',
});
const blogLabel = intl.formatMessage({
defaultMessage: 'Blog',
description: 'Layout: main nav - blog link',
id: 'D8vB38',
});
const projectsLabel = intl.formatMessage({
defaultMessage: 'Projects',
description: 'Layout: main nav - projects link',
id: 'qnwsWV',
});
const cvLabel = intl.formatMessage({
defaultMessage: 'CV',
description: 'Layout: main nav - cv link',
id: 'R895yC',
});
const contactLabel = intl.formatMessage({
defaultMessage: 'Contact',
description: 'Layout: main nav - contact link',
id: 'AE4kCD',
});
const nav: HeaderProps['nav'] = [
{ id: 'home', label: homeLabel, href: '#', logo: <Home /> },
{ id: 'blog', label: blogLabel, href: '#', logo: <PostsStack /> },
{
id: 'projects',
label: projectsLabel,
href: '#',
logo: <ComputerScreen />,
},
{ id: 'cv', label: cvLabel, href: '#', logo: <Career /> },
{ id: 'contact', label: contactLabel, href: '#', logo: <Envelop /> },
];
return (
<>
<noscript>
<div className={styles['noscript-spacing']}></div>
</noscript>
<span tabIndex={-1}></span>
<ButtonLink target="#main" className="screen-reader-text">
{skipToContent}
</ButtonLink>
<Header
title={settings.name}
baseline={settings.baseline.fr}
photo={photo.src}
nav={nav}
isHome={isHome}
className={styles.header}
withLink={true}
/>
<Main id="main" className={styles.main}>
<article {...props}>{children}</article>
</Main>
<Footer copyright={copyright} topId="top" className={styles.footer} />
<noscript>
<NoScript message={noScript} position="top" />
</noscript>
</>
);
};
export default Layout;
|