implement bookmark delete

This commit is contained in:
2025-05-07 15:47:08 +01:00
parent 30cc4d3fb5
commit e87a6586b6
26 changed files with 763 additions and 149 deletions

View File

@@ -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}

View 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 }

View 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 }