From f3d588c0eb4e36c8d035c52956a57ceb412a15e0 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Sat, 28 Jan 2023 23:53:45 -0800 Subject: [PATCH] button style improvements, homepage and navbar refactors --- src/app/(auth)/components/index.tsx | 38 +++--- src/app/(posts)/components/preview/index.tsx | 18 +-- src/app/(posts)/components/tabs/index.tsx | 14 +- .../post/[id]/components/post-files/index.tsx | 1 - .../post-files/view-document/index.tsx | 2 +- src/app/components/button/button.module.css | 2 +- src/app/components/button/index.tsx | 7 +- src/app/components/card/card.module.css | 4 +- src/app/components/header/header.module.css | 5 - src/app/components/header/index.tsx | 121 ++++++++-------- src/app/components/post-list/index.tsx | 34 +++-- .../components/post-list/post-list.module.css | 4 + src/app/components/skeleton/index.tsx | 9 +- src/app/layout.tsx | 7 +- src/app/mine/page.tsx | 15 +- src/app/page.tsx | 129 +++++++++--------- .../settings/components/sections/profile.tsx | 3 +- src/lib/server/auth.ts | 1 - src/pages/api/file/raw/[id].ts | 1 - 19 files changed, 214 insertions(+), 201 deletions(-) diff --git a/src/app/(auth)/components/index.tsx b/src/app/(auth)/components/index.tsx index 7de0a4aa..fbe5ae4e 100644 --- a/src/app/(auth)/components/index.tsx +++ b/src/app/(auth)/components/index.tsx @@ -132,25 +132,27 @@ function Auth({ - {isGithubEnabled ?
: null} {isGithubEnabled ? ( - + <> +
+ + ) : null}
diff --git a/src/app/(posts)/components/preview/index.tsx b/src/app/(posts)/components/preview/index.tsx index 8061711b..e74657e7 100644 --- a/src/app/(posts)/components/preview/index.tsx +++ b/src/app/(posts)/components/preview/index.tsx @@ -8,12 +8,12 @@ import { fetchWithUser } from "src/app/lib/fetch-with-user" type Props = { height?: number | string fileId?: string - content?: string title?: string + children?: string } -function MarkdownPreview({ height = 500, fileId, content = "", title }: Props) { - const [preview, setPreview] = useState(content) +function MarkdownPreview({ height = 500, fileId, title, children }: Props) { + const [preview, setPreview] = useState(children || "") const [isLoading, setIsLoading] = useState(true) useEffect(() => { async function fetchPost() { @@ -24,7 +24,7 @@ function MarkdownPreview({ height = 500, fileId, content = "", title }: Props) { ? undefined : JSON.stringify({ title: title || "", - content: content + content: children }) const resp = await fetchWithUser(path, { @@ -43,14 +43,14 @@ function MarkdownPreview({ height = 500, fileId, content = "", title }: Props) { setIsLoading(false) } fetchPost() - }, [content, fileId, title]) + }, [children, fileId, title]) return ( <> {isLoading ? ( ) : ( - + {preview} )} ) @@ -59,16 +59,16 @@ function MarkdownPreview({ height = 500, fileId, content = "", title }: Props) { export default memo(MarkdownPreview) export function StaticPreview({ - preview, + children, height = 500 }: { - preview: string + children: string height: string | number }) { return (
) => void onPaste?: (e: ClipboardEvent) => void title?: string - content?: string - preview?: string + staticPreview?: string + children: string; } export default function DocumentTabs({ @@ -23,8 +23,8 @@ export default function DocumentTabs({ handleOnContentChange, onPaste, title, - content, - preview, + staticPreview: preview, + children, ...props }: Props) { const codeEditorRef = useRef(null) @@ -72,7 +72,7 @@ export default function DocumentTabs({ onPaste={onPaste ? onPaste : undefined} ref={codeEditorRef} placeholder="" - value={content} + value={children} onChange={handleOnContentChange} // TODO: Textarea should grow to fill parent if height == 100% style={{ flex: 1, minHeight: 350 }} @@ -83,9 +83,9 @@ export default function DocumentTabs({ {isEditing ? ( - + {children} ) : ( - + {preview} )} diff --git a/src/app/(posts)/post/[id]/components/post-files/index.tsx b/src/app/(posts)/post/[id]/components/post-files/index.tsx index 86596a3c..c254f506 100644 --- a/src/app/(posts)/post/[id]/components/post-files/index.tsx +++ b/src/app/(posts)/post/[id]/components/post-files/index.tsx @@ -45,7 +45,6 @@ const PostFiles = ({ post: _initialPost }: Props) => { const isProtected = post?.visibility === "protected" const hasFetched = post?.files !== undefined - console.log({ isProtected, hasFetched }) if (isProtected && !hasFetched) { return ( { {/* Not /api/ because of rewrites defined in next.config.mjs */} diff --git a/src/app/components/button/button.module.css b/src/app/components/button/button.module.css index 047b8b38..5b0db4c7 100644 --- a/src/app/components/button/button.module.css +++ b/src/app/components/button/button.module.css @@ -3,7 +3,7 @@ cursor: pointer; border-radius: var(--radius); border: 1px solid var(--border); - padding: var(--gap-half) var(--gap); + /* padding: var(--gap-half) var(--gap); */ color: var(--darker-gray); } diff --git a/src/app/components/button/index.tsx b/src/app/components/button/index.tsx index bac2391d..60c10728 100644 --- a/src/app/components/button/index.tsx +++ b/src/app/components/button/index.tsx @@ -31,11 +31,12 @@ const Button = forwardRef( disabled = false, iconRight, iconLeft, - height, + height = 40, width, - padding, + padding = 10, margin, loading, + style, ...props }, ref @@ -49,7 +50,7 @@ const Button = forwardRef( })} disabled={disabled || loading} onClick={onClick} - style={{ height, width, margin, padding }} + style={{ height, width, margin, padding, ...style }} {...props} > {children && iconLeft && ( diff --git a/src/app/components/card/card.module.css b/src/app/components/card/card.module.css index 2a4f2b5d..75c50b2d 100644 --- a/src/app/components/card/card.module.css +++ b/src/app/components/card/card.module.css @@ -3,8 +3,8 @@ border-radius: var(--radius); color: var(--fg); border: 1px solid var(--light-gray); - width: auto; - height: auto; + width: 100%; + height: 100%; } diff --git a/src/app/components/header/header.module.css b/src/app/components/header/header.module.css index fdc30150..57441306 100644 --- a/src/app/components/header/header.module.css +++ b/src/app/components/header/header.module.css @@ -38,11 +38,6 @@ .header { transition: opacity 0.2s ease-in-out; - opacity: 0; -} - -.header:not(.loading) { - opacity: 1; } .selectContent { diff --git a/src/app/components/header/index.tsx b/src/app/components/header/index.tsx index 86f08c8f..a23dab84 100644 --- a/src/app/components/header/index.tsx +++ b/src/app/components/header/index.tsx @@ -9,7 +9,6 @@ import Button from "@components/button" import clsx from "clsx" import { useTheme } from "next-themes" import { - GitHub, Home, Menu, Moon, @@ -17,13 +16,13 @@ import { Settings, Sun, User, - UserPlus, UserX } from "react-feather" import * as DropdownMenu from "@radix-ui/react-dropdown-menu" import buttonStyles from "@components/button/button.module.css" import { useMemo } from "react" import { useSessionSWR } from "@lib/use-session-swr" +import Skeleton from "@components/skeleton" type Tab = { name: string @@ -34,7 +33,7 @@ type Tab = { } const Header = () => { - const { isAuthenticated, isAdmin, isLoading, mutate } = useSessionSWR() + const { isAdmin, isAuthenticated, isLoading, mutate } = useSessionSWR() const pathname = usePathname() const { setTheme, resolvedTheme } = useTheme() @@ -52,6 +51,7 @@ const Header = () => { aria-label={tab.name} aria-current={isActive ? "page" : undefined} data-tab={tab.value} + width="auto" > {tab.name ? tab.name : undefined} @@ -59,7 +59,7 @@ const Header = () => { } else if (tab.href) { return ( - @@ -69,12 +69,12 @@ const Header = () => { const pages = useMemo(() => { const defaultPages: Tab[] = [ - { - name: "GitHub", - href: "https://github.com/maxleiter/drift", - icon: , - value: "github" - } + // { + // name: "GitHub", + // href: "https://github.com/maxleiter/drift", + // icon: , + // value: "github" + // } ] if (isAdmin) { @@ -95,28 +95,10 @@ const Header = () => { value: "theme" }) - if (isAuthenticated) - return [ - { - name: "New", - icon: , - value: "new", - href: "/new" - }, - { - name: "Yours", - icon: , - value: "yours", - href: "/mine" - }, - { - name: "Settings", - icon: , - value: "settings", - href: "/settings" - }, - ...defaultPages, - { + // the is loading case is handled in the JSX + if (!isLoading) { + if (isAuthenticated) { + defaultPages.push({ name: "Sign Out", icon: , value: "signout", @@ -126,45 +108,68 @@ const Header = () => { callbackUrl: "/" }) } - } - ] - else - return [ - { - name: "Home", - icon: , - value: "home", - href: "/" - }, - ...defaultPages, - { + }) + } else { + defaultPages.push({ name: "Sign in", icon: , value: "signin", href: "/signin" - }, - { - name: "Sign up", - icon: , - value: "signup", - href: "/signup" - } - ] - }, [isAdmin, resolvedTheme, isAuthenticated, setTheme, mutate]) + }) + } + } + + return [ + { + name: "Home", + icon: , + value: "home", + href: "/home" + }, + { + name: "New", + icon: , + value: "new", + href: "/new" + }, + { + name: "Yours", + icon: , + value: "yours", + href: "/mine" + }, + { + name: "Settings", + icon: , + value: "settings", + href: "/settings" + }, + ...defaultPages + ] + }, [isAdmin, resolvedTheme, isLoading, setTheme, isAuthenticated, mutate]) const buttons = pages.map(getButton) + if (isLoading) { + buttons.push( + + ) + } + // TODO: this is a hack to close the radix ui menu when a next link is clicked const onClick = () => { document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" })) } return ( -
+
{buttons}
diff --git a/src/app/components/post-list/index.tsx b/src/app/components/post-list/index.tsx index 382a0263..e41e6069 100644 --- a/src/app/components/post-list/index.tsx +++ b/src/app/components/post-list/index.tsx @@ -10,6 +10,7 @@ import { ListItemSkeleton } from "./list-item-skeleton" import Link from "@components/link" import debounce from "lodash.debounce" import { fetchWithUser } from "src/app/lib/fetch-with-user" +import { Stack } from "@components/stack" type Props = { initialPosts: string | PostWithFiles[] @@ -63,7 +64,6 @@ const PostList = ({ } ) const json = await res.json() - console.log(json) setPosts(json) setSearching(false) } @@ -101,7 +101,7 @@ const PostList = ({ ) return ( -
+ {!hideSearch && (
)} {!showSkeleton && posts && posts.length > 0 ? ( -
-
    - {posts.map((post) => { - return ( - - ) - })} -
-
+
    + {posts.map((post) => { + return ( + + ) + })} +
) : null} -
+
) } diff --git a/src/app/components/post-list/post-list.module.css b/src/app/components/post-list/post-list.module.css index 39f82288..d59f02e4 100644 --- a/src/app/components/post-list/post-list.module.css +++ b/src/app/components/post-list/post-list.module.css @@ -4,6 +4,10 @@ margin: 0; } +.container > * { + width: 100%; +} + .container ul li { padding: 0.5rem 0; } diff --git a/src/app/components/skeleton/index.tsx b/src/app/components/skeleton/index.tsx index 6e8b1627..3a2a87c6 100644 --- a/src/app/components/skeleton/index.tsx +++ b/src/app/components/skeleton/index.tsx @@ -3,13 +3,18 @@ import styles from "./skeleton.module.css" export default function Skeleton({ width = 100, height = 24, - borderRadius = 4 + borderRadius = 4, + style }: { width?: number | string height?: number | string borderRadius?: number | string + style?: React.CSSProperties }) { return ( -
+
) } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 5f52e814..7e049acf 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -4,7 +4,8 @@ import Layout from "@components/layout" import { Toasts } from "@components/toasts" import Header from "@components/header" import { Inter } from "@next/font/google" -import { PropsWithChildren } from "react" +import { PropsWithChildren, Suspense } from "react" +import { Spinner } from "@components/spinner" const inter = Inter({ subsets: ["latin"], variable: "--inter-font" }) @@ -19,7 +20,9 @@ export default async function RootLayout({ -
+ }> +
+ {children} diff --git a/src/app/mine/page.tsx b/src/app/mine/page.tsx index ef2dce82..13ee3d1b 100644 --- a/src/app/mine/page.tsx +++ b/src/app/mine/page.tsx @@ -3,6 +3,7 @@ import { getPostsByUser } from "@lib/server/prisma" import PostList from "@components/post-list" import { getCurrentUser } from "@lib/server/session" import { authOptions } from "@lib/server/auth" +import { Suspense } from "react" export default async function Mine() { const userId = (await getCurrentUser())?.id @@ -15,12 +16,14 @@ export default async function Mine() { const stringifiedPosts = JSON.stringify(posts) return ( - + }> + + ) } diff --git a/src/app/page.tsx b/src/app/page.tsx index 5aefbb51..d2785d16 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,17 +2,72 @@ import Image from "next/image" import Card from "@components/card" import { getWelcomeContent } from "src/pages/api/welcome" import DocumentTabs from "./(posts)/components/tabs" -import { getAllPosts, Post } from "@lib/server/prisma" +import { getAllPosts } from "@lib/server/prisma" import PostList, { NoPostsFound } from "@components/post-list" -import { Suspense } from "react" +import { cache, Suspense } from "react" +import ErrorBoundary from "@components/error/fallback" +import { Stack } from "@components/stack" -export async function getWelcomeData() { +const getWelcomeData = cache(async () => { const welcomeContent = await getWelcomeContent() return welcomeContent -} +}) export default async function Page() { - const getPostsPromise = getAllPosts({ + const { title } = await getWelcomeData() + + return ( + + + +

{title}

+
+ {/* @ts-expect-error because of async RSC */} + +

Recent public posts

+ + + } + > + {/* @ts-expect-error because of async RSC */} + + + +
+ ) +} + +async function WelcomePost() { + const { content, rendered, title } = await getWelcomeData() + return ( + + + {content} + + + ) +} + +async function PublicPostList() { + const posts = await getAllPosts({ select: { id: true, title: true, @@ -38,66 +93,12 @@ export default async function Page() { createdAt: "desc" } }) - const { content, rendered, title } = await getWelcomeData() - return ( -
-
- -

{title}

-
- - - -
-

Recent public posts

- - } - > - {/* @ts-expect-error because of async RSC */} - - -
-
- ) -} - -async function PublicPostList({ - getPostsPromise -}: { - getPostsPromise: Promise -}) { - try { - const posts = await getPostsPromise - - if (posts.length === 0) { - return - } - - return ( - - ) - } catch (error) { + if (posts.length === 0) { return } -} -export const revalidate = 60 + return ( + + ) +} diff --git a/src/app/settings/components/sections/profile.tsx b/src/app/settings/components/sections/profile.tsx index 3955425a..55ffb8ac 100644 --- a/src/app/settings/components/sections/profile.tsx +++ b/src/app/settings/components/sections/profile.tsx @@ -12,7 +12,6 @@ import { User } from "@prisma/client" function Profile() { const { session } = useSessionSWR() - console.log(session) const { data: userData } = useSWR( session?.user?.id ? `/api/user/${session?.user?.id}` : null ) @@ -104,7 +103,7 @@ function Profile() { type="email" width={"100%"} placeholder="my@email.io" - value={session?.user.email || undefined} + value={session?.user.email || ""} disabled aria-label="Email" /> diff --git a/src/lib/server/auth.ts b/src/lib/server/auth.ts index 131f6641..2cbbaf27 100644 --- a/src/lib/server/auth.ts +++ b/src/lib/server/auth.ts @@ -49,7 +49,6 @@ const providers = () => { // @ts-expect-error TODO: fix types credentials: credentialsOptions() as unknown, async authorize(credentials) { - console.log("credentials") if (!credentials || !credentials.username || !credentials.password) { throw new Error("Missing credentials") } diff --git a/src/pages/api/file/raw/[id].ts b/src/pages/api/file/raw/[id].ts index 4a9de371..c4a3027b 100644 --- a/src/pages/api/file/raw/[id].ts +++ b/src/pages/api/file/raw/[id].ts @@ -5,7 +5,6 @@ import { withMethods } from "@lib/api-middleware/with-methods" const getRawFile = async (req: NextApiRequest, res: NextApiResponse) => { const { id, download } = req.query - const file = await prisma.file.findUnique({ where: { id: parseQueryParam(id)