Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DEV-027] Footer #46

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion frontend/components/Footer/Footer.module.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
.footer {
width: 100%;
width: 101.23%;
height: 100px;
border-top: 1px solid #eaeaea;
box-shadow: 0px 2px 20px rgba(0, 0, 0, 0.25);
background-color: #343a40;
display: flex;
justify-content: center;
align-items: center;
Expand Down
61 changes: 52 additions & 9 deletions frontend/components/Footer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,60 @@
import {
Center,
Flex,
GridItem,
Heading,
HStack,
SimpleGrid,
Text,
useBreakpointValue,
} from "@chakra-ui/react";
import React from "react";

import styles from "./Footer.module.css";

export const footerLinks = [
"Terms",
"Privacy",
"Help",
"API",
"Status",
"Blog",
];

export const Footer = (): JSX.Element => {
const verticalOffset = useBreakpointValue({ sm: "", md: "6" });
const spacing = useBreakpointValue({ xs: 6, sm: 14 });

return (
<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Hello{" "}
</a>
</footer>
<Flex className={styles.footer}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Since this component is used outside of the main component, we need a semantic sectional HTML element wrapping it, rather than a div. Can we wrap this in a footer?

Suggested change
<Flex className={styles.footer}>
<Flex className={styles.footer} as="footer">

Reference: https://www.w3.org/TR/wai-aria-practices/examples/landmarks/HTML5.html

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, just read up on the ARIA practices and accessible considerations! Does your fix automatically do the role="footer" tag onto the footer as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't automatically add a role="footer", rather it's a replacement to it!
It's recommended to use semantic html elements over adding roles to ambigious elements.
I believe just having it as a footer html element should be sufficient considering we're only using it at the end of the page, (if we're using footers in a different context then we'd have to specific what role it is!)

If I remember correctly, the default role of a footer is contentinfo, so the role would be that I think

<Center>
<SimpleGrid columns={[1, 1, 2]}>
<GridItem align="center" m="4">
<Heading size="sm" color="gray.500">
© 2020 White Van, Inc.
</Heading>
<Text fontSize="xs" color="white">
made with ❤ by pizza van
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we internationallize this + the footerLinks?

</Text>
</GridItem>
<GridItem>
<HStack pt={verticalOffset} spacing={spacing}>
{footerLinks.map((link, index) => {
return (
<Heading
key={index}
align="center"
fontSize="sm"
color="blue.600"
>
{link}
</Heading>
);
})}
</HStack>
</GridItem>
</SimpleGrid>
</Center>
</Flex>
);
};
2 changes: 2 additions & 0 deletions frontend/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ a {
}

.container {
overflow-x: hidden;
overflow-y: hidden;
min-height: 100vh;
padding: 0 0.5rem;
display: flex;
Expand Down
9 changes: 7 additions & 2 deletions frontend/testing/components/Footer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { render } from "@testing-library/react";
import { axe, toHaveNoViolations } from "jest-axe";
import React from "react";

import { Footer } from "../../components/Footer";
import { Footer, footerLinks } from "../../components/Footer";
import { setupTests } from "../helpers";

setupTests();

describe("Footer", () => {
expect.extend(toHaveNoViolations);
Expand All @@ -15,6 +18,8 @@ describe("Footer", () => {

it("Basic render functionality", () => {
const { queryByText } = render(<Footer />);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized this a bit late but -- can we use renderWrapped exported from the helpers.tsx file instead of render -- it's because renderWrapped has the appropriate providers wrapped and would give us a better picture on the actual component we're testing!

expect(queryByText("Hello")).toBeInTheDocument();
footerLinks.forEach((link) => {
expect(queryByText(link)).toBeInTheDocument();
});
});
});
21 changes: 21 additions & 0 deletions frontend/testing/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,24 @@ export const wrapInTheme = (component: React.ReactNode): React.ReactNode => {
export const renderWrapped = (component: React.ReactNode): RenderResult => {
return render(wrapInRouter(wrapInTheme(wrapInIntl(wrapInStore(component)))));
};

function defineMatchMedia(): void {
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
media: query,
onchange: null,
addListener: jest.fn(), // Deprecated
removeListener: jest.fn(), // Deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
}

export function setupTests(): void {
defineMatchMedia();
}