mirror of
https://github.com/StanGirard/quivr.git
synced 2024-12-24 20:03:41 +03:00
Responsive navbar (#136)
* feature: responsive navbar * style: nav links hover animatiosn
This commit is contained in:
parent
b2ab0dfa4e
commit
380e264a2e
@ -29,7 +29,7 @@ const DarkModeToggle: FC<DarkModeToggleProps> = ({}) => {
|
||||
return (
|
||||
<Button
|
||||
aria-label="toggle dark mode"
|
||||
className="focus:outline-none"
|
||||
className="focus:outline-none text-3xl"
|
||||
onClick={() => setDark((d) => !d)}
|
||||
variant={"tertiary"}
|
||||
>
|
||||
|
60
frontend/app/components/NavBar/MobileMenu.tsx
Normal file
60
frontend/app/components/NavBar/MobileMenu.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
import { FC, ReactNode, useState } from "react";
|
||||
import * as Dialog from "@radix-ui/react-dialog";
|
||||
import { MdClose, MdMenu } from "react-icons/md";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import Button from "../ui/Button";
|
||||
import NavItems from "./NavItems";
|
||||
|
||||
interface MobileMenuProps {}
|
||||
|
||||
const MobileMenu: FC<MobileMenuProps> = ({}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
return (
|
||||
<Dialog.Root onOpenChange={setOpen}>
|
||||
<Dialog.Trigger asChild>
|
||||
<button className="block sm:hidden" aria-label="open menu">
|
||||
<MdMenu className="text-4xl" />
|
||||
</button>
|
||||
</Dialog.Trigger>
|
||||
<AnimatePresence>
|
||||
{open ? (
|
||||
<Dialog.Portal forceMount>
|
||||
<Dialog.Overlay asChild forceMount>
|
||||
<motion.div
|
||||
className="fixed inset-0 flex overflow-auto cursor-pointer z-50 shadow-xl dark:shadow-primary/25"
|
||||
initial={{ opacity: 1, y: "-100%" }}
|
||||
animate={{ opacity: 1, y: "0%" }}
|
||||
exit={{ opacity: 1, y: "-100%" }}
|
||||
transition={{ duration: 0.4, ease: "circOut" }}
|
||||
>
|
||||
<Dialog.Content asChild forceMount>
|
||||
<div className="flex flex-col items-center justify-between py-24 flex-1 w-full bg-white dark:bg-black border border-black/10 dark:border-white/25 p-10 shadow-xl dark:shadow-primary/50 focus:outline-none cursor-auto z-50">
|
||||
<NavItems className="text-3xl h-fit text-center flex-col items-center justify-center gap-10" />
|
||||
|
||||
<p className="">
|
||||
Get a Second Brain with{" "}
|
||||
<span className="text-primary dark:bg-white rounded-sm">
|
||||
Quivr
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<Dialog.Close asChild>
|
||||
<button
|
||||
className="absolute top-0 p-3 right-0 flex items-center justify-center gap-2 appearance-none rounded-full focus:shadow-sm focus:outline-none"
|
||||
aria-label="close menu"
|
||||
>
|
||||
<MdClose className="text-4xl" />
|
||||
</button>
|
||||
</Dialog.Close>
|
||||
</div>
|
||||
</Dialog.Content>
|
||||
</motion.div>
|
||||
</Dialog.Overlay>
|
||||
</Dialog.Portal>
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
</Dialog.Root>
|
||||
);
|
||||
};
|
||||
|
||||
export default MobileMenu;
|
56
frontend/app/components/NavBar/NavItems.tsx
Normal file
56
frontend/app/components/NavBar/NavItems.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import Link from "next/link";
|
||||
import { FC, HTMLAttributes, ReactNode } from "react";
|
||||
import DarkModeToggle from "./DarkModeToggle";
|
||||
import Button from "../ui/Button";
|
||||
|
||||
interface NavItemsProps extends HTMLAttributes<HTMLUListElement> {}
|
||||
|
||||
const NavItems: FC<NavItemsProps> = ({ className, ...props }) => {
|
||||
return (
|
||||
// <div className={cn("flex flex-1 items-center", className)} {...props}>
|
||||
<ul
|
||||
className={cn(
|
||||
"flex flex-row items-center gap-4 text-sm flex-1",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{process.env.NEXT_PUBLIC_ENV === "local" ? (
|
||||
<>
|
||||
<NavLink to="/upload">Upload</NavLink>
|
||||
<NavLink to="/chat">Chat</NavLink>
|
||||
<NavLink to="/explore">Explore</NavLink>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<NavLink to="https://github.com/StanGirard/quivr">Github</NavLink>
|
||||
<NavLink to="https://discord.gg/HUpRgp2HG8">Discord</NavLink>
|
||||
</>
|
||||
)}
|
||||
<div className="flex sm:flex-1 sm:justify-end flex-col items-center justify-center sm:flex-row gap-5 sm:gap-2">
|
||||
<Link href={"https://try-quivr.streamlit.app"}>
|
||||
<Button variant={"secondary"}>Try Demo</Button>
|
||||
</Link>
|
||||
<DarkModeToggle />
|
||||
</div>
|
||||
</ul>
|
||||
// </div>
|
||||
);
|
||||
};
|
||||
|
||||
interface NavLinkProps {
|
||||
children: ReactNode;
|
||||
to: string;
|
||||
}
|
||||
|
||||
const NavLink: FC<NavLinkProps> = ({ children, to }) => {
|
||||
return (
|
||||
<li className="group relative">
|
||||
<Link href={to}>{children}</Link>
|
||||
<hr className="aboslute top-full border border-transparent border-b-primary dark:border-b-white scale-x-0 group-hover:scale-x-100 group-focus-within:scale-x-100 transition-transform" />
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export default NavItems;
|
@ -6,6 +6,8 @@ import Link from "next/link";
|
||||
import Button from "../ui/Button";
|
||||
import DarkModeToggle from "./DarkModeToggle";
|
||||
import { motion } from "framer-motion";
|
||||
import MobileMenu from "./MobileMenu";
|
||||
import NavItems from "./NavItems";
|
||||
|
||||
interface NavBarProps {}
|
||||
|
||||
@ -34,9 +36,9 @@ const NavBar: FC<NavBarProps> = ({}) => {
|
||||
y: hidden ? "-100%" : "0%",
|
||||
transition: { ease: "circOut" },
|
||||
}}
|
||||
className="fixed top-0 w-full border-b border-b-black/10 dark:border-b-white/25 bg-white dark:bg-black z-50"
|
||||
className="fixed top-0 w-full border-b border-b-black/10 dark:border-b-white/25 bg-white dark:bg-black z-20"
|
||||
>
|
||||
<nav className="max-w-screen-xl mx-auto py-1 flex items-center gap-8">
|
||||
<nav className="max-w-screen-xl mx-auto py-1 flex items-center justify-between gap-8">
|
||||
<Link href={"/"} className="flex items-center gap-4">
|
||||
<Image
|
||||
className="rounded-full"
|
||||
@ -47,35 +49,8 @@ const NavBar: FC<NavBarProps> = ({}) => {
|
||||
/>
|
||||
<h1 className="font-bold">Quivr</h1>
|
||||
</Link>
|
||||
{process.env.NEXT_PUBLIC_ENV === "local" ? (
|
||||
<ul className="flex gap-4 text-sm flex-1">
|
||||
<li>
|
||||
<Link href={"/upload"}>Upload</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={"/chat"}>Chat</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={"/explore"}>Explore</Link>
|
||||
</li>
|
||||
</ul>
|
||||
) : (
|
||||
<ul className="flex gap-4 text-sm flex-1">
|
||||
<li>
|
||||
<Link href={"https://github.com/StanGirard/quivr"}>Github</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={"https://discord.gg/HUpRgp2HG8"}>Discord</Link>
|
||||
</li>
|
||||
</ul>
|
||||
)}
|
||||
|
||||
<div className="flex">
|
||||
<Link href={"https://try-quivr.streamlit.app"}>
|
||||
<Button variant={"secondary"}>Try Demo</Button>
|
||||
</Link>
|
||||
<DarkModeToggle />
|
||||
</div>
|
||||
<NavItems className="hidden sm:flex" />
|
||||
<MobileMenu />
|
||||
</nav>
|
||||
</motion.header>
|
||||
);
|
||||
|
@ -18,7 +18,7 @@ const ButtonVariants = cva(
|
||||
"bg-black disabled:bg-gray-500 disabled:hover:bg-gray-500 text-white dark:bg-white dark:text-black hover:bg-gray-700 dark:hover:bg-gray-200 transition-colors",
|
||||
tertiary: "text-black dark:text-white bg-transparent py-2 px-4",
|
||||
secondary:
|
||||
"border border-black dark:border-white bg-white dark:bg-black text-black dark:text-white focus:bg-black dark:focus:bg-white hover:bg-black dark:hover:bg-white hover:text-white dark:hover:text-black focus:text-white transition-colors py-2 px-4 shadow-none",
|
||||
"border border-black dark:border-white bg-white dark:bg-black text-black dark:text-white focus:bg-black dark:focus:bg-white hover:bg-black dark:hover:bg-white hover:text-white dark:hover:text-black focus:text-white dark:focus:text-black transition-colors py-2 px-4 shadow-none",
|
||||
danger:
|
||||
"border border-red-500 hover:bg-red-500 hover:text-white transition-colors",
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user