From dcf9c999697d5eac949c810ea427ee8b85c512ef Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Sat, 15 Jul 2023 22:14:11 -0700 Subject: [PATCH] Styling adjustmnets, fix pages feature, replace styles with tw --- next.config.mjs | 4 +- package.json | 5 +- pnpm-lock.yaml | 72 +++++++++++----- src/app/(drift)/(auth)/components/index.tsx | 2 - .../(auth)/components/query-handler.tsx | 4 +- .../components/document-tabs/index.tsx | 20 ++++- .../file-dropdown/dropdown.module.css | 13 --- .../components/file-dropdown/index.tsx | 7 +- .../components/preview/preview.module.css | 41 +++------ .../(drift)/(posts)/new/components/new.tsx | 86 +++++++++---------- .../(posts)/new/components/title/index.tsx | 5 +- .../components/header/post-buttons/index.tsx | 1 - src/app/(drift)/page.tsx | 2 +- .../settings/components/sections/profile.tsx | 1 - src/app/components/badges/badge.tsx | 2 +- .../badges/expiration-badge/index.tsx | 3 +- .../badges/visibility-control/index.tsx | 1 - src/app/components/button/index.tsx | 4 +- src/app/components/date-picker.tsx | 2 +- src/app/components/header/index.tsx | 3 +- src/app/components/link/index.tsx | 1 - src/app/components/password-modal/index.tsx | 5 +- .../components/post-list/home-list-item.tsx | 86 +++++++++---------- src/app/components/post-list/index.tsx | 6 +- src/app/components/post-list/list-item.tsx | 2 - src/app/pages/[fileId]/[fileTitle]/page.tsx | 9 +- .../[fileId]/[fileTitle]/theme-provider.tsx | 2 +- src/app/styles/globals.css | 2 +- tailwind.config.js | 2 +- 29 files changed, 192 insertions(+), 201 deletions(-) diff --git a/next.config.mjs b/next.config.mjs index 33ab4e9d..e176ab72 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -32,6 +32,6 @@ const nextConfig = { } } -export default bundleAnalyzer({ enabled: process.env.ANALYZE === "true" })( +export default process.env.ANALYZE === "true" ? bundleAnalyzer({ enabled: true })( nextConfig -) +) : nextConfig diff --git a/package.json b/package.json index 58ed0a07..0377d2e7 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "dependencies": { "@next-auth/prisma-adapter": "^1.0.7", "@next/eslint-plugin-next": "13.4.9", - "@prisma/client": "^4.16.2", + "@prisma/client": "^5.0.0", "@radix-ui/react-alert-dialog": "^1.0.4", "@radix-ui/react-dialog": "^1.0.3", "@radix-ui/react-dropdown-menu": "^2.0.4", @@ -25,6 +25,7 @@ "@radix-ui/react-tabs": "^1.0.3", "@radix-ui/react-tooltip": "^1.0.5", "@tailwindcss/nesting": "0.0.0-insiders.565cd3e", + "@tailwindcss/typography": "^0.5.9", "class-variance-authority": "^0.6.0", "client-only": "^0.0.1", "client-zip": "2.3.1", @@ -84,7 +85,7 @@ "postcss-preset-env": "^8.4.1", "prettier": "2.8.7", "prettier-plugin-tailwindcss": "^0.3.0", - "prisma": "^4.16.2", + "prisma": "^5.0.0", "tailwindcss": "^3.3.2", "typescript": "5.1.6", "typescript-plugin-css-modules": "5.0.1" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5a208ed5..1abd9bc6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,13 +7,13 @@ settings: dependencies: '@next-auth/prisma-adapter': specifier: ^1.0.7 - version: 1.0.7(@prisma/client@4.16.2)(next-auth@4.22.1) + version: 1.0.7(@prisma/client@5.0.0)(next-auth@4.22.1) '@next/eslint-plugin-next': specifier: 13.4.9 version: 13.4.9 '@prisma/client': - specifier: ^4.16.2 - version: 4.16.2(prisma@4.16.2) + specifier: ^5.0.0 + version: 5.0.0(prisma@5.0.0) '@radix-ui/react-alert-dialog': specifier: ^1.0.4 version: 1.0.4(@types/react-dom@18.0.11)(@types/react@18.0.35)(react-dom@18.2.0)(react@18.2.0) @@ -41,6 +41,9 @@ dependencies: '@tailwindcss/nesting': specifier: 0.0.0-insiders.565cd3e version: 0.0.0-insiders.565cd3e(postcss@8.4.21) + '@tailwindcss/typography': + specifier: ^0.5.9 + version: 0.5.9(tailwindcss@3.3.2) class-variance-authority: specifier: ^0.6.0 version: 0.6.0(typescript@5.1.6) @@ -220,8 +223,8 @@ devDependencies: specifier: ^0.3.0 version: 0.3.0(prettier@2.8.7) prisma: - specifier: ^4.16.2 - version: 4.16.2 + specifier: ^5.0.0 + version: 5.0.0 tailwindcss: specifier: ^3.3.2 version: 3.3.2 @@ -1240,13 +1243,13 @@ packages: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 - /@next-auth/prisma-adapter@1.0.7(@prisma/client@4.16.2)(next-auth@4.22.1): + /@next-auth/prisma-adapter@1.0.7(@prisma/client@5.0.0)(next-auth@4.22.1): resolution: {integrity: sha512-Cdko4KfcmKjsyHFrWwZ//lfLUbcLqlyFqjd/nYE2m3aZ7tjMNUjpks47iw7NTCnXf+5UWz5Ypyt1dSs1EP5QJw==} peerDependencies: '@prisma/client': '>=2.26.0 || >=3' next-auth: ^4 dependencies: - '@prisma/client': 4.16.2(prisma@4.16.2) + '@prisma/client': 5.0.0(prisma@5.0.0) next-auth: 4.22.1(next@13.4.9)(react-dom@18.2.0)(react@18.2.0) dev: false @@ -1395,9 +1398,9 @@ packages: resolution: {integrity: sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==} dev: false - /@prisma/client@4.16.2(prisma@4.16.2): - resolution: {integrity: sha512-qCoEyxv1ZrQ4bKy39GnylE8Zq31IRmm8bNhNbZx7bF2cU5aiCCnSa93J2imF88MBjn7J9eUQneNxUQVJdl/rPQ==} - engines: {node: '>=14.17'} + /@prisma/client@5.0.0(prisma@5.0.0): + resolution: {integrity: sha512-XlO5ELNAQ7rV4cXIDJUNBEgdLwX3pjtt9Q/RHqDpGf43szpNJx2hJnggfFs7TKNx0cOFsl6KJCSfqr5duEU/bQ==} + engines: {node: '>=16.13'} requiresBuild: true peerDependencies: prisma: '*' @@ -1405,16 +1408,16 @@ packages: prisma: optional: true dependencies: - '@prisma/engines-version': 4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81 - prisma: 4.16.2 + '@prisma/engines-version': 4.17.0-26.6b0aef69b7cdfc787f822ecd7cdc76d5f1991584 + prisma: 5.0.0 dev: false - /@prisma/engines-version@4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81: - resolution: {integrity: sha512-q617EUWfRIDTriWADZ4YiWRZXCa/WuhNgLTVd+HqWLffjMSPzyM5uOWoauX91wvQClSKZU4pzI4JJLQ9Kl62Qg==} + /@prisma/engines-version@4.17.0-26.6b0aef69b7cdfc787f822ecd7cdc76d5f1991584: + resolution: {integrity: sha512-HHiUF6NixsldsP3JROq07TYBLEjXFKr6PdH8H4gK/XAoTmIplOJBCgrIUMrsRAnEuGyRoRLXKXWUb943+PFoKQ==} dev: false - /@prisma/engines@4.16.2: - resolution: {integrity: sha512-vx1nxVvN4QeT/cepQce68deh/Turxy5Mr+4L4zClFuK1GlxN3+ivxfuv+ej/gvidWn1cE1uAhW7ALLNlYbRUAw==} + /@prisma/engines@5.0.0: + resolution: {integrity: sha512-kyT/8fd0OpWmhAU5YnY7eP31brW1q1YrTGoblWrhQJDiN/1K+Z8S1kylcmtjqx5wsUGcP1HBWutayA/jtyt+sg==} requiresBuild: true /@radix-ui/primitive@1.0.0: @@ -2390,6 +2393,18 @@ packages: postcss-nested: 5.0.6(postcss@8.4.21) dev: false + /@tailwindcss/typography@0.5.9(tailwindcss@3.3.2): + resolution: {integrity: sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + dependencies: + lodash.castarray: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + postcss-selector-parser: 6.0.10 + tailwindcss: 3.3.2 + dev: false + /@total-typescript/ts-reset@0.4.2: resolution: {integrity: sha512-vqd7ZUDSrXFVT1n8b2kc3LnklncDQFPvR58yUS1kEP23/nHPAO9l1lMjUfnPrXYYk4Hj54rrLKMW5ipwk7k09A==} dev: true @@ -5774,17 +5789,24 @@ packages: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} dev: true + /lodash.castarray@4.4.0: + resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} + dev: false + /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} dev: false + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: false + /lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} dev: false /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -7283,6 +7305,14 @@ packages: postcss-selector-parser: 6.0.11 dev: true + /postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: false + /postcss-selector-parser@6.0.11: resolution: {integrity: sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==} engines: {node: '>=4'} @@ -7503,13 +7533,13 @@ packages: parse-ms: 2.1.0 dev: true - /prisma@4.16.2: - resolution: {integrity: sha512-SYCsBvDf0/7XSJyf2cHTLjLeTLVXYfqp7pG5eEVafFLeT0u/hLFz/9W196nDRGUOo1JfPatAEb+uEnTQImQC1g==} - engines: {node: '>=14.17'} + /prisma@5.0.0: + resolution: {integrity: sha512-KYWk83Fhi1FH59jSpavAYTt2eoMVW9YKgu8ci0kuUnt6Dup5Qy47pcB4/TLmiPAbhGrxxSz7gsSnJcCmkyPANA==} + engines: {node: '>=16.13'} hasBin: true requiresBuild: true dependencies: - '@prisma/engines': 4.16.2 + '@prisma/engines': 5.0.0 /process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} diff --git a/src/app/(drift)/(auth)/components/index.tsx b/src/app/(drift)/(auth)/components/index.tsx index 6c9f9773..88315ffe 100644 --- a/src/app/(drift)/(auth)/components/index.tsx +++ b/src/app/(drift)/(auth)/components/index.tsx @@ -12,8 +12,6 @@ import { useRouter } from "next/navigation" import Note from "@components/note" import { ErrorQueryParamsHandler } from "./query-handler" import { AuthProviders } from "@lib/server/auth-props" -import { TypographyH1 } from "@components/typography" -import { cn } from "@lib/cn" function Auth({ page, diff --git a/src/app/(drift)/(auth)/components/query-handler.tsx b/src/app/(drift)/(auth)/components/query-handler.tsx index 02e51d32..dff5740c 100644 --- a/src/app/(drift)/(auth)/components/query-handler.tsx +++ b/src/app/(drift)/(auth)/components/query-handler.tsx @@ -4,7 +4,7 @@ import { useToasts } from "@components/toasts" import { useSearchParams } from "next/navigation" import { Suspense, useEffect } from "react" -function _ErrorQueryParamsHandler() { +function InnerErrorQueryParamsHandler() { const queryParams = useSearchParams() const { setToast } = useToasts() @@ -24,7 +24,7 @@ export function ErrorQueryParamsHandler() { /* Suspense boundary because useSearchParams causes static bailout */ return ( - <_ErrorQueryParamsHandler /> + ) } diff --git a/src/app/(drift)/(posts)/components/document-tabs/index.tsx b/src/app/(drift)/(posts)/components/document-tabs/index.tsx index a1600341..1a7a8bd4 100644 --- a/src/app/(drift)/(posts)/components/document-tabs/index.tsx +++ b/src/app/(drift)/(posts)/components/document-tabs/index.tsx @@ -1,7 +1,13 @@ "use client" import FormattingIcons from "src/app/(drift)/(posts)/new/components/edit-document-list/edit-document/formatting-icons" -import { ChangeEvent, ClipboardEvent, ComponentProps, useRef } from "react" +import { + ChangeEvent, + ClipboardEvent, + ComponentProps, + useRef, + useState +} from "react" import TextareaMarkdown, { TextareaMarkdownRef } from "textarea-markdown-editor" import Preview, { StaticPreview } from "../preview" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@components/tabs" @@ -28,13 +34,16 @@ export default function DocumentTabs({ ...props }: Props) { const codeEditorRef = useRef(null) - + const [activeTab, setActiveTab] = useState<"preview" | "edit">(defaultTab) const handleTabChange = (newTab: string) => { if (newTab === "preview") { codeEditorRef.current?.focus() } + setActiveTab(newTab as "preview" | "edit") } + const formattingIconsVisibilityClass = + activeTab === "preview" ? "hidden" : "block" return ( @@ -44,7 +53,12 @@ export default function DocumentTabs({ {isEditing ? "Preview" : "Rendered"} - {isEditing && } + {isEditing && ( + + )}
+ icon: } } else { return { ...file, - icon: + icon: } } }) const content = ( -
    +
      {items.map((item) => (
    • *:first-child { + margin-top: 0; +} + .markdownPreview h1, .markdownPreview h2, .markdownPreview h3, @@ -26,52 +31,26 @@ .markdownPreview h5, .markdownPreview h6 { font-weight: 600; - letter-spacing: -0.025em; - margin-top: 1.5rem; - margin-bottom: 0.5rem; } .markdownPreview h1 { - font-size: 1.65rem; - line-height: 2.5rem; - - @media (min-width: 1024px) { - font-size: 3rem; - line-height: 1; - } + font-size: 1.775rem; } .markdownPreview h2 { - padding-bottom: 0.5rem; - font-size: 1.875rem; - line-height: 2.25rem; - font-weight: 600; - border-bottom-width: 1px; - - @media (min-width: 1024px) { - font-size: 2.25rem; - line-height: 1; - } + font-size: 1.5rem; } .markdownPreview h3 { - font-size: 1.5rem; - line-height: 2rem; - - @media (min-width: 1024px) { - font-size: 1.75rem; - line-height: 1; - } + font-size: 1.25rem; } .markdownPreview h4 { - font-size: 1.25rem; - line-height: 1.8rem; + font-size: 1.125rem; } .markdownPreview h5 { - font-size: 1.125rem; - line-height: 1.75rem; + font-size: 1.1rem; } .markdownPreview p { diff --git a/src/app/(drift)/(posts)/new/components/new.tsx b/src/app/(drift)/(posts)/new/components/new.tsx index ae64bb46..270bd08f 100644 --- a/src/app/(drift)/(posts)/new/components/new.tsx +++ b/src/app/(drift)/(posts)/new/components/new.tsx @@ -3,7 +3,6 @@ import { useRouter } from "next/navigation" import { useCallback, useState, ClipboardEvent } from "react" import generateUUID from "@lib/generate-uuid" -import styles from "./post.module.css" import EditDocumentList from "./edit-document-list" import { ChangeEvent } from "react" import getTitleForPostCopy from "src/app/lib/get-title-for-post-copy" @@ -13,7 +12,6 @@ import PasswordModal from "../../../../components/password-modal" import Title from "./title" import FileDropzone from "./drag-and-drop" import { Button, buttonVariants } from "@components/button" -import { Input } from "@components/input" import { useToasts } from "@components/toasts" import { fetchWithUser } from "src/app/lib/fetch-with-user" import dynamic from "next/dynamic" @@ -36,7 +34,7 @@ const DatePicker = dynamic( )} > - Won't expire + Won't expire ) } @@ -66,7 +64,9 @@ function Post({ const [title, setTitle] = useState( getTitleForPostCopy(initialPost?.title) || "" ) - const [description, setDescription] = useState(initialPost?.description || "") + const [description /*, setDescription */] = useState( + initialPost?.description || "" + ) const [expiresAt, setExpiresAt] = useState() const defaultDocs: Document[] = initialPost @@ -149,7 +149,7 @@ function Post({ if (!docs.length) { setToast({ - message: "Please add at least one document", + message: "Please add at least one file", type: "error" }) hasErrored = true @@ -188,13 +188,13 @@ function Post({ setTitle(e.target.value) }, []) - const onChangeDescription = useCallback( - (e: ChangeEvent) => { - e.preventDefault() - setDescription(e.target.value) - }, - [] - ) + // const onChangeDescription = useCallback( + // (e: ChangeEvent) => { + // e.preventDefault() + // setDescription(e.target.value) + // }, + // [] + // ) function onClosePasswordModal() { setPasswordModalVisible(false) @@ -205,10 +205,6 @@ function Post({ return onSubmit("protected", password) } - function onChangeExpiration(date: Date) { - return setExpiresAt(date) - } - function updateDocTitle(i: number) { return (title: string) => { setDocs((docs) => @@ -259,8 +255,8 @@ function Post({ } return ( -
      - + <div className="flex flex-col flex-1 gap-4"> + <Title title={title} onChange={onChangeTitle} className="py-4" /> {/* <Description description={description} onChange={onChangeDescription} /> */} <EditDocumentList onPaste={onPaste} @@ -335,30 +331,30 @@ function Post({ export default Post -function CustomTimeInput({ - date, - value, - onChange -}: { - date: Date - value: string - onChange: (date: string) => void -}) { - return ( - <input - type="time" - value={value} - onChange={(e) => { - if (!isNaN(date.getTime())) { - onChange(e.target.value || date.toISOString().slice(11, 16)) - } - }} - style={{ - backgroundColor: "var(--bg)", - border: "1px solid var(--light-gray)", - borderRadius: "var(--radius)" - }} - required - /> - ) -} +// function CustomTimeInput({ +// date, +// value, +// onChange +// }: { +// date: Date +// value: string +// onChange: (date: string) => void +// }) { +// return ( +// <input +// type="time" +// value={value} +// onChange={(e) => { +// if (!isNaN(date.getTime())) { +// onChange(e.target.value || date.toISOString().slice(11, 16)) +// } +// }} +// style={{ +// backgroundColor: "var(--bg)", +// border: "1px solid var(--light-gray)", +// borderRadius: "var(--radius)" +// }} +// required +// /> +// ) +// } diff --git a/src/app/(drift)/(posts)/new/components/title/index.tsx b/src/app/(drift)/(posts)/new/components/title/index.tsx index cb8779c7..471d26e0 100644 --- a/src/app/(drift)/(posts)/new/components/title/index.tsx +++ b/src/app/(drift)/(posts)/new/components/title/index.tsx @@ -17,11 +17,12 @@ const placeholder = titlePlaceholders[3] type props = { onChange: (e: ChangeEvent<HTMLInputElement>) => void title?: string + className?: string } -function Title({ onChange, title }: props) { +function Title({ onChange, title, className}: props) { return ( - <div className="pt-4"> + <div className={className}> <Input placeholder={placeholder} value={title} diff --git a/src/app/(drift)/(posts)/post/[id]/components/header/post-buttons/index.tsx b/src/app/(drift)/(posts)/post/[id]/components/header/post-buttons/index.tsx index 8e18b308..cef47617 100644 --- a/src/app/(drift)/(posts)/post/[id]/components/header/post-buttons/index.tsx +++ b/src/app/(drift)/(posts)/post/[id]/components/header/post-buttons/index.tsx @@ -3,7 +3,6 @@ import { Button } from "@components/button" import ButtonGroup from "@components/button-group" import FileDropdown from "src/app/(drift)/(posts)/components/file-dropdown" -import { Edit, ArrowUpCircle, Archive } from "react-feather" import styles from "./post-buttons.module.css" import { useRouter } from "next/navigation" import { PostWithFiles } from "@lib/server/prisma" diff --git a/src/app/(drift)/page.tsx b/src/app/(drift)/page.tsx index 7c5343f0..7b57006f 100644 --- a/src/app/(drift)/page.tsx +++ b/src/app/(drift)/page.tsx @@ -73,7 +73,7 @@ async function PublicPostList() { id: true, title: true, content: true, - html: true, + html: true } }, authorId: true diff --git a/src/app/(drift)/settings/components/sections/profile.tsx b/src/app/(drift)/settings/components/sections/profile.tsx index f541b64a..1847cedb 100644 --- a/src/app/(drift)/settings/components/sections/profile.tsx +++ b/src/app/(drift)/settings/components/sections/profile.tsx @@ -9,7 +9,6 @@ import { useEffect, useState } from "react" import styles from "./profile.module.css" import useSWR from "swr" import { User } from "@prisma/client" -import { Spinner } from "@components/spinner" function Profile() { const { session } = useSessionSWR() diff --git a/src/app/components/badges/badge.tsx b/src/app/components/badges/badge.tsx index 87934e06..51052278 100644 --- a/src/app/components/badges/badge.tsx +++ b/src/app/components/badges/badge.tsx @@ -13,7 +13,7 @@ const badgeVariants = cva( "bg-secondary hover:bg-secondary/80 border-transparent text-secondary-foreground", destructive: "bg-destructive hover:bg-destructive/80 border-transparent text-destructive-foreground", - outline: "text-foreground" + outline: "text-foreground", } }, defaultVariants: { diff --git a/src/app/components/badges/expiration-badge/index.tsx b/src/app/components/badges/expiration-badge/index.tsx index 3e894438..4a409282 100644 --- a/src/app/components/badges/expiration-badge/index.tsx +++ b/src/app/components/badges/expiration-badge/index.tsx @@ -36,7 +36,6 @@ const ExpirationBadge = ({ } }, [expirationDate]) - console.log("expirationDate", expirationDate, timeUntilString) if (!expirationDate) { return null } @@ -44,7 +43,7 @@ const ExpirationBadge = ({ const isExpired = expirationDate < new Date() return ( - <Badge variant={isExpired ? "destructive" : "default"}> + <Badge variant={isExpired ? "destructive" : "outline"}> <Tooltip content={`${expirationDate.toLocaleDateString()} ${expirationDate.toLocaleTimeString()}`} > diff --git a/src/app/components/badges/visibility-control/index.tsx b/src/app/components/badges/visibility-control/index.tsx index 9d91fbd6..5ab9b3f0 100644 --- a/src/app/components/badges/visibility-control/index.tsx +++ b/src/app/components/badges/visibility-control/index.tsx @@ -5,7 +5,6 @@ import { useCallback, useState } from "react" import ButtonGroup from "@components/button-group" import { Button } from "@components/button" import { useToasts } from "@components/toasts" -import { Spinner } from "@components/spinner" import { useRouter } from "next/navigation" import { useSessionSWR } from "@lib/use-session-swr" import { fetchWithUser } from "src/app/lib/fetch-with-user" diff --git a/src/app/components/button/index.tsx b/src/app/components/button/index.tsx index e56f75d4..fb76db25 100644 --- a/src/app/components/button/index.tsx +++ b/src/app/components/button/index.tsx @@ -6,11 +6,11 @@ import { cn } from "@lib/cn" import { Spinner } from "@components/spinner" const buttonVariants = cva( - "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background", + "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-75 disabled:pointer-events-none ring-offset-background", { variants: { variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", + default: "bg-primary/80 text-primary-foreground/80 hover:bg-primary/70", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: diff --git a/src/app/components/date-picker.tsx b/src/app/components/date-picker.tsx index ea8ae29b..16418b6d 100644 --- a/src/app/components/date-picker.tsx +++ b/src/app/components/date-picker.tsx @@ -27,7 +27,7 @@ export function DatePicker({ )} > <CalendarIcon className="w-4 h-4 mr-2" /> - {expiresAt ? format(expiresAt, "PPP") : <span>Won't expire</span>} + {expiresAt ? format(expiresAt, "PPP") : <span>Won't expire</span>} </Button> </PopoverTrigger> <PopoverContent className="w-auto p-0"> diff --git a/src/app/components/header/index.tsx b/src/app/components/header/index.tsx index 8562ec0c..e39b9b92 100644 --- a/src/app/components/header/index.tsx +++ b/src/app/components/header/index.tsx @@ -4,10 +4,9 @@ import Link from "next/link" import { cn } from "@lib/cn" import { useSessionSWR } from "@lib/use-session-swr" -import { PropsWithChildren, useEffect, useState } from "react" +import { PropsWithChildren } from "react" import { useSelectedLayoutSegments } from "next/navigation" import Image from "next/image" -import FadeIn from "@components/fade-in" import { useTheme } from "next-themes" // <NavButton diff --git a/src/app/components/link/index.tsx b/src/app/components/link/index.tsx index ace145cd..dba9d134 100644 --- a/src/app/components/link/index.tsx +++ b/src/app/components/link/index.tsx @@ -1,5 +1,4 @@ import NextLink from "next/link" -import styles from "./link.module.css" import { cn } from "@lib/cn" type LinkProps = { diff --git a/src/app/components/password-modal/index.tsx b/src/app/components/password-modal/index.tsx index c60d7006..9cf0f8be 100644 --- a/src/app/components/password-modal/index.tsx +++ b/src/app/components/password-modal/index.tsx @@ -1,7 +1,6 @@ -import { Button } from "@components/button" import { Input } from "@components/input" import Note from "@components/note" -import { useState } from "react" +import { MouseEventHandler, useState } from "react" import styles from "./modal.module.css" import { AlertDialog, @@ -31,7 +30,7 @@ const PasswordModal = ({ const [confirmPassword, setConfirmPassword] = useState<string>("") const [error, setError] = useState<string>() - const onSubmit: React.FormEventHandler<HTMLFormElement> = (e) => { + const onSubmit: MouseEventHandler<HTMLButtonElement> = (e) => { e.preventDefault() if (!password || (creating && !confirmPassword)) { setError("Please enter a password") diff --git a/src/app/components/post-list/home-list-item.tsx b/src/app/components/post-list/home-list-item.tsx index 829789cd..fa23d0a5 100644 --- a/src/app/components/post-list/home-list-item.tsx +++ b/src/app/components/post-list/home-list-item.tsx @@ -2,11 +2,9 @@ import VisibilityBadge from "../badges/visibility-badge" import FadeIn from "@components/fade-in" import ExpirationBadge from "@components/badges/expiration-badge" import CreatedAgoBadge from "@components/badges/created-ago-badge" -import { useRouter } from "next/navigation" import styles from "./list-item.module.css" import Link from "@components/link" import type { PostWithFiles } from "@lib/server/prisma" -import { Tooltip } from "@components/tooltip" import { Badge } from "@components/badges/badge" import { Card, @@ -15,25 +13,8 @@ import { CardHeader, CardTitle } from "@components/card" -import { Button } from "@components/button" -import { - ArrowUpCircle, - Code, - Database, - Edit, - FileText, - MoreVertical, - Terminal, - Trash -} from "react-feather" -import { codeFileExtensions } from "@lib/constants" -import { - DropdownMenu, - DropdownMenuItem, - DropdownMenuTrigger -} from "@components/dropdown-menu" -import { DropdownMenuContent } from "@radix-ui/react-dropdown-menu" import DocumentTabs from "src/app/(drift)/(posts)/components/document-tabs" +import { useEffect, useRef, useState } from "react" // TODO: isOwner should default to false so this can be used generically const HomeListItem = ({ @@ -44,30 +25,23 @@ const HomeListItem = ({ deletePost: () => void hideActions?: boolean }) => { - const router = useRouter() + const [isExpanded, setIsExpanded] = useState(false) + const [isOverflowing, setIsOverflowing] = useState(false) + const containerRef = useRef<HTMLDivElement>(null) - const getIconFromFilename = (filename: string) => { - const extension = filename.split(".").pop() - switch (extension) { - case "sql": - return <Database /> - case "sh": - case "fish": - case "bash": - case "zsh": - case ".zshrc": - case ".bashrc": - case ".bash_profile": - return <Terminal /> - default: - if (codeFileExtensions.includes(extension || "")) { - return <Code /> - } else { - return <FileText /> - } - } + const handleExpandClick = () => { + setIsExpanded(!isExpanded) } + useEffect(() => { + console.log("checking overflow", containerRef.current) + if (!containerRef.current) return + if (containerRef.current.scrollHeight > containerRef.current.clientHeight) { + console.log("overflowing") + setIsOverflowing(true) + } + }, [post]) + return ( <FadeIn key={post.id} as="li"> <Card> @@ -102,13 +76,31 @@ const HomeListItem = ({ )} </CardHeader> <CardContent> - <DocumentTabs - isEditing={false} - staticPreview={post.files[0].html} - defaultTab={"preview"} + <div + className={`overflow-y-hidden ${ + isExpanded ? "max-h-full" : "max-h-64" + }`} + ref={containerRef} > - {post.files[0].content} - </DocumentTabs> + <DocumentTabs + isEditing={false} + staticPreview={post.files[0].html} + defaultTab={"preview"} + > + {post.files[0].content} + </DocumentTabs> + </div> + {isOverflowing && ( + <div className="flex items-center mt-2"> + <hr className="flex-grow border-gray-300 dark:border-gray-700" /> + <div className="inline-block px-2 border border-gray-300 rounded text-accent-foreground dark:border-gray-700"> + <button onClick={handleExpandClick} className="text-sm font-bold transition-colors hover:bg-gray-100 dark:hover:bg-gray-800"> + {isExpanded ? "Collapse" : "Expand"} + </button> + </div> + <hr className="flex-grow border-gray-300 dark:border-gray-700" /> + </div> + )} </CardContent> </Card> </FadeIn> diff --git a/src/app/components/post-list/index.tsx b/src/app/components/post-list/index.tsx index 3e1f996f..fa9fec65 100644 --- a/src/app/components/post-list/index.tsx +++ b/src/app/components/post-list/index.tsx @@ -43,7 +43,6 @@ const PostList = ({ const showSkeleton = skeleton || searching - console.log(initialPosts) // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: address this const onSearch = useCallback( debounce((query: string) => { @@ -88,7 +87,10 @@ const PostList = ({ }) if (!res?.ok) { - console.error(res) + setToast({ + message: "Failed to delete post", + type: "error" + }) return } else { setPosts((posts) => posts?.filter((post) => post.id !== postId)) diff --git a/src/app/components/post-list/list-item.tsx b/src/app/components/post-list/list-item.tsx index 6750a3e8..a49da647 100644 --- a/src/app/components/post-list/list-item.tsx +++ b/src/app/components/post-list/list-item.tsx @@ -6,7 +6,6 @@ import { useRouter } from "next/navigation" import styles from "./list-item.module.css" import Link from "@components/link" import type { PostWithFiles } from "@lib/server/prisma" -import { Tooltip } from "@components/tooltip" import { Badge } from "@components/badges/badge" import { Card, @@ -15,7 +14,6 @@ import { CardHeader, CardTitle } from "@components/card" -import { Button } from "@components/button" import { ArrowUpCircle, Code, diff --git a/src/app/pages/[fileId]/[fileTitle]/page.tsx b/src/app/pages/[fileId]/[fileTitle]/page.tsx index 18b83837..7cad8fe1 100644 --- a/src/app/pages/[fileId]/[fileTitle]/page.tsx +++ b/src/app/pages/[fileId]/[fileTitle]/page.tsx @@ -28,13 +28,14 @@ export default async function FilePage({ } return ( - <> - <h1 style={{ color: "var(--gray)" }}>{file.title}</h1> - <hr /> + <main className="max-w-3xl px-4 mx-auto dark:prose-invert dark:bg-gray-800"> + <h1 className="prose-2xl text-foreground ">{file.title}</h1> + <hr className="my-4 border-foreground" /> <article dangerouslySetInnerHTML={{ __html: file.html.toString("utf-8") }} + className="prose dark:prose-dark" /> - </> + </main> ) } diff --git a/src/app/pages/[fileId]/[fileTitle]/theme-provider.tsx b/src/app/pages/[fileId]/[fileTitle]/theme-provider.tsx index 0ad822fb..46bb2ed5 100644 --- a/src/app/pages/[fileId]/[fileTitle]/theme-provider.tsx +++ b/src/app/pages/[fileId]/[fileTitle]/theme-provider.tsx @@ -7,7 +7,7 @@ export default function ThemeProvider({ children }: PropsWithChildren<unknown>) { return ( - <NextThemesProvider enableSystem defaultTheme="dark"> + <NextThemesProvider enableSystem defaultTheme="dark" attribute="class" enableColorScheme> {children} </NextThemesProvider> ) diff --git a/src/app/styles/globals.css b/src/app/styles/globals.css index dc241017..da62e4b6 100644 --- a/src/app/styles/globals.css +++ b/src/app/styles/globals.css @@ -55,7 +55,7 @@ color-scheme: dark; --background: 0 0% 100%; - --foreground: 222.2 47.4% 11.2%; + --foreground: #fafbfc; --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; diff --git a/tailwind.config.js b/tailwind.config.js index 0377ea1d..ff5ba0c6 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -72,5 +72,5 @@ module.exports = { }, }, }, - plugins: [require("tailwindcss-animate")], + plugins: [require("tailwindcss-animate"), require('@tailwindcss/typography')] } \ No newline at end of file