diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index c838d12..b66d17b 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8,6 +8,7 @@
"name": "goshort",
"version": "0.0.0",
"dependencies": {
+ "@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.0.18",
"classnames": "^2.3.2",
"react": "^18.2.0",
@@ -469,6 +470,21 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@headlessui/react": {
+ "version": "1.7.17",
+ "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.17.tgz",
+ "integrity": "sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==",
+ "dependencies": {
+ "client-only": "^0.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^16 || ^17 || ^18",
+ "react-dom": "^16 || ^17 || ^18"
+ }
+ },
"node_modules/@heroicons/react": {
"version": "2.0.18",
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.18.tgz",
@@ -1614,6 +1630,11 @@
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
},
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
+ },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 066f8ad..820e47f 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
+ "@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.0.18",
"classnames": "^2.3.2",
"react": "^18.2.0",
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 2358255..c1f5395 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,17 +1,20 @@
import { FunctionComponent } from "react"
-import { Outlet } from "react-router-dom"
+import { Outlet, ScrollRestoration } from "react-router-dom"
-import Button from "./components/Button"
+// import Button from "./components/Button"
import Container from "./components/Container"
-import { useIsAuthenticated } from "./hooks/useAuth"
+import Navbar from "./components/Navbar"
+// import { useIsAuthenticated } from "./hooks/useAuth"
const App: FunctionComponent = () => {
- const isAuthenticated = useIsAuthenticated()
+ // const isAuthenticated = useIsAuthenticated()
return (
-
-
-
+ <>
+
+
+
+ {/*
@@ -29,12 +32,14 @@ const App: FunctionComponent = () => {
{isAuthenticated ||
}
{isAuthenticated &&
}
+
*/}
+
+
+
-
-
-
-
-
+
+
+ >
)
}
diff --git a/frontend/src/components/BackButton.tsx b/frontend/src/components/BackButton.tsx
new file mode 100644
index 0000000..9654b0d
--- /dev/null
+++ b/frontend/src/components/BackButton.tsx
@@ -0,0 +1,27 @@
+import { FunctionComponent, useCallback } from "react"
+
+import { ChevronLeftIcon } from "@heroicons/react/24/outline"
+import classNames from "classnames"
+import { useNavigate } from "react-router-dom"
+
+const BackButton: FunctionComponent<{ className?: string }> = ({
+ className,
+}) => {
+ const navigate = useNavigate()
+ const goBack = useCallback(() => navigate(-1), [navigate])
+
+ return (
+
+
+
+
+ )
+}
+
+export default BackButton
diff --git a/frontend/src/components/Container.tsx b/frontend/src/components/Container.tsx
index be49b9f..642a3a3 100644
--- a/frontend/src/components/Container.tsx
+++ b/frontend/src/components/Container.tsx
@@ -2,7 +2,7 @@ import { FunctionComponent, PropsWithChildren } from "react"
const Container: FunctionComponent = ({ children }) => {
return (
-
+
{children}
)
diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx
index c8fc0fe..ca179ea 100644
--- a/frontend/src/components/Header.tsx
+++ b/frontend/src/components/Header.tsx
@@ -2,7 +2,7 @@ import { FunctionComponent } from "react"
const Header: FunctionComponent<{ title: string }> = ({ title }) => {
return (
-
+
)
diff --git a/frontend/src/components/Button.tsx b/frontend/src/components/NavButton.tsx
similarity index 87%
rename from frontend/src/components/Button.tsx
rename to frontend/src/components/NavButton.tsx
index e7b5490..5de40c2 100644
--- a/frontend/src/components/Button.tsx
+++ b/frontend/src/components/NavButton.tsx
@@ -3,7 +3,7 @@ import { FunctionComponent } from "react"
import classNames from "classnames"
import { NavLink, useSearchParams } from "react-router-dom"
-const Button: FunctionComponent<{
+const NavButton: FunctionComponent<{
text: string
onClick?: () => void
link?: string
@@ -11,7 +11,7 @@ const Button: FunctionComponent<{
const Content: FunctionComponent<{ active?: boolean }> = ({ active }) => (
}
-export default Button
+export default NavButton
diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx
new file mode 100644
index 0000000..acafebd
--- /dev/null
+++ b/frontend/src/components/Navbar.tsx
@@ -0,0 +1,146 @@
+import { Fragment, useMemo } from "react"
+
+import { Disclosure, Menu, Transition } from "@headlessui/react"
+import {
+ Bars3Icon,
+ ChevronDownIcon,
+ XMarkIcon,
+} from "@heroicons/react/24/outline"
+import classNames from "classnames"
+import { Link, NavLink } from "react-router-dom"
+
+import { useIsAuthenticated, useUser } from "../hooks/useAuth"
+
+import NavButton from "./NavButton"
+
+export default function Navbar() {
+ const isAuthenticated = useIsAuthenticated()
+ const user = useUser()
+
+ const navigation = useMemo(() => {
+ const authed = [
+ { name: "Shorts", href: "sht" },
+ { name: "Tokens", href: "tkn" },
+ { name: "Sessions", href: "ses" },
+ ]
+ const unauthed = [
+ { name: "Login", href: "lgn" },
+ { name: "Signup", href: "sgn" },
+ ]
+ return isAuthenticated ? authed : unauthed
+ }, [isAuthenticated])
+
+ return (
+
+ {({ open }) => (
+ <>
+
+
+
+ {/* Mobile menu button*/}
+
+
+ Open main menu
+ {open ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+ {navigation.map((item) => (
+
+ ))}
+
+
+
+
+ {/* Profile dropdown */}
+ {isAuthenticated && (
+
+ )}
+ {isAuthenticated ||
}
+
+
+
+
+
+ {({ close }) => (
+
+ {navigation.map((item) => (
+ close()}
+ key={item.name}
+ to={item.href}
+ className={({ isActive }) =>
+ classNames(
+ isActive
+ ? "bg-blue-100 text-blue-600 border-blue-500"
+ : "text-slate-500 hover:bg-slate-50 hover:text-slate-600 hover:border-slate-500",
+ "block border-l-4 border-transparent px-3 py-2 text-base font-medium"
+ )
+ }>
+ {item.name}
+
+ ))}
+
+ )}
+
+ >
+ )}
+
+ )
+}
diff --git a/frontend/src/components/ShortItem.tsx b/frontend/src/components/ShortItem.tsx
index b904770..5cf6694 100644
--- a/frontend/src/components/ShortItem.tsx
+++ b/frontend/src/components/ShortItem.tsx
@@ -68,7 +68,7 @@ const ShortItem: FunctionComponent
void }> = ({
@@ -87,10 +87,10 @@ const ShortItem: FunctionComponent void }> = ({
Last viewed
-
diff --git a/frontend/src/index.css b/frontend/src/index.css
index 62d2254..22299f5 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -3,6 +3,6 @@
@tailwind utilities;
:root {
- @apply text-slate-700;
+ @apply text-slate-700 bg-slate-50;
font-family: -apple-system, SF Pro Text, SF UI Text, system-ui, Helvetica Neue, Helvetica, Arial, sans-serif;
}
diff --git a/frontend/src/pages/ShortDetails.tsx b/frontend/src/pages/ShortDetails.tsx
index f245833..dd9e73c 100644
--- a/frontend/src/pages/ShortDetails.tsx
+++ b/frontend/src/pages/ShortDetails.tsx
@@ -1,5 +1,6 @@
import { LoaderFunction, redirect, useLoaderData } from "react-router-dom"
+import BackButton from "../components/BackButton"
import Header from "../components/Header"
import { protectedLoader } from "../hooks/useAuth"
import { Short } from "../types"
@@ -10,6 +11,7 @@ export function Component() {
return (
<>
+
{short.url}
>