Skip to content

Commit

Permalink
Addition of footer (#12)
Browse files Browse the repository at this point in the history
* Adding footer and footer stories

* Added in props option to allow for custom props. Fixed styling.

* tests added for footer

* coverage folder added to git ignore

* Standardised exports

* Coverage job added to json package

* resolving MR comments.

* removing duped from p json

* jest-transform-stub added for tests to pass with svgs

* addressing MR comments.

* adding extra checks for tests

* removed all data-testid from tests and component

* Footer now appears at the bottom of the page and not sticky

* Footer links will stack wehen page gets narrower

* addressing MR comments

* addressed MR comments to copyright text

* added company instead of text

* addressing MR commet to allow changing of styles without TS complaining
  • Loading branch information
RhysMAdey authored Dec 16, 2024
1 parent d16ac65 commit 1f385f7
Show file tree
Hide file tree
Showing 9 changed files with 299 additions and 26 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/dist/
/node_modules/
/coverage

*storybook.log

Expand Down
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
module.exports = {
testEnvironment: "jsdom",
moduleNameMapper: {
'^.+.(svg)$': 'jest-transform-stub',
}
};
18 changes: 7 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"lint": "eslint .",
"rollup": "rollup --config rollup.config.mjs",
"jest": "jest --config jest.config.js",
"jest:coverage": "jest --coverage",
"storybook": "storybook dev -p 6006",
"storybook:build": "storybook build -o storybook-static",
"storybook:publish": "gh-pages -b storybook/publish -d storybook-static"
Expand All @@ -22,21 +23,17 @@
"types": "dist/index.d.ts",
"dependencies": {
"@mui/icons-material": "^6.1.7",
"jest-transform-stub": "^2.0.0",
"react-icons": "^5.3.0"
},
"peerDependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",
"@mui/material": "^6.1.7",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0"
"@emotion/styled": "^11.13.0",
"@mui/material": "^6.1.7",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",
"@mui/material": "^6.1.7",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@babel/preset-react": "^7.25.9",
Expand Down Expand Up @@ -78,8 +75,7 @@
"storybook-dark-mode": "^4.0.2",
"tslib": "^2.8.1",
"typescript": "^5.6.3",
"typescript-eslint": "^8.15.0",
"@testing-library/jest-dom": "^6.6.3"
"typescript-eslint": "^8.15.0"
},
"packageManager": "[email protected]+sha256.24235772cc4ac82a62627cd47f834c72667a2ce87799a846ec4e8e555e2d4b8b"
}
56 changes: 56 additions & 0 deletions src/components/Footer.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Meta, StoryObj } from "@storybook/react/*";
import { Footer, FooterLink, FooterLinks } from "./Footer";

const meta: Meta<typeof Footer> = {
title: "SciReactUI/Navigation/Footer",
component: Footer,
decorators: [(Story) => <Story />],
tags: ["autodocs"],
};

export default meta;
type Story = StoryObj<typeof meta>;

export const LogoOnly: Story = {
args: {},
};

export const CopyrightOnly: Story = {
args: {
logo: "",
copyright: "Company",
},
};

export const CopyrightAndLogo: Story = {
args: { copyright: "Company" },
};

export const WithOneLink: Story = {
args: {
copyright: "Company",
children: [
<FooterLinks key="footer-links">
<FooterLink href="#" key="first-footer-link">
Link one
</FooterLink>
</FooterLinks>,
],
},
};

