Add mobile nav

This commit is contained in:
Kalle (Sendou)
2021-10-31 13:43:57 +02:00
parent bc1742b123
commit c161f3dead
7 changed files with 307 additions and 34 deletions

View File

@@ -12,10 +12,10 @@ const S_Container = styled("div", {
position: "relative",
userSelect: "none",
overflow: "hidden",
width: "38px",
minWidth: "38px",
height: "38px",
borderRadius: "16px",
width: "var(--item-size)",
minWidth: "var(--item-size)",
height: "var(--item-size)",
borderRadius: "$rounded",
});
const S_Avatar = styled("img", {

View File

@@ -0,0 +1,121 @@
import { styled } from "stitches.config";
export function HamburgerButton({
isExpanded,
onClick,
}: {
onClick: () => void;
isExpanded: boolean;
}) {
return (
<S_TransformingBurger
aria-label="Toggle menu visibility"
aria-expanded={isExpanded ? "true" : "false"}
onClick={onClick}
>
<svg
width="32"
height="32"
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<S_TopLine
x="6"
y="9"
width="20"
height="2"
rx="1"
fill="currentColor"
type={isExpanded ? "expanded" : undefined}
/>
<S_MiddleLine
x="6"
y="15"
width="20"
height="2"
rx="1"
fill="currentColor"
type={isExpanded ? "expanded" : undefined}
/>
<S_BottomLine
x="6"
y="21"
width="20"
height="2"
rx="1"
fill="currentColor"
type={isExpanded ? "expanded" : undefined}
/>
</svg>
</S_TransformingBurger>
);
}
const S_TransformingBurger = styled("button", {
display: "flex",
width: "var(--item-size)",
height: "var(--item-size)",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
padding: "$1",
border: "3px solid",
borderColor: "$bgLighter",
backgroundColor: "transparent",
borderRadius: "$rounded",
color: "inherit",
cursor: "pointer",
gap: "2px",
"@sm": {
display: "none",
},
});
const S_TopLine = styled("rect", {
transform: "none",
transformOrigin: "16px 10px",
transitionDuration: "150ms",
transitionProperty: "transform",
transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
variants: {
type: {
expanded: {
transform: "translateY(7px) rotate(45deg)",
},
},
},
});
const S_MiddleLine = styled("rect", {
opacity: 1,
transitionDuration: "150ms",
transitionProperty: "opacity",
transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
variants: {
type: {
expanded: {
opacity: 0,
},
},
},
});
const S_BottomLine = styled("rect", {
transform: "none",
transformOrigin: "16px 22px",
transitionDuration: "150ms",
transitionProperty: "transform",
transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
variants: {
type: {
expanded: {
transform: "translateY(-5px) rotate(-45deg)",
},
},
},
});

View File

@@ -1,41 +1,36 @@
import { ReactNode } from "react";
import { ReactNode, useState } from "react";
import NextImage from "next/image";
import logo from "../assets/img/logo.png";
import { Avatar } from "./common/Avatar";
import NextLink from "next/link";
import logo from "assets/img/logo.png";
import { Avatar } from "components/common/Avatar";
import { styled } from "stitches.config";
import { SearchInput } from "./common/SearchInput";
const navItems = [
{
title: "builds",
items: ["browse", "gear", "analyzer"],
},
{
title: "play",
items: ["calendar", "battle", "Rankings"],
},
{
title: "tools",
items: ["planner", "rotations", "top 500"],
},
{
title: "misc",
items: ["badges", "links"],
},
];
import { SearchInput } from "components/common/SearchInput";
import { HamburgerButton } from "./HamburgerButton";
import { navItems } from "utils/constants";
import { MobileNav } from "./MobileNav";
export function Layout({ children }: { children: ReactNode }) {
const [menuExpanded, setMenuExpanded] = useState(false);
return (
<>
<S_Header>
<S_LogoContainer>
<NextImage src={logo} width={30} height={30} />
</S_LogoContainer>
<SearchInput />
<NextLink href="/">
<S_LogoContainer>
<NextImage src={logo} />
</S_LogoContainer>
</NextLink>
<S_SearchContainer>
<SearchInput />
</S_SearchContainer>
<S_RightContainer>
<HamburgerButton
isExpanded={menuExpanded}
onClick={() => setMenuExpanded((expanded) => !expanded)}
/>
<Avatar src="https://cdn.discordapp.com/avatars/79237403620945920/fcfd65a3bea598905abb9ca25296816b.png?size=80" />
</S_RightContainer>
</S_Header>
<MobileNav isExpanded={menuExpanded} />
<S_Nav>
<S_NavItems>
{navItems.map((navItem) => (
@@ -59,10 +54,19 @@ export function Layout({ children }: { children: ReactNode }) {
}
const S_Header = styled("header", {
position: "relative",
display: "grid",
gridTemplateColumns: "repeat(3, 1fr)",
gridTemplateColumns: "repeat(2, 1fr)",
alignItems: "center",
padding: "$4",
"--item-size": "3rem",
zIndex: 10,
backgroundColor: "$bg",
"@sm": {
gridTemplateColumns: "repeat(3, 1fr)",
"--item-size": "38px",
},
});
const S_LogoContainer = styled("div", {
@@ -73,6 +77,18 @@ const S_LogoContainer = styled("div", {
padding: "$1",
borderRadius: "$rounded",
justifySelf: "flex-start",
cursor: "pointer",
width: "var(--item-size)",
minWidth: "var(--item-size)",
height: "var(--item-size)",
});
const S_SearchContainer = styled("div", {
display: "none",
"@sm": {
display: "block",
},
});
const S_RightContainer = styled("div", {
@@ -82,10 +98,14 @@ const S_RightContainer = styled("div", {
});
const S_Nav = styled("nav", {
display: "flex",
display: "none",
justifyContent: "center",
backgroundColor: "$bgLighter",
backgroundImage: `url(/svg/background-pattern.svg)`,
"@sm": {
display: "flex",
},
});
const S_NavItems = styled("div", {

View File

@@ -0,0 +1,113 @@
import { SearchInput } from "components/common/SearchInput";
import { styled } from "stitches.config";
import { navItems } from "utils/constants";
import NextLink from "next/link";
import { Fragment } from "react";
export function MobileNav({ isExpanded }: { isExpanded: boolean }) {
return (
<S_Container
aria-hidden={isExpanded ? "false" : "true"}
type={isExpanded ? "expanded" : undefined}
>
<S_TopAction>
<SearchInput />
</S_TopAction>
<S_LinksContainer>
{navItems.map((navItem) => {
return (
<Fragment key={navItem.title}>
<S_GroupTitle>{navItem.title}</S_GroupTitle>
{navItem.items.map((item) => {
return (
<NextLink key={item} href="/">
<S_NavLink>
<S_NavLinkImage
src={`/img/nav-icons/${item.replace(" ", "")}.png`}
/>
<div>{item}</div>
</S_NavLink>
</NextLink>
);
})}
</Fragment>
);
})}
</S_LinksContainer>
</S_Container>
);
}
const S_Container = styled("nav", {
position: "absolute",
bottom: "100vh",
width: "100%",
height: "100%",
transition: "bottom 0.5s",
transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
backgroundImage: `url(/svg/background-pattern.svg)`,
backgroundColor: "$bgLighter",
zIndex: 5,
overflowY: "auto",
paddingBottom: "$6",
"@sm": {
display: "none",
},
variants: {
type: {
expanded: {
bottom: "0",
},
},
},
});
const S_TopAction = styled("div", {
display: "grid",
gap: "$4",
placeItems: "center",
backgroundColor: "$bg",
paddingTop: "$24",
paddingBottom: "$8",
});
const S_LinksContainer = styled("div", {
display: "grid",
justifyContent: "center",
gridAutoColumns: "1fr",
gridAutoRows: "4rem",
paddingX: "$24",
});
const S_NavLinkImage = styled("img", {
width: "2.5rem",
marginRight: "$3",
});
const S_GroupTitle = styled("div", {
textTransform: "uppercase",
alignSelf: "flex-end",
justifySelf: "center",
paddingX: "$3",
paddingY: "$2",
marginBottom: "$1",
backgroundColor: "$bg",
fontWeight: "$bold",
});
const S_NavLink = styled("div", {
display: "flex",
alignItems: "center",
textTransform: "capitalize",
borderTop: "3px solid $bgLighter",
fontWeight: "$bold",
backgroundColor: "$bg",
paddingX: "$2",
fontSize: "$sm",
"&:last-child": {
borderBottom: "3px solid $bgLighter",
},
});

View File

@@ -4,7 +4,7 @@ import "./_app.css";
import { AppProps } from "next/app";
import Head from "next/head";
import { SWRConfig } from "swr";
import { Layout } from "../components/layout";
import { Layout } from "components/layout/Layout";
import { globalCss } from "stitches.config";
const globalStyles = globalCss({

View File

@@ -41,6 +41,7 @@ export const {
"0.5": "0.125rem",
"1": "0.25rem",
"2": "0.5rem",
// TODO: fix vars with . "invalid property"
"2.5": "0.625rem",
"3": "0.75rem",
"3.5": "0.875rem",

View File

@@ -0,0 +1,18 @@
export const navItems = [
{
title: "builds",
items: ["browse", "gear", "analyzer"],
},
{
title: "play",
items: ["calendar", "battle", "Rankings"],
},
{
title: "tools",
items: ["planner", "rotations", "top 500"],
},
{
title: "misc",
items: ["badges", "links"],
},
];