SPB Git
2.7 KB · 21 lines tsx
1import Link from "next/link";2export function Field({ label, name, value, type = "text", hint, required, rows, className = "" }: { label: string; name: string; value?: string | number | null; type?: string; hint?: string; required?: boolean; rows?: number; className?: string }) {3  return (<label className={`block text-sm ${className}`}><span className="label">{label}{required ? " *" : ""}</span>4    {rows ? <textarea name={name} defaultValue={value ?? ""} rows={rows} className="input mt-1 font-mono text-xs" /> : <input type={type} name={name} defaultValue={value ?? ""} required={required} className="input mt-1" />}5    {hint && <span className="block text-xs text-fg-3 mt-1">{hint}</span>}</label>);6}7export function Select({ label, name, value, options, hint }: { label: string; name: string; value?: string | number | null; options: { v: string | number; label: string }[]; hint?: string }) {8  return (<label className="block text-sm"><span className="label">{label}</span><select name={name} defaultValue={value ?? ""} className="input mt-1">{options.map((o) => <option key={o.v} value={o.v}>{o.label}</option>)}</select>{hint && <span className="block text-xs text-fg-3 mt-1">{hint}</span>}</label>);9}10export function Check({ label, name, checked }: { label: string; name: string; checked?: boolean }) { return <label className="flex items-center gap-2 text-sm"><input type="checkbox" name={name} defaultChecked={checked} className="accent-[var(--navy)]" />{label}</label>; }11export function Csrf({ token }: { token: string }) { return <input type="hidden" name="_csrf" value={token} />; }12export function Notice({ sp }: { sp: Record<string, string | string[] | undefined> }) {13  if (sp.saved) return <p className="card p-3 mb-4 text-sm text-ok border-ok">Saved.</p>;14  if (sp.queued) return <p className="card p-3 mb-4 text-sm text-ok border-ok">Queued — the worker will process it shortly.</p>;15  if (sp.deleted) return <p className="card p-3 mb-4 text-sm text-ok border-ok">Deleted.</p>;16  if (sp.error) return <p className="card p-3 mb-4 text-sm text-bad border-bad">{String(sp.error)}</p>;17  return null;18}19export function PageTitle({ title, children }: { title: string; children?: React.ReactNode }) { return <div className="flex flex-wrap items-center gap-3 mb-6"><h1 className="text-2xl sm:text-3xl">{title}</h1><div className="ml-auto flex gap-2">{children}</div></div>; }20export function Tabs({ items, current }: { items: [string, string][]; current: string }) { return <nav className="flex flex-wrap gap-1 border-b border-line mb-6 text-sm">{items.map(([h, l]) => <Link key={h} href={h} className={`px-3 py-2 -mb-px border-b-2 no-underline ${current === h ? "border-navy text-navy" : "border-transparent text-fg-2 hover:text-fg"}`}>{l}</Link>)}</nav>; }21
Files · main
Menu

Theme