use custom input/buttons on postlist/new page

This commit is contained in:
Max Leiter 2022-11-15 22:52:25 -08:00
parent dfe0d39fa0
commit 45c2e59105
16 changed files with 99 additions and 74 deletions

View file

@ -5,7 +5,7 @@ import { Note, Text } from "@geist-ui/core/dist"
export default function ExpiredPage() {
return (
<Note type="error" label={false}>
<Text h4>Error: The Drift you&apos;re trying to view has expired.</Text>
<h2>Error: The Drift you&apos;re trying to view has expired.</h2>
</Note>
)
}

View file

@ -1,4 +1,4 @@
import { Text, useMediaQuery, useTheme, useToasts } from "@geist-ui/core/dist"
import { useMediaQuery, useTheme, useToasts } from "@geist-ui/core/dist"
import { useDropzone } from "react-dropzone"
import styles from "./drag-and-drop.module.css"
import generateUUID from "@lib/generate-uuid"
@ -79,7 +79,7 @@ function FileDropzone({ setDocs }: { setDocs: (docs: Document[]) => void }) {
<ul>
{errors.map((e) => (
<li key={e.code}>
<Text>{e.message}</Text>
{e.message}
</li>
))}
</ul>
@ -100,12 +100,12 @@ function FileDropzone({ setDocs }: { setDocs: (docs: Document[]) => void }) {
{!isDragActive && (
<p style={{color: "var(--gray)"}}>Drag some files here, or {verb} to select files</p>
)}
{isDragActive && <Text p>Release to drop the files here</Text>}
{isDragActive && <p>Release to drop the files here</p>}
</div>
{fileRejections.length > 0 && (
<ul className={styles.error}>
{/* <Button style={{ float: 'right' }} type="abort" onClick={() => fileRejections.splice(0, fileRejections.length)} auto iconRight={<XCircle />}></Button> */}
<Text h5>There was a problem with one or more of your files.</Text>
<p>There was a problem with one or more of your files.</p>
{fileRejectionItems}
</ul>
)}

View file

@ -37,6 +37,7 @@
.actionWrapper .actions {
position: absolute;
right: 0;
top: 4px;
}
@media (max-width: 768px) {

View file

@ -7,9 +7,10 @@ import List from "@geist-ui/icons/list"
import ImageIcon from "@geist-ui/icons/image"
import { RefObject, useMemo } from "react"
import styles from "../document.module.css"
import { Button, ButtonGroup } from "@geist-ui/core/dist"
import { TextareaMarkdownRef } from "textarea-markdown-editor"
import Tooltip from "@components/tooltip"
import Button from "@components/button"
import ButtonGroup from "@components/button-group"
// TODO: clean up
@ -69,11 +70,8 @@ const FormattingIcons = ({
key={name}
>
<Button
auto
scale={2 / 3}
px={0.6}
aria-label={name}
icon={icon}
iconRight={icon}
onMouseDown={(e) => e.preventDefault()}
onClick={action}
/>

View file

@ -11,8 +11,9 @@ import Trash from "@geist-ui/icons/trash"
import FormattingIcons from "./formatting-icons"
import TextareaMarkdown, { TextareaMarkdownRef } from "textarea-markdown-editor"
import { Button, Input, Spacer, Tabs, Textarea } from "@geist-ui/core/dist"
import { Input, Tabs, Textarea } from "@geist-ui/core/dist"
import Preview from "../../../../components/preview"
import Button from "@components/button"
// import Link from "next/link"
type Props = {
@ -103,12 +104,11 @@ const Document = ({
/>
{remove && (
<Button
type="abort"
ghost
icon={<Trash />}
auto
iconLeft={<Trash />}
height={"36px"}
width={"36px"}
width={"48px"}
padding={0}
margin={0}
onClick={() => removeFile(remove)}
/>
)}

View file

@ -1,6 +1,6 @@
"use client"
import { Button, useToasts, Input, ButtonDropdown } from "@geist-ui/core/dist"
import { useToasts, Input, ButtonDropdown } from "@geist-ui/core/dist"
import { useRouter } from "next/navigation"
import { useCallback, useState } from "react"
import generateUUID from "@lib/generate-uuid"
@ -14,6 +14,7 @@ import { PostWithFiles } from "@lib/server/prisma"
import PasswordModal from "../../../components/password-modal"
import Title from "./title"
import FileDropzone from "./drag-and-drop"
import Button from "@components/button"
const emptyDoc = {
title: "",
content: "",
@ -162,13 +163,11 @@ const Post = ({
const onChangeExpiration = (date: Date) => setExpiresAt(date)
const onChangeTitle =
(e: ChangeEvent<HTMLInputElement>) => {
const onChangeTitle = (e: ChangeEvent<HTMLInputElement>) => {
setTitle(e.target.value)
}
const onChangeDescription =
(e: ChangeEvent<HTMLInputElement>) => {
const onChangeDescription = (e: ChangeEvent<HTMLInputElement>) => {
setDescription(e.target.value)
}
@ -278,6 +277,9 @@ const Post = ({
])
}}
type="default"
style={{
flex: 1
}}
>
Add a File
</Button>

View file

@ -0,0 +1,13 @@
.button-group {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: stretch;
align-content: stretch;
}
.button-group > * {
flex: 1 1 auto;
margin: 0;
}

View file

@ -0,0 +1,14 @@
import styles from "./button-group.module.css"
export default function ButtonGroup({
children,
...props
}: {
children: React.ReactNode | React.ReactNode[]
} & React.HTMLAttributes<HTMLDivElement>) {
return (
<div className={styles["button-group"]} {...props}>
{children}
</div>
)
}

View file

@ -9,14 +9,14 @@
border-radius: var(--radius);
border: 1px solid var(--border);
padding: var(--gap-half) var(--gap);
color: var(--darker-gray);
}
.button:hover,
.button:focus {
outline: none;
color: var(--hover);
background: var(--hover-bg);
border: var(--);
border: 1px solid var(--darker-gray);
}
.button[disabled] {

View file

@ -2,12 +2,16 @@ import styles from "./button.module.css"
import { forwardRef, Ref } from "react"
type Props = React.HTMLProps<HTMLButtonElement> & {
children: React.ReactNode
children?: React.ReactNode
buttonType?: "primary" | "secondary"
className?: string
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void
iconRight?: React.ReactNode
iconLeft?: React.ReactNode
height?: string | number
width?: string | number
padding?: string | number
margin?: string | number
}
// eslint-disable-next-line react/display-name
@ -22,6 +26,10 @@ const Button = forwardRef<HTMLButtonElement, Props>(
disabled = false,
iconRight,
iconLeft,
height,
width,
padding,
margin,
...props
},
ref
@ -32,15 +40,16 @@ const Button = forwardRef<HTMLButtonElement, Props>(
className={`${styles.button} ${styles[type]} ${className || ""}`}
disabled={disabled}
onClick={onClick}
style={{ height, width, margin, padding }}
{...props}
>
{iconLeft && (
{children && iconLeft && (
<span className={`${styles.icon} ${styles.iconLeft}`}>
{iconLeft}
</span>
)}
{children}
{iconRight && (
{children ? children : <span className={`${styles.icon}`}>{iconLeft || iconRight}</span>}
{children && iconRight && (
<span className={`${styles.icon} ${styles.iconRight}`}>
{iconRight}
</span>

View file

@ -18,18 +18,16 @@
background: var(--bg);
}
.tabs .buttons > a:hover,
.tabs .buttons > button:hover {
color: var(--fg);
box-shadow: inset 0 -1px 0 var(--fg);
transition: box-shadow 0.2s ease-in-out;
.tabs button,
.tabs a {
color: var(--darker-gray);
transition: color, box-shadow 0.2s ease-in-out;
}
.tabs a:active,
.tabs a:focus,
.tabs button:active,
.tabs button:focus {
color: var(--darker-gray);
.tabs .buttons a:hover,
.tabs .buttons button:hover {
color: var(--fg);
box-shadow: inset 0 -1px 0 var(--fg);
}
.mobile {

View file

@ -2,7 +2,6 @@
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
height: 100%;
font-size: 1rem;
}
@ -55,3 +54,9 @@
margin-bottom: var(--gap);
}
}
.input:disabled {
background-color: var(--lighter-gray);
color: var(--fg);
cursor: not-allowed;
}

View file

@ -1,7 +1,5 @@
"use client"
import { Button, Input, Text } from "@geist-ui/core/dist"
import styles from "./post-list.module.css"
import ListItemSkeleton from "./list-item-skeleton"
import ListItem from "./list-item"
@ -9,6 +7,8 @@ import { ChangeEvent, useCallback, useEffect, useState } from "react"
import useDebounce from "@lib/hooks/use-debounce"
import Link from "@components/link"
import type { PostWithFiles } from "@lib/server/prisma"
import Input from "@components/input"
import Button from "@components/button"
type Props = {
initialPosts: string | PostWithFiles[]
@ -106,13 +106,13 @@ const PostList = ({
<div className={styles.container}>
<div className={styles.searchContainer}>
<Input
scale={3 / 2}
placeholder="Search..."
onChange={handleSearchChange}
disabled={Boolean(!posts?.length)}
style={{ maxWidth: 300 }}
/>
</div>
{!posts && <Text type="error">Failed to load.</Text>}
{!posts && <p style={{color: 'var(--warning)'}}>Failed to load.</p>}
{!posts?.length && searching && (
<ul>
<li>
@ -124,13 +124,13 @@ const PostList = ({
</ul>
)}
{posts?.length === 0 && posts && (
<Text type="secondary">
<p>
No posts found. Create one{" "}
<Link colored href="/new">
here
</Link>
.
</Text>
</p>
)}
{posts?.length > 0 && (
<div>

View file

@ -1,5 +1,4 @@
import VisibilityBadge from "../badges/visibility-badge"
import { Divider, Button } from "@geist-ui/core/dist"
import FadeIn from "@components/fade-in"
import Trash from "@geist-ui/icons/trash"
import ExpirationBadge from "@components/badges/expiration-badge"
@ -14,6 +13,7 @@ import type { File } from "@lib/server/prisma"
import Tooltip from "@components/tooltip"
import Badge from "@components/badges/badge"
import Card from "@components/card"
import Button from "@components/button"
// TODO: isOwner should default to false so this can be used generically
const ListItem = ({
@ -41,7 +41,7 @@ const ListItem = ({
<Card style={{ overflowY: "scroll" }}>
<>
<div className={styles.title}>
<h3 style={{ display: "inline-block" }}>
<h3 style={{ display: "inline-block", margin: 0 }}>
<Link
colored
style={{ marginRight: "var(--gap)" }}
@ -55,17 +55,17 @@ const ListItem = ({
{post.parentId && (
<Tooltip content={"View parent"}>
<Button
auto
icon={<Parent />}
iconRight={<Parent />}
onClick={viewParentClick}
height={38}
/>
</Tooltip>
)}
<Tooltip content={"Make a copy"}>
<Button auto iconRight={<Edit />} onClick={editACopy} />
<Button iconRight={<Edit />} onClick={editACopy} height={38} />
</Tooltip>
<Tooltip content={"Delete"}>
<Button iconRight={<Trash />} onClick={deletePost} auto />
<Button iconRight={<Trash />} onClick={deletePost} height={38} />
</Tooltip>
</span>
)}
@ -86,7 +86,7 @@ const ListItem = ({
<ExpirationBadge postExpirationDate={post.expiresAt} />
</div>
</>
<Divider h="1px" my={2} />
<hr />
<>
{post?.files?.map((file: File) => {
return (

View file

@ -27,7 +27,6 @@
"jest": "^29.3.1",
"next": "13.0.3",
"next-auth": "^4.16.4",
"next-themes": "^0.2.1",
"rc-table": "7.24.1",
"react": "18.2.0",
"react-datepicker": "4.8.0",

View file

@ -25,7 +25,6 @@ specifiers:
katex: ^0.16.3
next: 13.0.3
next-auth: ^4.16.4
next-themes: ^0.2.1
next-unused: 0.0.6
prettier: 2.6.2
prisma: ^4.6.1
@ -58,7 +57,6 @@ dependencies:
jest: 29.3.1_@types+node@17.0.23
next: 13.0.3_biqbaboplfbrettd7655fr4n2y
next-auth: 4.16.4_ogpkrxaz2lg6nectum6dl66tn4
next-themes: 0.2.1_ogpkrxaz2lg6nectum6dl66tn4
rc-table: 7.24.1_biqbaboplfbrettd7655fr4n2y
react: 18.2.0
react-datepicker: 4.8.0_biqbaboplfbrettd7655fr4n2y
@ -5117,18 +5115,6 @@ packages:
uuid: 8.3.2
dev: false
/next-themes/0.2.1_ogpkrxaz2lg6nectum6dl66tn4:
resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==}
peerDependencies:
next: '*'
react: '*'
react-dom: '*'
dependencies:
next: 13.0.3_biqbaboplfbrettd7655fr4n2y
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
dev: false
/next-unused/0.0.6:
resolution: {integrity: sha512-dHFNNBanFq4wvYrULtsjfWyZ6BzOnr5VYI9EYMGAZYF2vkAhFpj2JOuT5Wu2o3LbFSG92PmAZnSUF/LstF82pA==}
hasBin: true