export const WithTwoLinks: Story = {
args: {
copyright: "Company",
children: [
<FooterLinks key="footer-links">
<FooterLink href="#" key="first-footer-link">
Link one
</FooterLink>
<FooterLink href="#" key="second-footer-link">
Link two
</FooterLink>
</FooterLinks>,
],
},
};
88 changes: 88 additions & 0 deletions src/components/Footer.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { render, screen, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";

import dlsLogo from "../public/dls.svg";

import { Footer, FooterLink, FooterLinks } from "./Footer";
describe("Footer", () => {
test("Should render logo only", async () => {
render(<Footer logo={dlsLogo} />);

await waitFor(() => {
expect(screen.getByRole("img")).toBeInTheDocument();
// No copyright text
expect(screen.queryByRole("paragraph")).not.toBeTruthy();
});
});

test("Should render copyright only", async () => {
const copyrightText = "add text here";
render(<Footer logo={null} copyright={copyrightText} />);

await waitFor(() => {
expect(screen.queryByRole("paragraph")).toBeInTheDocument();
expect(screen.queryByRole("paragraph")?.textContent).toStrictEqual(
`Copyright © 2024 ${copyrightText}`
);
// No logo
expect(screen.queryByRole("img")).not.toBeTruthy();
});
});

test("Should render logo and copyright", async () => {
const copyrightText = "add text here";
render(<Footer logo={dlsLogo} copyright={copyrightText} />);

await waitFor(() => {
expect(screen.getByRole("img")).toBeInTheDocument();
expect(screen.queryByRole("paragraph")).toBeInTheDocument();
expect(screen.queryByRole("paragraph")?.textContent).toStrictEqual(
`Copyright © 2024 ${copyrightText}`
);
});
});

test("Should render with one link", async () => {
const lineOneText = "Link one";
const linkOneName = "link-one-href";

render(
<Footer>
<FooterLinks>
<FooterLink href={linkOneName}>{lineOneText}</FooterLink>
</FooterLinks>
</Footer>
);

await waitFor(() => {
const linkOneContainer = screen.getByText(lineOneText);

expect(linkOneContainer).toBeInTheDocument();
expect(linkOneContainer.getAttribute("href")).toStrictEqual(linkOneName);
expect(linkOneContainer.textContent).toStrictEqual(lineOneText);
});
});

test("Should render with two links", async () => {
const linkOneText = "Link one";
const linkTwoText = "Link two";
const linkOneName = "link-one-href";
const linkTwoName = "link-two-href";
render(
<Footer>
<FooterLinks>
<FooterLink href={linkOneName}>{linkOneText}</FooterLink>
<FooterLink href={linkTwoName}>{linkTwoText}</FooterLink>
</FooterLinks>
</Footer>
);

await waitFor(() => {
const linkTwoContainer = screen.getByText(linkTwoText);

expect(linkTwoContainer).toBeInTheDocument();
expect(linkTwoContainer.getAttribute("href")).toStrictEqual(linkTwoName);
expect(linkTwoContainer.textContent).toStrictEqual(linkTwoText);
});
});
});
115 changes: 115 additions & 0 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { Link, LinkProps, Typography, useTheme } from "@mui/material";
import Grid from "@mui/material/Grid2";
import dlsLogo from "../public/logo-short.svg";
import React from "react";

interface FooterLinksProps {
children: React.ReactElement<LinkProps> | React.ReactElement<LinkProps>[];
}

interface FooterProps extends React.HTMLProps<HTMLDivElement> {
/** Location/content of the logo */
logo?: string | null;
copyright?: string | null;
children?: React.ReactElement | React.ReactElement[];
}

const FooterLinks = ({ children }: FooterLinksProps) => {
return (
<div
style={{
float: "left",
alignItems: "center",
borderTop: "4px solid transparent",
borderBottom: "4px solid transparent",
display: "flex",
flexWrap: "wrap",
}}
>
{children}
</div>
);
};

const FooterLink = ({ children, ...props }: LinkProps) => {
const theme = useTheme();

return (
<Link
sx={{
"&:hover": {
color: theme.palette.secondary.main,
borderBottom: "solid 4px",
},
textDecoration: "none",
color: theme.palette.primary.contrastText,
marginLeft: "1.5rem",
cursor: "pointer",
}}
{...props}
>
{children}
</Link>
);
};

/*
* Basic footer bar.
* Can be used with `FooterLinks` and `FooterLink` to display a list of links.
*/
const Footer = ({
logo = dlsLogo as string,
copyright,
children,
...props
}: FooterProps) => {
const theme = useTheme();

return (
<footer
style={{
bottom: 0,
marginTop: "auto",
minHeight: 50,
backgroundColor: theme.palette.primary.light,
}}
{...props}
>
<Grid container>
<Grid
size={{ xs: 6, md: 8 }}
style={{
alignContent: "center",
}}
>
{children}
</Grid>
<Grid size={{ xs: 6, md: 4 }}>
<div
style={{
float: "right",
paddingTop: "10px",
paddingRight: "15px",
textAlign: "right",
}}
>
{logo ? <img alt="footer-logo" src={logo} /> : null}
{copyright ? (
<Typography
style={{
margin: 0,
color: theme.palette.primary.contrastText,
}}
>
{`Copyright © ${new Date().getFullYear()} ${copyright}`}
</Typography>
) : null}
</div>
</Grid>
</Grid>
</footer>
);
};

export { Footer, FooterLinks, FooterLink };
export type { FooterLinksProps, FooterProps };
32 changes: 17 additions & 15 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
useTheme,
} from "@mui/material";
import { MdMenu, MdClose } from "react-icons/md";
import logoImage from "../public/logo-dark.svg"
import logoImage from "../public/logo-dark.svg";
import React, { useState } from "react";

interface NavLinksProps {
Expand Down Expand Up @@ -83,12 +83,12 @@ const NavLinks = ({ children }: NavLinksProps) => {
{children}
</Stack>
<Drawer
open={isOpen}
onClose={onClose}
anchor="left"
PaperProps={{
sx:{backgroundColor:theme.palette.primary.main}
}}
open={isOpen}
onClose={onClose}
anchor="left"
PaperProps={{
sx: { backgroundColor: theme.palette.primary.main },
}}
>
<Box
sx={{
Expand Down Expand Up @@ -116,13 +116,13 @@ const Navbar = ({
...props
}: NavbarProps) => {
const theme = useTheme();

return (
<Box position="sticky" top="0" zIndex={1} width="100%" {...props}>
<Box top="0" zIndex={1} width="100%" {...props}>
<Paper
sx={{
display: "flex",
backgroundColor:theme.palette.primary.main,
backgroundColor: theme.palette.primary.main,
px: { xs: "1rem", md: "7.5vw" },
height: 50,
width: "100%",
Expand All @@ -138,11 +138,13 @@ const Navbar = ({
>
{logo ? (
<Link href="/" key="logo">
<Box maxWidth="5rem"
<Box
maxWidth="5rem"
sx={{
"&:hover": { filter: "brightness(80%);" }
}}>
<img
"&:hover": { filter: "brightness(80%);" },
}}
>
<img
alt="Home"
src={logo}
width={"100px"}
Expand All @@ -159,4 +161,4 @@ const Navbar = ({
};

export { Navbar, NavLinks, NavLink };
export type {NavLinksProps, NavbarProps };
export type { NavLinksProps, NavbarProps };
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// components
export * from "./components/Breadcrumbs";
export * from "./components/Navbar";
export * from "./components/Footer";
export * from "./components/User";
export * from "./components/VisitInput";

Expand Down
Loading

0 comments on commit 1f385f7

Please sign in to comment.