implement bookmark delete
This commit is contained in:
@@ -1,13 +1,27 @@
|
||||
import clsx from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
const VARIANT_CLASSES = {
|
||||
light:
|
||||
"px-4 py-2 md:py-0 font-bold border border-2 border-b-4 border-stone-200 enabled:active:bg-stone-200 enabled:active:text-stone-800 enabled:active:border-b-1 enabled:hover:bg-stone-600 focus:bg-stone-600 focus:ring-0 focus:outline-none enabled:active:translate-y-0.5",
|
||||
normal:
|
||||
"px-4 py-2 md:py-0 font-bold border border-2 border-b-4 border-stone-800 dark:border-stone-200 enabled:active:bg-stone-800 dark:enabled:active:bg-stone-200 enabled:active:text-stone-200 dark:enabled:active:text-stone-800 enabled:active:border-b-1 enabled:hover:bg-stone-400 dark:enabled:hover:bg-stone-600 focus:bg-stone-400 dark:focus:bg-stone-600 focus:ring-0 focus:outline-none enabled:active:translate-y-0.5",
|
||||
} as const
|
||||
|
||||
function Button({
|
||||
className,
|
||||
variant = "normal",
|
||||
disabled,
|
||||
...props
|
||||
}: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>) {
|
||||
}: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> & {
|
||||
variant?: keyof typeof VARIANT_CLASSES
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
className={clsx(
|
||||
"px-4 font-bold border border-2 border-b-4 border-text-inherit active:bg-stone-700 active:text-stone-200 active:border-b-1 active:translate-y-0.5",
|
||||
disabled={disabled}
|
||||
className={twMerge(
|
||||
VARIANT_CLASSES[variant],
|
||||
"disabled:text-stone-500 disabled:cursor-not-allowed",
|
||||
disabled ? "stripes" : "",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
23
packages/web/src/components/dialog.tsx
Normal file
23
packages/web/src/components/dialog.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
function Dialog({ children }: React.PropsWithChildren) {
|
||||
return (
|
||||
<div className="fixed z-20 top-0 bottom-0 left-0 right-0 flex items-center justify-center bg-stone-200">
|
||||
<div className="w-full m-8 md:w-2/3 lg:w-1/3 flex flex-col items-center border-2 bg-stone-300 relative after:absolute after:-z-10 after:inset-0 after:bg-stone-400 after:translate-4 md:after:translate-8">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function DialogTitle({ children }: React.PropsWithChildren) {
|
||||
return <h2 className="select-none font-bold w-full bg-stone-800 text-stone-300 text-center">{children}</h2>
|
||||
}
|
||||
|
||||
function DialogBody({ children }: React.PropsWithChildren) {
|
||||
return <div className="m-8 text-center">{children}</div>
|
||||
}
|
||||
|
||||
function DialogActionRow({ children }: React.PropsWithChildren) {
|
||||
return <div className="flex flex-row space-x-4 mb-8">{children}</div>
|
||||
}
|
||||
|
||||
export { Dialog, DialogTitle, DialogBody, DialogActionRow }
|
32
packages/web/src/components/form-field.tsx
Normal file
32
packages/web/src/components/form-field.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { clsx } from "clsx"
|
||||
import { useId } from "react"
|
||||
|
||||
interface FormFieldProps {
|
||||
name: string
|
||||
label: string
|
||||
type: React.HTMLInputTypeAttribute
|
||||
className?: string
|
||||
}
|
||||
|
||||
function FormField({ name, label, type, className }: FormFieldProps) {
|
||||
const id = useId()
|
||||
return (
|
||||
<div className={clsx("flex flex-col-reverse focus:text-teal-600", className)}>
|
||||
<input
|
||||
id={id}
|
||||
name={name}
|
||||
type={type}
|
||||
defaultValue=""
|
||||
className="peer px-3 pb-2 pt-3 border focus:border-2 border-stone-800 focus:border-teal-600 focus:ring-0 focus:outline-none"
|
||||
/>
|
||||
<label
|
||||
htmlFor={id}
|
||||
className="select-none border-x-2 border-transparent w-min translate-y-[55%] bg-stone-200 mx-2 px-1 peer-focus:text-teal-600 peer-focus:font-bold"
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export { FormField }
|
Reference in New Issue
Block a user