Skip to content

Commit

Permalink
added drawer components and window width hook
Browse files Browse the repository at this point in the history
  • Loading branch information
aasmal97 committed Oct 13, 2023
1 parent 62d6f4b commit dc1f423
Show file tree
Hide file tree
Showing 6 changed files with 304 additions and 11 deletions.
24 changes: 24 additions & 0 deletions studyAi/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions studyAi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/react-fontawesome": "^0.2.0",
"@mui/material": "^5.14.12",
"lodash": "^4.17.21",
"next": "13.5.4",
"react": "18",
"react-dom": "18"
},
"devDependencies": {
"@types/lodash": "^4.14.199",
"@types/node": "20",
"@types/react": "18",
"@types/react-dom": "18",
Expand Down
181 changes: 181 additions & 0 deletions studyAi/src/app/util/components/navigation/client/drawer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
'use client'
import { Transition } from "react-transition-group";
import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import useElementSize from "@/app/util/hooks/useElementSize";

const Drawer = ({
children,
id,
className,
onClose,
open,
anchor,
animationTime = 225,
}: {
className?: string;
children: JSX.Element | JSX.Element[] | React.ReactNode;
id?: string;
anchor: "left" | "right";
open: boolean;
onClose: (e: React.MouseEvent) => void;
animationTime?: number;
}) => {
const { setRef, position: size } = useElementSize();
const nodeRef = useRef(null);
const [scrollbarWidth, setScrollbarWidth] = useState(0);
const overallContainerStyles: React.CSSProperties = {
position: "fixed",
top: "0",
left: "0",
width: "100%",
height: "100%",
zIndex: "9999",
};
const overallTransitionStyles: {
[key: string]: React.CSSProperties;
} = {
entering: { visibility: "visible", opacity: 1 },
entered: { visibility: "visible", opacity: 1 },
exiting: { visibility: "visible", opacity: 1 },
exited: { visibility: "hidden", opacity: 0 },
};
const buttonContainerStyles: React.CSSProperties = {
position: "absolute",
cursor: "pointer",
width: "100%",
height: "100%",
border: "none",
top: "0",
right: "0",
zIndex: "1",
backgroundColor: "rgba(0,0,0,0.5)",
transition: `opacity ${animationTime}ms cubic- bezier(0.4, 0, 0.2, 1) 0ms`,
};
const buttonContainerTransitionStyles: {
[key: string]: React.CSSProperties;
} = {
entering: { opacity: 1 },
entered: { opacity: 1 },
exiting: { opacity: 0 },
exited: { opacity: 0 },
};
const innerDrawerContainerStyles: React.CSSProperties = {
position: "absolute",
top: "0",
left: anchor === "left" ? "0" : "",
right: anchor === "left" ? "" : "0",
zIndex: "2",
height: "100%",
display: "flex",
flexDirection: "column",
transition: `transform ${animationTime}ms cubic-bezier(0, 0, 0.2, 1) 0ms`,
};
const innerTransitionStyles: {
[key: string]: React.CSSProperties;
} = {
entering: {
// transform: "translateX(0)"
},
entered: { transform: "translateX(0)" },
exiting: {
transform: `translateX(${anchor === "right" ? "" : "-"}${size.width}px)`,
},
exited: {
transform: `translateX(${anchor === "right" ? "" : "-"}${size.width}px)`,
},
};
useEffect(() => {
function getScrollbarWidth() {
// Creating invisible container
const outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.overflow = "scroll"; // forcing scrollbar to appear
document.body.appendChild(outer);
// Creating inner element and placing it in the container
const inner = document.createElement("div");
outer.appendChild(inner);
// Calculating difference between container's full width and the child width
const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
// Removing temporary elements from the DOM
outer?.parentNode?.removeChild(outer);
return scrollbarWidth;
}
setScrollbarWidth(getScrollbarWidth());
return () => {
document.body.style.overflow = "";
document.body.style.paddingRight = "";
document.body.style.overflowX = "";
};
}, []);
useEffect(() => {
let timeout: NodeJS.Timeout | undefined;
if (open) {
document.body.style.paddingRight = scrollbarWidth.toString() + "px";
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "";
document.body.style.paddingRight = "";
document.body.style.overflowX = "hidden";
timeout = setTimeout(() => {
document.body.style.overflowX = "";
}, animationTime);
}
return () => {
if (timeout) clearTimeout(timeout);
};
}, [open, scrollbarWidth, animationTime]);
return createPortal(
<Transition
nodeRef={nodeRef}
in={open}
timeout={animationTime}
// mountOnEnter
// unmountOnExit
>
{(state) => (
<div
ref={nodeRef}
id={id}
className={`drawer-container MuiPaper-root ${
className ? className : ""
}`}
style={{
...overallContainerStyles,
...overallTransitionStyles[state],
}}
>
<div
style={{
width: "100%",
height: "100%",
position: "relative",
}}
>
<button
style={{
...buttonContainerStyles,
...buttonContainerTransitionStyles[state],
}}
onClick={onClose}
aria-label="close-drawer"
></button>
<div
ref={setRef}
style={{
...innerDrawerContainerStyles,
...innerTransitionStyles[state],
}}
className="drawer-content MuiPaper-root"
>
{children}
</div>
</div>
{children}
</div>
)}
</Transition>,
document.body
);
};
export default Drawer;
81 changes: 73 additions & 8 deletions studyAi/src/app/util/components/navigation/client/navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
"use client";
import React, { useState } from "react";
import { MenuItem, Menu, Link } from "@mui/material";
import React from "react";
import { MenuItem, Menu, Link, Button } from "@mui/material";
import NextLink from "next/link";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCaretDown } from "@fortawesome/free-solid-svg-icons";
import { faCaretDown, faBars, faClose } from "@fortawesome/free-solid-svg-icons";
import useRemToPixel from "@/app/util/hooks/useRemToPixel";
import useElementPosition from "@/app/util/hooks/useElementSize";
import { faWandMagicSparkles } from "@fortawesome/free-solid-svg-icons/faWandMagicSparkles";
import { faFileLines } from "@fortawesome/free-regular-svg-icons";
import useDropdown from "@/app/util/hooks/useDropdown";
import useWindowWidth from "@/app/util/hooks/useWindowWidth";
import dynamic from "next/dynamic";
const Drawer = dynamic(() => import("../client/drawer"), { ssr: false });
const links = [
{
href: "/about",
Expand Down Expand Up @@ -38,7 +41,7 @@ const menuItemLinks = [
export const GenerateDropdown = () => {
const currRemToPixelVal = useRemToPixel("1rem");
const { setRef, position: dropdownButtonPos } = useElementPosition();
const {anchorEl, handleClick, handleClose} = useDropdown()
const { anchorEl, handleClick, handleClose } = useDropdown();
return (
<div className="relative flex items-center m-0 p-0">
<Link
Expand Down Expand Up @@ -109,7 +112,69 @@ export const NavButtons = () => {
</>
);
};

export const NavbarDrawer = () => {
return<></>
}
export const NavDrawer = ({ children }: { children: React.ReactNode }) => {
const [open, setOpen] = React.useState(false);
const toggleDrawer =
(open: boolean) => (event: React.KeyboardEvent | React.MouseEvent) => {
if (
event.type === "keydown" &&
((event as React.KeyboardEvent).key === "Tab" ||
(event as React.KeyboardEvent).key === "Shift")
) {
return;
}
setOpen(open);
};
return (
<>
<Button
variant="text"
aria-label="open-drawer"
onClick={toggleDrawer(true)}
>
<FontAwesomeIcon icon={faBars} />
</Button>
<Drawer
anchor="right"
open={open}
onClose={(e) => toggleDrawer(false)(e)}
>
<Button
variant="text"
aria-label="close-drawer"
className="absolute top-0 right-0"
onClick={toggleDrawer(false)}
>
<FontAwesomeIcon icon={faClose} />
</Button>
{/* <Button
variant="text"
aria-label="close-drawer"
onClick={toggleDrawer(false)}
className=""
>
<FontAwesomeIcon icon={faBars} />
</Button> */}
{children}
</Drawer>
</>
);
};
export const NavbarLinks = ({
children,
}: {
children: React.JSX.Element[];
}) => {
const windowWidth = useWindowWidth();
const reversedChildren = React.Children.map(
children,
(child) => child
).reverse();
const innerContainer = (
<div className="flex-col xs:flex-row flex w-full h-full items-center">
{windowWidth < 480 ? reversedChildren : children}
</div>
);
if (windowWidth > 480) return innerContainer;
return <NavDrawer>{innerContainer}</NavDrawer>;
};
8 changes: 5 additions & 3 deletions studyAi/src/app/util/components/navigation/server/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import AppBar from "@mui/material/AppBar";
import Typography from "@mui/material/Typography";
import SVGLogo from "../../../icons/logo";
import Link from "next/link";
import { NavButtons } from "../client/navbar";
import { NavButtons, NavbarLinks } from "../client/navbar";
import AuthenticationNav from "../client/authentication";

const appName = "Study AI";
Expand Down Expand Up @@ -31,8 +31,10 @@ const Navbar = () => {
>
<div className="flex items-center justify-start flex-row h-full w-full max-w-screen-xl mx-auto">
<Logo showLabel={false} />
<NavButtons />
<AuthenticationNav />
<NavbarLinks>
<NavButtons />
<AuthenticationNav />
</NavbarLinks>
</div>
</AppBar>
);
Expand Down
Loading

0 comments on commit dc1f423

Please sign in to comment.