diff --git a/client/package.json b/client/package.json
index 2af36d5..0732496 100644
--- a/client/package.json
+++ b/client/package.json
@@ -9,6 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
+ "@headlessui/react": "^1.7.2",
"@heroicons/react": "^2.0.11",
"clsx": "^1.2.1",
"react": "^18.2.0",
diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml
index afa2c81..237de88 100644
--- a/client/pnpm-lock.yaml
+++ b/client/pnpm-lock.yaml
@@ -1,6 +1,7 @@
lockfileVersion: 5.4
specifiers:
+ '@headlessui/react': ^1.7.2
'@heroicons/react': ^2.0.11
'@types/react': ^18.0.17
'@types/react-dom': ^18.0.6
@@ -18,6 +19,7 @@ specifiers:
vite: ^3.1.0
dependencies:
+ '@headlessui/react': 1.7.2_biqbaboplfbrettd7655fr4n2y
'@heroicons/react': 2.0.11_react@18.2.0
clsx: 1.2.1
react: 18.2.0
@@ -323,6 +325,17 @@ packages:
dev: true
optional: true
+ /@headlessui/react/1.7.2_biqbaboplfbrettd7655fr4n2y:
+ resolution: {integrity: sha512-snLv2lxwsf2HNTOBNgHYdvoYZ3ChJE8QszPi1d/hl9js8KrFrUulTaQBfSyPbJP5BybVreWh9DxCgz9S0Z6hKQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ react: ^16 || ^17 || ^18
+ react-dom: ^16 || ^17 || ^18
+ dependencies:
+ react: 18.2.0
+ react-dom: 18.2.0_react@18.2.0
+ dev: false
+
/@heroicons/react/2.0.11_react@18.2.0:
resolution: {integrity: sha512-bASjOgSSaYj8HqXWsOqaBiB6ZLalE/g90WYGgZ5lPm4KCCG7wPXntY4kzHf5NrLh6UBAcnPwvbiw1Ne9GYfJtw==}
peerDependencies:
diff --git a/client/src/assets/images/logo.png b/client/src/assets/images/logo.png
new file mode 100644
index 0000000..9332bcb
Binary files /dev/null and b/client/src/assets/images/logo.png differ
diff --git a/client/src/components/FormField.tsx b/client/src/components/FormField.tsx
new file mode 100644
index 0000000..8cb3671
--- /dev/null
+++ b/client/src/components/FormField.tsx
@@ -0,0 +1,22 @@
+import { ReactNode } from "react";
+import Input from "./Input";
+
+interface FormFieldProps extends React.ComponentPropsWithoutRef<"input"> {
+ label: string;
+ bottomElement?: ReactNode;
+}
+
+const FormField = ({ label, bottomElement, ...inputProps }: FormFieldProps) => {
+ return (
+
+
+
+
+ {bottomElement}
+
+ );
+};
+
+export default FormField;
diff --git a/client/src/components/InlineLink.tsx b/client/src/components/InlineLink.tsx
new file mode 100644
index 0000000..6982714
--- /dev/null
+++ b/client/src/components/InlineLink.tsx
@@ -0,0 +1,38 @@
+import { FC } from "react";
+import clsx from "clsx";
+import { NavLink } from "react-router-dom";
+
+export interface InlineLinkProps
+ extends React.ComponentPropsWithoutRef<"span"> {
+ to: string;
+ external?: boolean;
+}
+
+const InlineLink: FC = ({
+ to,
+ external,
+ className,
+ ...rest
+}) => {
+ if (external === true) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+
+
+ );
+};
+
+export default InlineLink;
diff --git a/client/src/components/LoginModal.tsx b/client/src/components/LoginModal.tsx
new file mode 100644
index 0000000..f67b840
--- /dev/null
+++ b/client/src/components/LoginModal.tsx
@@ -0,0 +1,129 @@
+import React, { FC } from "react";
+import { Dialog } from "@headlessui/react";
+import { createPortal } from "react-dom";
+import { Tab } from "@headlessui/react";
+import clsx from "clsx";
+import FormField from "./FormField";
+import Button from "./Button";
+import InlineLink from "./InlineLink";
+import logo from "../assets/images/logo.png";
+
+export interface LoginModelProps {
+ isOpen: boolean;
+ onClose: () => any;
+ defaultPage?: number;
+}
+
+const LoginModal: FC = ({ defaultPage, isOpen, onClose }) => {
+ return createPortal(
+ ,
+ document.body
+ );
+};
+
+interface LoginModalTabProps extends React.ComponentPropsWithoutRef<"p"> {
+ selected: boolean;
+}
+
+const LoginModalTab: FC = ({ selected, ...rest }) => {
+ return (
+
+ );
+};
+
+export default LoginModal;
diff --git a/client/src/components/NavBar.tsx b/client/src/components/NavBar.tsx
index 0cff89b..92ac784 100644
--- a/client/src/components/NavBar.tsx
+++ b/client/src/components/NavBar.tsx
@@ -1,16 +1,31 @@
import { TvIcon, UserIcon } from "@heroicons/react/24/outline";
-import { FC } from "react";
+import { FC, useState } from "react";
import Button from "./Button";
import Input from "./Input";
+import LoginModal from "./LoginModal";
+import logo from "../assets/images/logo.png";
const NavBar: FC = () => {
+ const [showLogin, setShowLogin] = useState(false);
+ const [showTab, setShowTab] = useState(0);
+
+ const showLoginTab = () => {
+ setShowTab(0);
+ setShowLogin(true);
+ };
+
+ const showSignupTab = () => {
+ setShowTab(1);
+ setShowLogin(true);
+ };
+
return (