New front page design

This commit is contained in:
Timothy Armes
2024-03-01 09:20:14 +01:00
parent 1c271cda05
commit cc0ae71c26
36 changed files with 224 additions and 52 deletions
@@ -0,0 +1,49 @@
"use client";
import { useTranslations } from "next-intl";
import { FaGithub, FaRegEnvelope } from "react-icons/fa";
import { Link, usePathname } from "@/utils/navigation";
import { useSetAtom } from "jotai";
import { burgerMenuIsOpenAtom } from "@/atoms";
import ThemeSwitcher from "./ThemeSwitcher";
export default function Footer() {
const t = useTranslations("Footer");
const setBurgerMenuIsOpen = useSetAtom(burgerMenuIsOpenAtom);
const pathname = usePathname();
return (
<footer
className="fixed bottom-0 z-30 flex h-12 w-[100vw] flex-col items-center justify-center justify-items-center bg-primary-600 px-5 py-2 text-white dark:bg-gray-700"
data-test="footer"
>
<div className="flex items-center py-2 hover:[&_a]:opacity-80" onClick={() => setBurgerMenuIsOpen(false)}>
<a
href="https://github.com/TheRealOwenRees/echecsfrance"
target="_blank"
aria-label={t("githubAria")}
className="mr-4"
>
<FaGithub />
</a>
<Link href="/contact-us" aria-label={t("contactAria")} className="mr-4">
<FaRegEnvelope />
</Link>
<div className="mr-4 space-x-2 text-xs">
<Link href={pathname} locale="fr">
FR
</Link>
<span>|</span>
<Link href={pathname} locale="en">
EN
</Link>
</div>
<div className="text-xs hover:opacity-80">
<ThemeSwitcher />
</div>
</div>
</footer>
);
}
@@ -0,0 +1,46 @@
"use client";
import { useAtom } from "jotai";
import { twMerge } from "tailwind-merge";
import { burgerMenuIsOpenAtom } from "@/atoms";
import HamburgerMenu from "./HamburgerMenu";
const Hamburger = () => {
const [burgerMenuIsOpen, setBurgerMenuIsOpen] = useAtom(burgerMenuIsOpenAtom);
return (
<>
<div
className="hamburger-button relative z-[99999] space-y-2"
data-test="hamburger-button"
onClick={() => setBurgerMenuIsOpen(!burgerMenuIsOpen)}
>
<div
className={twMerge(
"h-0.5 w-8 bg-gray-600 transition-all duration-300 ease-in-out dark:bg-white",
burgerMenuIsOpen &&
"translate-x-[1px] translate-y-2.5 rotate-45 bg-white",
)}
></div>
<div
className={twMerge(
"h-0.5 w-8 bg-gray-600 transition-transform duration-300 ease-linear dark:bg-white",
burgerMenuIsOpen && "scale-0 bg-white opacity-0",
)}
></div>
<div
className={twMerge(
"h-0.5 w-8 bg-gray-600 transition-transform duration-300 ease-in-out dark:bg-white",
burgerMenuIsOpen && "-translate-y-2.5 -rotate-45 bg-white",
)}
></div>
</div>
<HamburgerMenu />
</>
);
};
export default Hamburger;
@@ -0,0 +1,57 @@
import { useAtom } from "jotai";
import { useTranslations } from "next-intl";
import { twMerge } from "tailwind-merge";
import { burgerMenuIsOpenAtom } from "@/atoms";
import { Link } from "@/utils/navigation";
const HamburgerMenu = () => {
const t = useTranslations("Nav");
const [burgerMenuIsOpen, setBurgerMenuIsOpen] = useAtom(burgerMenuIsOpenAtom);
const closeMenu = () => setBurgerMenuIsOpen(false);
return (
<div
className={twMerge(
"fixed right-0 top-0 z-[9999] h-[calc(100svh-3rem)] w-full",
"flex items-center justify-center bg-primary-600 transition-transform duration-200 ease-linear dark:bg-gray-600 md:hidden",
!burgerMenuIsOpen && "translate-x-full",
)}
>
<ul className="list-reset text-white">
<li className="py-5 text-center text-xl">
<Link
onClick={closeMenu}
href="/tournaments"
className="border-b-2 border-transparent transition-all duration-300 ease-in-out hover:border-white"
>
{t("tournaments")}
</Link>
</li>
<li className="py-5 text-center text-xl">
<Link
onClick={closeMenu}
href="/clubs"
className="border-b-2 border-transparent transition-all duration-300 ease-in-out hover:border-white"
>
{t("clubs")}
</Link>
</li>
<li className="py-5 text-center text-xl">
<Link
onClick={closeMenu}
href="/elo"
className="border-b-2 border-transparent transition-all duration-300 ease-in-out hover:border-white"
>
{t("elo")}
</Link>
</li>
</ul>
</div>
);
};
export default HamburgerMenu;
@@ -0,0 +1,55 @@
import { useTranslations } from "next-intl";
import { Link } from "@/utils/navigation";
import Hamburger from "./Hamburger";
export default function Navbar() {
const t = useTranslations("Nav");
const links = [
{ title: t("tournaments"), route: "/tournaments" },
{ title: t("clubs"), route: "/clubs" },
{ title: t("elo"), route: "/elo" },
] as const;
return (
<nav
className="relative mt-0 h-16 w-full overflow-x-clip border-b-[1px] bg-white px-5 dark:border-gray-700 dark:bg-gray-800"
data-test="navbar"
>
<div className="container mx-auto flex h-full items-center justify-between">
<Link
className="font-extrabold text-gray-900 no-underline hover:no-underline dark:text-white"
href="/"
>
<span className="font-title text-2xl text-gray-800 dark:text-white">
{t("title")}
</span>
</Link>
<div className="md:hidden" data-test="mobile-menu">
<Hamburger />
</div>
<div
className="hidden h-full justify-center md:flex md:w-1/2 md:justify-end"
data-test="desktop-menu"
>
<ul className="list-reset flex h-full flex-1 items-center gap-14 text-gray-900 no-underline dark:text-white md:flex-none">
{links.map(({ title, route }) => (
<li key={route} className="h-full">
<Link
className="inline-flex h-full items-center border-b-4 border-t-4 border-transparent transition-all duration-300 ease-in-out hover:border-b-primary-600"
href={route}
>
{title}
</Link>
</li>
))}
</ul>
</div>
</div>
</nav>
);
}
@@ -0,0 +1,48 @@
"use client";
import { useEffect, useState } from "react";
import useDarkMode from "@/hooks/useDarkMode";
const ThemeSwitcher = () => {
const [mounted, setMounted] = useState(false);
const [colorTheme, setTheme] = useDarkMode();
useEffect(() => setMounted(true), []);
if (!mounted) return null;
return (
<div className="cursor-pointer">
{colorTheme === "light" ? (
<div data-test="toggle-dark" onClick={() => setTheme("light")}>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="inline-block h-4 w-4"
>
<path
fillRule="evenodd"
d="M9.528 1.718a.75.75 0 01.162.819A8.97 8.97 0 009 6a9 9 0 009 9 8.97 8.97 0 003.463-.69.75.75 0 01.981.98 10.503 10.503 0 01-9.694 6.46c-5.799 0-10.5-4.701-10.5-10.5 0-4.368 2.667-8.112 6.46-9.694a.75.75 0 01.818.162z"
clipRule="evenodd"
/>
</svg>
</div>
) : (
<div data-test="toggle" onClick={() => setTheme("dark")}>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
className="inline-block h-4 w-4"
>
<path d="M12 2.25a.75.75 0 01.75.75v2.25a.75.75 0 01-1.5 0V3a.75.75 0 01.75-.75zM7.5 12a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM18.894 6.166a.75.75 0 00-1.06-1.06l-1.591 1.59a.75.75 0 101.06 1.061l1.591-1.59zM21.75 12a.75.75 0 01-.75.75h-2.25a.75.75 0 010-1.5H21a.75.75 0 01.75.75zM17.834 18.894a.75.75 0 001.06-1.06l-1.59-1.591a.75.75 0 10-1.061 1.06l1.59 1.591zM12 18a.75.75 0 01.75.75V21a.75.75 0 01-1.5 0v-2.25A.75.75 0 0112 18zM7.758 17.303a.75.75 0 00-1.061-1.06l-1.591 1.59a.75.75 0 001.06 1.061l1.591-1.59zM6 12a.75.75 0 01-.75.75H3a.75.75 0 010-1.5h2.25A.75.75 0 016 12zM6.697 7.757a.75.75 0 001.06-1.06l-1.59-1.591a.75.75 0 00-1.061 1.06l1.59 1.591z" />
</svg>
</div>
)}
</div>
);
};
export default ThemeSwitcher;