Skip to content
Merged
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
24 changes: 19 additions & 5 deletions js/src/components/ui/footer/Footer.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,36 @@

.footerContents {
max-width: 1200px;
min-height: 150px;
margin: 0 auto;
padding: var(--mantine-spacing-xs) var(--mantine-spacing-xl);
display: grid;
grid-template-columns: 1fr auto 1fr;
grid-template-columns: 1fr 1fr;
width: 100%;
background-color: var(--mantine-color-dark-6);
align-items: center;

@mixin smaller-than $mantine-breakpoint-md {
padding: var(--mantine-spacing-xs) var(--mantine-spacing-xl);
@mixin smaller-than $mantine-breakpoint-sm {
display: flex;
flex-direction: column;
padding: var(--mantine-spacing-lg);
}
}

.footerRight {
display: flex;
justify-content: flex-end;
gap: calc(var(--spacing) * 20);

@mixin smaller-than $mantine-breakpoint-sm {
flex-direction: column;
gap: calc(var(--spacing) * 2);
}
}

.footerLeft {
display: flex;
align-items: center;
gap: 12px;
flex-direction: column;
}

.logo {
Expand Down
40 changes: 40 additions & 0 deletions js/src/components/ui/footer/Footer.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Footer } from "@/components/ui/footer/Footer";
import { TestUtils, TestUtilTypes } from "@/lib/test";
import { screen } from "@testing-library/react";

describe("Footer rendered successfully", () => {
let renderProviderFn: TestUtilTypes.RenderWithAllProvidersFn | null = null;
beforeEach(() => {
renderProviderFn = TestUtils.getRenderWithAllProvidersFn();
});

it("should render mission text", () => {
renderProviderFn?.(<Footer />);
const elements = screen.getAllByText(
"LeetCode motivation site for Patina Network",
);
expect(elements).toHaveLength(2);
for (const element of elements) {
expect(element).toBeInTheDocument();
expect(element).toBeVisible();
}
});

it("should render links section", () => {
renderProviderFn?.(<Footer />);
const element = screen.getByTestId("footer-links-section");
expect(element).toBeInTheDocument();
expect(element).toBeVisible();
});

it("should have correct github link", () => {
renderProviderFn?.(<Footer />);
const element = screen.getByLabelText("CodeBloom GitHub");
expect(element).toBeInTheDocument();
expect(element).toBeVisible();
expect(element).toHaveAttribute(
"href",
"https://github.com/tahminator/codebloom",
);
});
});
139 changes: 88 additions & 51 deletions js/src/components/ui/footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { GotoAdminPageButton } from "@/components/ui/admin-button/AdminButton";
import styles from "@/components/ui/footer/Footer.module.css";
import { ActionIcon, Text, Anchor } from "@mantine/core";
import { Text, Anchor, Flex, Box, Stack } from "@mantine/core";
import { motion, useScroll, useTransform } from "motion/react";
import { ReactNode, useRef } from "react";
import { FaInstagram, FaLinkedin, FaGithub } from "react-icons/fa";
import { FaInstagram, FaDiscord, FaGithub } from "react-icons/fa";

import Logo from "/logo.png";

Expand All @@ -13,57 +13,95 @@ export function Footer() {
target: containerRef,
offset: ["start end", "end end"],
});
const missionText = "LeetCode motivation site for Patina Network";

const y = useTransform(scrollYProgress, [0, 1], ["-100%", "0%"]);

return (
<div ref={containerRef} className={styles.footerWrapper}>
<Box ref={containerRef} className={styles.footerWrapper}>
<motion.div className={styles.footer} style={{ y }}>
<div className={styles.footerContents}>
<div className={styles.footerLeft}>
<img src={Logo} width={45} alt="Logo" />
<Box className={styles.footerContents}>
<Box
visibleFrom={"sm"}
data-testid={"footer-logo-mission-desktop"}
className={styles.footerLeft}
>
<Flex align={"center"}>
<img src={Logo} width={45} alt={"Logo"} />
<Text fw={550} size={"md"}>
Codebloom
</Text>
</Flex>
<Flex>
<Text pl={"xs"} c={"dimmed"} size={"sm"}>
{missionText}
</Text>
</Flex>
<GotoAdminPageButton />
</div>
<Text px={30} fs="italic" visibleFrom={"sm"}>
CodeBloom is a LeetCode motivation site for Patina Network members.
</Text>
<div className={styles.footerLinks}>
<FooterIconLink
href={"https://www.linkedin.com/company/patinanetwork"}
ariaLabel={"Patina Network LinkedIn"}
>
<FaLinkedin size={24} />
</FooterIconLink>
<FooterIconLink
href={"https://www.instagram.com/patinanetwork"}
ariaLabel={"Patina Network Instagram"}
>
<FaInstagram size={24} />
</FooterIconLink>
<FooterIconLink
href={"https://github.com/tahminator/codebloom"}
ariaLabel={"CodeBloom GitHub"}
>
<FaGithub size={24} />
</FooterIconLink>
<Anchor
href="/privacy"
c="dimmed"
size="sm"
variant="subtle"
underline="always"
pb={"sm"}
>
Privacy Policy
</Anchor>
</div>
</div>
</Box>
<Box className={styles.footerRight}>
<Box hiddenFrom={"sm"} data-testid={"footer-logo-mission-mobile"}>
<Flex align={"center"}>
<img src={Logo} width={45} alt={"Logo"} />
<Text fw={550} size={"md"}>
Codebloom
</Text>
</Flex>
<Flex>
<Text c={"dimmed"} size={"sm"}>
{missionText}
</Text>
</Flex>
<GotoAdminPageButton />
</Box>
<Box data-testid={"footer-links-section"}>
<Stack gap={4}>
<Text fw={550}>About</Text>
<AnchorLink href={"/privacy"} ariaLabel={"Privacy Policy"}>
Privacy Policy
</AnchorLink>
<AnchorLink
href={"https://github.com/tahminator/codebloom"}
ariaLabel={"CodeBloom GitHub"}
>
<Flex align={"center"} gap={"xs"}>
<Text>View GitHub</Text>
<FaGithub size={16} color={"white"} />
</Flex>
</AnchorLink>
</Stack>
</Box>
<Box>
<Stack gap={4}>
<Text fw={550}>Community</Text>
<AnchorLink
href={"https://www.instagram.com/patinanetwork"}
ariaLabel={"Patina Network Instagram"}
>
<Flex align={"center"} gap={"xs"}>
<Text>Follow on Instagram</Text>
<FaInstagram size={16} color={"white"} />
</Flex>
</AnchorLink>
<AnchorLink
href={"https://discord.com/invite/jKaPfHtcaD"}
ariaLabel={"Patina Network Discord"}
>
<Flex align={"center"} gap={"xs"}>
<Text>Join our Discord</Text>
<FaDiscord size={16} color={"white"} />
</Flex>
</AnchorLink>
</Stack>
</Box>
</Box>
</Box>
</motion.div>
</div>
</Box>
);
}

function FooterIconLink({
function AnchorLink({
href,
children,
ariaLabel,
Expand All @@ -73,17 +111,16 @@ function FooterIconLink({
ariaLabel: string;
}) {
return (
<ActionIcon
component="a"
<Anchor
href={href}
target="_blank"
color={"dark.0"}
variant="transparent"
size="lg"
c={"dimmed"}
size={"sm"}
variant={"subtle"}
target={"_blank"}
aria-label={ariaLabel}
mt={-7}
rel={"noopener noreferrer"}
>
{children}
</ActionIcon>
</Anchor>
);
}
Loading