Skip to content

Commit 4b9994f

Browse files
authored
Merge pull request #1160 from CodeForAfrica/trustlab_header_footer
Trustlab Navigation/Footer components
2 parents c0a903d + eb37377 commit 4b9994f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1559
-621
lines changed

apps/trustlab/jest.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ module.exports = {
1111
"<rootDir>/../../packages/commons-ui-core/src/$1",
1212
"^@/commons-ui/next/(.*)$":
1313
"<rootDir>/../../packages/commons-ui-next/src/$1",
14+
"^@/commons-ui/payload/(.*)$":
15+
"<rootDir>/../../packages/commons-ui-payload/src/$1",
1416
"^next/font/google$": "<rootDir>/__mocks__/nextFontMock.js",
1517
},
1618
};

apps/trustlab/package.json

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
"@commons-ui/payload": "workspace:*",
2222
"@emotion/react": "catalog:",
2323
"@emotion/styled": "catalog:",
24-
"@mui/material": "catalog:mui-v7",
25-
"@mui/utils": "catalog:mui-v7",
24+
"@mui/material": "catalog:",
25+
"@mui/utils": "catalog:",
2626
"@next/third-parties": "catalog:",
2727
"@payloadcms/admin-bar": "catalog:payload-v3",
2828
"@payloadcms/db-mongodb": "catalog:payload-v3",
@@ -39,27 +39,26 @@
3939
"@sentry/nextjs": "catalog:",
4040
"cross-env": "catalog:",
4141
"graphql": "catalog:payload-v3",
42-
"next": "catalog:",
4342
"next-seo": "catalog:",
43+
"next": "catalog:",
4444
"payload": "catalog:payload-v3",
45-
"react": "catalog:",
4645
"react-dom": "catalog:",
46+
"react": "catalog:",
4747
"require-in-the-middle": "^7.5.2",
4848
"sharp": "catalog:",
4949
"swr": "catalog:"
5050
},
5151
"devDependencies": {
5252
"@commons-ui/testing-library": "workspace:*",
53-
"@eslint/eslintrc": "catalog:",
5453
"@svgr/webpack": "catalog:",
54+
"@testing-library/react": "catalog:",
5555
"babel-jest": "catalog:",
56-
"eslint": "catalog:",
5756
"eslint-config-commons-ui": "workspace:*",
58-
"eslint-config-next": "catalog:",
59-
"eslint-import-resolver-babel-module": "catalog:",
60-
"jest": "catalog:",
57+
"eslint-import-resolver-webpack": "catalog:",
58+
"eslint-plugin-import": "catalog:",
59+
"eslint": "catalog:",
6160
"jest-config-commons-ui": "workspace:*",
62-
"playwright-config-commons-ui": "workspace:*",
63-
"@testing-library/react": "catalog:"
61+
"jest": "catalog:",
62+
"playwright-config-commons-ui": "workspace:*"
6463
}
6564
}
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 5 additions & 0 deletions
Loading
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { Section, StayInTouch } from "@commons-ui/core";
2+
import { Link, HtmlEmbed } from "@commons-ui/next";
3+
import { Box, Grid } from "@mui/material";
4+
import React from "react";
5+
6+
import FooterDescription from "./FooterDescription";
7+
8+
import FooterLinks from "@/trustlab/components/FooterLinks";
9+
10+
const Footer = React.forwardRef(function Footer(props, ref) {
11+
const { connect, description, newsletter, primaryMenus, secondaryMenus } =
12+
props;
13+
14+
const htmlEmbedStyles = (theme) => ({
15+
"& #mc_embed_signup": {
16+
typography: "body1",
17+
backgroundColor: "unset",
18+
color: "inherit",
19+
width: "100%",
20+
},
21+
"& #mc_embed_signup input[type=text], & #mc_embed_signup input[type=email]":
22+
{
23+
typography: "body1",
24+
border: "1px solid #D0CBCB",
25+
borderRadius: 0,
26+
display: "flex",
27+
height: theme.typography.pxToRem(36),
28+
marginTop: 0,
29+
marginBottom: theme.typography.pxToRem(30),
30+
outline: "none",
31+
padding: `0 ${theme.typography.pxToRem(12)}`,
32+
width: "100%",
33+
},
34+
"& #mc_embed_signup input::placeholder": {
35+
color: "#D0CBCB",
36+
opacity: 1.0,
37+
WebkitTextFillColor: "#D0CBCB",
38+
},
39+
"& #mc_embed_signup input:focus, #mc_embed_signup textarea:focus": {
40+
border: `1px solid ${theme.palette?.primary?.main}`,
41+
},
42+
"& #mc_embed_signup input:active, #mc_embed_signup textarea:active": {
43+
border: `1px solid ${theme.palette?.highlight?.main}`,
44+
},
45+
"& #mc_embed_signup input[type=submit]": {
46+
typography: "subtitle1",
47+
background: "none",
48+
border: `1px solid ${theme.palette?.text?.secondary}`,
49+
color: "inherit",
50+
padding: `${theme.typography.pxToRem(6)} ${theme.typography.pxToRem(12)}`,
51+
textDecoration: "none",
52+
},
53+
"& #mc_embed_signup input[type=submit]:hover": {
54+
cursor: "pointer",
55+
background: theme.palette?.text?.secondary,
56+
color: theme.palette?.text?.primary,
57+
},
58+
});
59+
60+
return (
61+
<Box
62+
sx={({ palette }) => ({
63+
backgroundColor: palette.common.black,
64+
color: palette.text.secondary,
65+
px: 0,
66+
py: { xs: 10, md: 13.75, lg: 12.5 },
67+
})}
68+
component="footer"
69+
ref={ref}
70+
>
71+
<Section sx={{ px: { xs: 2.5, sm: 0 } }}>
72+
{/* Increase number of columns to getter columns size */}
73+
<Grid container columns={24} justifyContent="space-between">
74+
<Grid
75+
item
76+
xs={24}
77+
md={15}
78+
lg={16}
79+
sx={{
80+
order: { xs: 1, md: 0 },
81+
}}
82+
>
83+
<Grid container justifyContent="space-between">
84+
<Grid
85+
item
86+
xs={12}
87+
md="auto"
88+
container
89+
direction="column"
90+
sx={{
91+
maxWidth: { xs: "none", md: "337px" },
92+
}}
93+
>
94+
<Grid item>
95+
<FooterDescription
96+
description={description}
97+
logo={null}
98+
sx={{ mt: { xs: 10, md: 0 } }}
99+
/>
100+
</Grid>
101+
<Grid item>
102+
<StayInTouch
103+
{...connect}
104+
LinkProps={{ component: Link }}
105+
TitleProps={{ variant: "footerCap" }}
106+
sx={{ mt: "52px" }}
107+
/>
108+
</Grid>
109+
</Grid>
110+
<Grid item xs={12} md="auto">
111+
<FooterLinks
112+
primaryMenus={primaryMenus}
113+
secondaryMenus={secondaryMenus}
114+
sx={{ mt: { xs: "52px", md: 0 } }}
115+
/>
116+
</Grid>
117+
</Grid>
118+
</Grid>
119+
<Grid item xs={24} md="auto" sx={{ order: { xs: 0, md: 1 } }}>
120+
<HtmlEmbed
121+
EmbedCodeProps={{ sx: htmlEmbedStyles }}
122+
{...newsletter}
123+
/>
124+
</Grid>
125+
</Grid>
126+
</Section>
127+
</Box>
128+
);
129+
});
130+
131+
export default Footer;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`<Footer /> renders unchanged 1`] = `
4+
<div>
5+
<footer
6+
class="MuiBox-root css-g6071f"
7+
>
8+
<div
9+
class="MuiContainer-root MuiContainer-maxWidthLg MuiContainer-fixed MuiContainer-disableGutters css-iz79el-MuiContainer-root"
10+
>
11+
<div
12+
class="MuiGrid-root MuiGrid-container css-1xzqqmo-MuiGrid-root"
13+
>
14+
<div
15+
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-24 MuiGrid-grid-md-15 MuiGrid-grid-lg-16 css-182fz6w-MuiGrid-root"
16+
>
17+
<div
18+
class="MuiGrid-root MuiGrid-container css-1xzqqmo-MuiGrid-root"
19+
>
20+
<div
21+
class="MuiGrid-root MuiGrid-container MuiGrid-item MuiGrid-direction-xs-column MuiGrid-grid-xs-12 MuiGrid-grid-md-auto css-12olfi-MuiGrid-root"
22+
>
23+
<div
24+
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root"
25+
/>
26+
<div
27+
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root"
28+
/>
29+
</div>
30+
<div
31+
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-md-auto css-gjb3vx-MuiGrid-root"
32+
/>
33+
</div>
34+
</div>
35+
<div
36+
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-24 MuiGrid-grid-md-auto css-4ah52f-MuiGrid-root"
37+
/>
38+
</div>
39+
</div>
40+
</footer>
41+
</div>
42+
`;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { createRender } from "@commons-ui/testing-library";
2+
import React from "react";
3+
4+
import Footer from "./Footer";
5+
6+
import theme from "@/trustlab/theme";
7+
8+
const render = createRender({ theme });
9+
10+
const defaultProps = {
11+
subscription: {
12+
embedCode: "",
13+
title: "Subscribe",
14+
},
15+
secondaryMenu: [
16+
{ content: "Imprint", href: "/imprint" },
17+
{ content: "Privacy policy", href: "/policy" },
18+
],
19+
menus: [
20+
{
21+
content: "Our Work",
22+
href: "/our-work",
23+
},
24+
{
25+
content: "About",
26+
href: "/about",
27+
},
28+
{
29+
content: "Stories",
30+
href: "/about",
31+
},
32+
{
33+
content: "Opportunity",
34+
href: "/opportunity",
35+
},
36+
{
37+
content: "Contact",
38+
href: "/contact",
39+
},
40+
],
41+
};
42+
43+
describe("<Footer />", () => {
44+
it("renders unchanged", () => {
45+
const { container } = render(<Footer {...defaultProps} />);
46+
expect(container).toMatchSnapshot();
47+
});
48+
});
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* eslint-env browser */
2+
import { Figure, Link } from "@commons-ui/next";
3+
import { LexicalRichText } from "@commons-ui/payload";
4+
import { Stack } from "@mui/material";
5+
import React from "react";
6+
7+
const FooterDescription = React.forwardRef(
8+
function FooterDescription(props, ref) {
9+
const { description, logo, sx } = props;
10+
11+
if (!(logo || description)) {
12+
return null;
13+
}
14+
return (
15+
<Stack alignItems={{ xs: "center", md: "flex-start" }} sx={sx} ref={ref}>
16+
<Link href="/">
17+
<Figure
18+
ImageProps={logo}
19+
sx={{
20+
display: {
21+
sm: "block",
22+
},
23+
filter: "grayscale(100%)",
24+
height: { xs: "113px", md: "113px", lg: "113px" },
25+
width: { xs: "251px", md: "251px", lg: "251px" },
26+
}}
27+
/>
28+
</Link>
29+
<LexicalRichText
30+
variant="footer"
31+
TypographyProps={{
32+
LinkProps: {
33+
color: "text.secondary",
34+
sx: { textDecorationColor: "text.secondary" },
35+
},
36+
sx: { mt: { xs: 2, md: 0 } },
37+
}}
38+
sx={(theme) => ({
39+
a: {
40+
textDecorationColor: theme.palette.text.secondary,
41+
},
42+
textAlign: { xs: "center", md: "left" },
43+
typography: "footer",
44+
mt: 0,
45+
})}
46+
ref={ref}
47+
elements={description}
48+
/>
49+
</Stack>
50+
);
51+
},
52+
);
53+
54+
export default FooterDescription;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Footer from "./Footer";
2+
3+
export default Footer;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { NavListItem } from "@commons-ui/core";
2+
import { Link } from "@commons-ui/next";
3+
import { Box } from "@mui/material";
4+
import React from "react";
5+
6+
import FooterNavList from "@/trustlab/components/FooterNavList";
7+
8+
const FooterLinks = React.forwardRef(function FooterLinks(props, ref) {
9+
const { primaryMenus, secondaryMenus, sx } = props;
10+
11+
if (!(primaryMenus?.length || secondaryMenus?.length)) {
12+
return null;
13+
}
14+
return (
15+
<Box sx={sx} ref={ref}>
16+
<FooterNavList menus={primaryMenus}>
17+
{secondaryMenus?.map((item, i) => (
18+
<NavListItem
19+
sx={{
20+
display: "flex",
21+
justifyContent: { xs: "center", md: "flex-start" },
22+
mt: i === 0 ? 5 : undefined,
23+
p: "0 0 10px",
24+
}}
25+
key={item.href}
26+
>
27+
<Link
28+
underline="none"
29+
variant="body2SemiBold"
30+
sx={{
31+
color: "text.secondary",
32+
}}
33+
href={item.href}
34+
>
35+
{item.label}
36+
</Link>
37+
</NavListItem>
38+
)) ?? null}
39+
</FooterNavList>
40+
</Box>
41+
);
42+
});
43+
44+
export default FooterLinks;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import FooterLinks from "./FooterLinks";
2+
3+
export default FooterLinks;

0 commit comments

Comments
 (0)