+
Sign {signText}
@@ -123,28 +125,30 @@ function Auth({
width="100%"
aria-label="Password"
/>
-
Sign {signText}
+
Sign {signText}
>
) : null}
{authProviders?.length ? (
<>
+
+
+ Or sign {signText.toLowerCase()} with one of the following
+
{authProviders?.map((provider) => {
return provider.enabled ? (
{
e.preventDefault()
signIn(provider.id, {
callbackUrl: "/",
registration_password: serverPassword
})
- router.refresh();
+ router.refresh()
}}
+ className="my-2 flex w-full max-w-[250px] items-center justify-center"
>
{getProviderIcon(provider.id)} Sign{" "}
{signText.toLowerCase()} with {provider.public_name}
@@ -182,10 +186,10 @@ export default Auth
const getProviderIcon = (provider: string) => {
switch (provider) {
case "github":
- return
+ return
case "keycloak":
- return
+ return
default:
- return
+ return
}
}
diff --git a/src/app/(drift)/(auth)/signin/page.tsx b/src/app/(drift)/(auth)/signin/page.tsx
index 682ad512..eb09c176 100644
--- a/src/app/(drift)/(auth)/signin/page.tsx
+++ b/src/app/(drift)/(auth)/signin/page.tsx
@@ -2,14 +2,17 @@ import { getMetadata } from "src/app/lib/metadata"
import Auth from "../components"
import { getAuthProviders, isCredentialEnabled } from "@lib/server/auth-props"
+import { PageWrapper } from "@components/page-wrapper"
export default function SignInPage() {
return (
-
+
+
+
)
}
diff --git a/src/app/(drift)/(auth)/signup/page.tsx b/src/app/(drift)/(auth)/signup/page.tsx
index 75efdafa..f076864a 100644
--- a/src/app/(drift)/(auth)/signup/page.tsx
+++ b/src/app/(drift)/(auth)/signup/page.tsx
@@ -2,6 +2,7 @@ import Auth from "../components"
import { getMetadata } from "src/app/lib/metadata"
import { getAuthProviders, isCredentialEnabled } from "@lib/server/auth-props"
import { getRequiresPasscode } from "src/app/api/auth/requires-passcode/route"
+import { PageWrapper } from "@components/page-wrapper"
async function getPasscode() {
return getRequiresPasscode()
@@ -10,12 +11,14 @@ async function getPasscode() {
export default async function SignUpPage() {
const requiresPasscode = await getPasscode()
return (
-
+
+
+
)
}
diff --git a/src/app/(drift)/(posts)/components/file-dropdown/index.tsx b/src/app/(drift)/(posts)/components/file-dropdown/index.tsx
index 022d5a80..d2f2454e 100644
--- a/src/app/(drift)/(posts)/components/file-dropdown/index.tsx
+++ b/src/app/(drift)/(posts)/components/file-dropdown/index.tsx
@@ -1,4 +1,4 @@
-import { Popover } from "@components/popover"
+import { Popover, PopoverContent, PopoverTrigger } from "@components/popover"
import { codeFileExtensions } from "@lib/constants"
import type { PostWithFiles } from "src/lib/server/prisma"
import styles from "./dropdown.module.css"
@@ -18,7 +18,7 @@ function FileDropdown({
if (loading) {
return (
-
-
+
)
}
@@ -71,7 +71,7 @@ function FileDropdown({
return (
-
Jump to {files.length} {files.length === 1 ? "file" : "files"}
-
-
+
+
{content}
-
+
)
}
diff --git a/src/app/(drift)/(posts)/new/components/new.tsx b/src/app/(drift)/(posts)/new/components/new.tsx
index cee5cea1..ae64bb46 100644
--- a/src/app/(drift)/(posts)/new/components/new.tsx
+++ b/src/app/(drift)/(posts)/new/components/new.tsx
@@ -20,11 +20,27 @@ import dynamic from "next/dynamic"
import ButtonDropdown from "@components/button-dropdown"
import clsx from "clsx"
import { Spinner } from "@components/spinner"
-
-const DatePicker = dynamic(() => import("react-datepicker"), {
- ssr: false,
- loading: () =>
-})
+import { cn } from "@lib/cn"
+import { Calendar as CalendarIcon } from "react-feather"
+
+const DatePicker = dynamic(
+ () => import("@components/date-picker").then((m) => m.DatePicker),
+ {
+ ssr: false,
+ loading: () => (
+
+
+ Won't expire
+
+ )
+ }
+)
const emptyDoc = {
title: "",
@@ -273,24 +289,7 @@ function Post({
>
Add a File
-
- }
- placeholderText="Won't expire"
- selected={expiresAt}
- showTimeInput={true}
- // @ts-expect-error fix time input type
- customTimeInput={
}
- timeInputLabel="Time:"
- dateFormat="MM/dd/yyyy h:mm aa"
- clearButtonTitle={"Clear"}
- // TODO: investigate why this causes margin shift if true
- enableTabLoop={false}
- minDate={new Date()}
- className="max-w-[200px] flex-1"
- />
+
{
return (
// TODO: investigate tooltip not showing
-
+
{" "}
<>{time}>
diff --git a/src/app/components/calendar.tsx b/src/app/components/calendar.tsx
new file mode 100644
index 00000000..3b4dae61
--- /dev/null
+++ b/src/app/components/calendar.tsx
@@ -0,0 +1,64 @@
+"use client"
+
+import * as React from "react"
+import { ChevronLeft, ChevronRight } from "react-feather"
+import { DayPicker } from "react-day-picker"
+
+import { cn } from "@lib/cn"
+import { buttonVariants } from "@components/button"
+
+export type CalendarProps = React.ComponentProps
+
+function Calendar({
+ className,
+ classNames,
+ showOutsideDays = true,
+ ...props
+}: CalendarProps) {
+ return (
+ ,
+ IconRight: ({}) =>
+ }}
+ {...props}
+ />
+ )
+}
+Calendar.displayName = "Calendar"
+
+export { Calendar }
diff --git a/src/app/components/date-picker.tsx b/src/app/components/date-picker.tsx
new file mode 100644
index 00000000..ea8ae29b
--- /dev/null
+++ b/src/app/components/date-picker.tsx
@@ -0,0 +1,46 @@
+"use client"
+
+import * as React from "react"
+import { format } from "date-fns"
+import { Calendar as CalendarIcon } from "react-feather"
+
+import { cn } from "@lib/cn"
+import { Button } from "@components/button"
+import { Calendar } from "@components/calendar"
+import { Popover, PopoverContent, PopoverTrigger } from "@components/popover"
+
+export function DatePicker({
+ expiresAt,
+ setExpiresAt
+}: {
+ expiresAt?: Date
+ setExpiresAt: React.Dispatch>
+}) {
+ return (
+
+
+
+
+ {expiresAt ? format(expiresAt, "PPP") : Won't expire }
+
+
+
+ {
+ setExpiresAt(date)
+ }}
+ initialFocus
+ fromDate={new Date()}
+ />
+
+
+ )
+}
diff --git a/src/app/components/header/index.tsx b/src/app/components/header/index.tsx
index 7d212a2e..8562ec0c 100644
--- a/src/app/components/header/index.tsx
+++ b/src/app/components/header/index.tsx
@@ -115,6 +115,13 @@ export default function Header() {
Settings
+
+ Theme
+
{isAdmin && Admin }
{isAuthenticated !== undefined && (
<>
@@ -124,13 +131,6 @@ export default function Header() {
{isAuthenticated === false && (
Sign In
)}
-
- {resolvedTheme === "dark" ? "Light" : "Dark"}
-
>
)}
@@ -149,7 +149,7 @@ function NavLink({ href, disabled, children }: NavLinkProps) {
const baseClasses =
"text-sm text-muted-foreground font-medium transition-colors hover:text-primary"
const activeClasses = "text-primary border-primary"
- const disabledClasses = "text-gray-400 hover:text-gray-400 cursor-default"
+ const disabledClasses = "text-gray-600 hover:text-gray-400 cursor-not-allowed"
const segments = useSelectedLayoutSegments()
const activeSegment = segments[segments.length - 1]
diff --git a/src/app/components/input/index.tsx b/src/app/components/input/index.tsx
index d8896018..8ed85003 100644
--- a/src/app/components/input/index.tsx
+++ b/src/app/components/input/index.tsx
@@ -11,12 +11,12 @@ const Input = React.forwardRef(
({ className, type, label, hideLabel, ...props }, ref) => {
const id = React.useId()
return (
-
+
{label && !hideLabel ? (
-const Link = ({ colored, children, ...props }: LinkProps) => {
- const className = colored ? `${styles.link} ${styles.color}` : styles.link
+const Link = ({ colored, className, children, ...props }: LinkProps) => {
+ const classes = colored ? "text-blue-500 no-underline" : "no-underline"
return (
-
+
{children}
)
diff --git a/src/app/components/popover/index.tsx b/src/app/components/popover/index.tsx
index 7f7f2f90..a8999b5a 100644
--- a/src/app/components/popover/index.tsx
+++ b/src/app/components/popover/index.tsx
@@ -1,35 +1,31 @@
-// largely from https://github.com/shadcn/taxonomy
-
+"use client"
+
import * as React from "react"
import * as PopoverPrimitive from "@radix-ui/react-popover"
-import clsx from "clsx"
-import styles from "./popover.module.css"
-
-type PopoverProps = PopoverPrimitive.PopoverProps
-
-export function Popover({ ...props }: PopoverProps) {
- return
-}
-
-Popover.Trigger = React.forwardRef<
- HTMLButtonElement,
- PopoverPrimitive.PopoverTriggerProps
->(function PopoverTrigger({ ...props }, ref) {
- return
-})
-
-Popover.Portal = PopoverPrimitive.Portal
-
-Popover.Content = React.forwardRef<
- HTMLDivElement,
- PopoverPrimitive.PopoverContentProps
->(function PopoverContent({ className, ...props }, ref) {
- return (
-
- )
-})
+
+import { cn } from "@lib/cn"
+
+const Popover = PopoverPrimitive.Root
+
+const PopoverTrigger = PopoverPrimitive.Trigger
+
+const PopoverContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
+
+
+
+))
+PopoverContent.displayName = PopoverPrimitive.Content.displayName
+
+export { Popover, PopoverTrigger, PopoverContent }
diff --git a/src/app/components/post-list/index.tsx b/src/app/components/post-list/index.tsx
index 3d1581f9..2c27d8c6 100644
--- a/src/app/components/post-list/index.tsx
+++ b/src/app/components/post-list/index.tsx
@@ -98,12 +98,12 @@ const PostList = ({
return (
- {!hideSearch && posts.length > 0 && (
+ {!hideSearch && (
["files"][0]) => {
return (
-
+
{getIconFromFilename(file.title)}
{file.title || "Untitled file"}
diff --git a/src/app/components/skeleton/index.tsx b/src/app/components/skeleton/index.tsx
index 3a2a87c6..e792f5ec 100644
--- a/src/app/components/skeleton/index.tsx
+++ b/src/app/components/skeleton/index.tsx
@@ -1,4 +1,4 @@
-import styles from "./skeleton.module.css"
+import { cn } from "@lib/cn"
export default function Skeleton({
width = 100,
@@ -13,8 +13,13 @@ export default function Skeleton({
}) {
return (
)
}
diff --git a/src/app/components/skeleton/skeleton.module.css b/src/app/components/skeleton/skeleton.module.css
deleted file mode 100644
index d86eb857..00000000
--- a/src/app/components/skeleton/skeleton.module.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.skeleton {
- background-color: var(--lighter-gray);
- border-radius: var(--radius);
-}
diff --git a/src/app/lib/fetch-with-user.ts b/src/app/lib/fetch-with-user.ts
index a70280f7..ee207df0 100644
--- a/src/app/lib/fetch-with-user.ts
+++ b/src/app/lib/fetch-with-user.ts
@@ -1,13 +1,13 @@
import { getSession } from "next-auth/react"
-const protocol = process.env.NODE_ENV === "development" ? "http://" : "https://"
+// const protocol = process.env.NODE_ENV === "development" ? "http://" : "https://"
/**
* a fetch wrapper that adds `userId={userId}` to the query string
*/
export async function fetchWithUser(url: string, options: RequestInit = {}) {
// TODO: figure out if this extra network call hurts performance
const session = await getSession()
- const newUrl = new URL(url, `${protocol}${process.env.NEXT_PUBLIC_DRIFT_URL}`)
+ const newUrl = new URL(url, `${process.env.NEXT_PUBLIC_DRIFT_URL}`)
newUrl.searchParams.append("userId", session?.user.id || "")
return fetch(newUrl.toString(), options)
}
diff --git a/src/app/pages/[fileId]/[fileTitle]/layout.tsx b/src/app/pages/[fileId]/[fileTitle]/layout.tsx
index 3af56aa1..073af03f 100644
--- a/src/app/pages/[fileId]/[fileTitle]/layout.tsx
+++ b/src/app/pages/[fileId]/[fileTitle]/layout.tsx
@@ -1,5 +1,4 @@
import "@styles/globals.css"
-import "@styles/markdown.css"
import Layout from "@components/layout"
import { Inter } from "next/font/google"
diff --git a/src/app/styles/globals.css b/src/app/styles/globals.css
index 84d47787..dc241017 100644
--- a/src/app/styles/globals.css
+++ b/src/app/styles/globals.css
@@ -12,7 +12,7 @@
--small-gap: 4rem;
--big-gap: 4rem;
- --main-content: 55rem;
+ --main-content: min(55rem, 100vw);
--radius: 8px;
--inline-radius: 5px;
diff --git a/src/app/styles/markdown.css b/src/app/styles/markdown.css
index b17f31da..28273fd6 100644
--- a/src/app/styles/markdown.css
+++ b/src/app/styles/markdown.css
@@ -49,7 +49,7 @@ article ul li.reset .check {
/* Checkbox */
-input[type="checkbox"] {
+article input[type="checkbox"] {
vertical-align: middle;
appearance: none;
display: inline-block;
@@ -64,7 +64,7 @@ input[type="checkbox"] {
border-radius: 3px;
}
-input[type="checkbox"]:checked {
+article input[type="checkbox"]:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='black' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M5.707 7.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0-1.414-1.414L7 8.586 5.707 7.293z'/%3e%3c/svg%3e");
border-color: transparent;
background-color: currentColor;
@@ -73,18 +73,18 @@ input[type="checkbox"]:checked {
background-repeat: no-repeat;
}
-html[data-theme="light"] input[type="checkbox"]:checked {
+html[data-theme="light"] article input[type="checkbox"]:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M5.707 7.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0-1.414-1.414L7 8.586 5.707 7.293z'/%3e%3c/svg%3e");
}
-input[type="checkbox"]:focus {
+article input[type="checkbox"]:focus {
outline: none;
border-color: var(--fg);
}
/* Code Snippets */
-.token-line:not(:last-child) {
+article .token-line:not(:last-child) {
min-height: 1.4rem;
}
@@ -107,16 +107,16 @@ article pre {
background-color: var(--lighter-gray);
}
-table {
+article table {
border-collapse: collapse;
}
-table th {
+article table th {
font-weight: 500;
}
-table th,
-table td {
+article table th,
+article table td {
padding: 0.35rem 0.75rem;
border: 1px solid var(--light-gray);
}
diff --git a/tailwind.config.js b/tailwind.config.js
index d28cf26e..0377ea1d 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,76 +1,76 @@
-const { fontFamily } = require("tailwindcss/defaultTheme")
-
/** @type {import('tailwindcss').Config} */
module.exports = {
- darkMode: ["class"],
- content: ["src/app/**/*.{ts,tsx}"],
- theme: {
- container: {
- center: true,
- padding: "2rem",
- screens: {
- "2xl": "1400px"
- }
- },
- extend: {
- colors: {
- border: "hsl(var(--border))",
- input: "hsl(var(--input))",
- ring: "hsl(var(--ring))",
- background: "hsl(var(--background))",
- foreground: "hsl(var(--foreground))",
- primary: {
- DEFAULT: "hsl(var(--primary))",
- foreground: "hsl(var(--primary-foreground))"
- },
- secondary: {
- DEFAULT: "hsl(var(--secondary))",
- foreground: "hsl(var(--secondary-foreground))"
- },
- destructive: {
- DEFAULT: "hsl(var(--destructive))",
- foreground: "hsl(var(--destructive-foreground))"
- },
- muted: {
- DEFAULT: "hsl(var(--muted))",
- foreground: "hsl(var(--muted-foreground))"
- },
- accent: {
- DEFAULT: "hsl(var(--accent))",
- foreground: "hsl(var(--accent-foreground))"
- },
- popover: {
- DEFAULT: "hsl(var(--popover))",
- foreground: "hsl(var(--popover-foreground))"
- },
- card: {
- DEFAULT: "hsl(var(--card))",
- foreground: "hsl(var(--card-foreground))"
- }
- },
- borderRadius: {
- lg: `var(--radius)`,
- md: `calc(var(--radius) - 2px)`,
- sm: "calc(var(--radius) - 4px)"
- },
- fontFamily: {
- sans: ["var(--font-sans)", ...fontFamily.sans]
- },
- keyframes: {
- "accordion-down": {
- from: { height: 0 },
- to: { height: "var(--radix-accordion-content-height)" }
- },
- "accordion-up": {
- from: { height: "var(--radix-accordion-content-height)" },
- to: { height: 0 }
- }
- },
- animation: {
- "accordion-down": "accordion-down 0.2s ease-out",
- "accordion-up": "accordion-up 0.2s ease-out"
- }
- }
- },
- plugins: [require("tailwindcss-animate")]
-}
+ darkMode: ["class"],
+ content: [
+ './pages/**/*.{ts,tsx}',
+ './components/**/*.{ts,tsx}',
+ './app/**/*.{ts,tsx}',
+ './src/**/*.{ts,tsx}',
+ ],
+ theme: {
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
+ },
+ extend: {
+ colors: {
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
+ primary: {
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))",
+ },
+ },
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ keyframes: {
+ "accordion-down": {
+ from: { height: 0 },
+ to: { height: "var(--radix-accordion-content-height)" },
+ },
+ "accordion-up": {
+ from: { height: "var(--radix-accordion-content-height)" },
+ to: { height: 0 },
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ },
+ },
+ },
+ plugins: [require("tailwindcss-animate")],
+}
\ No newline at end of file