All Taste components
Forms
Billing details form
A two-column billing form with GSTIN and address that folds to one column on narrow screens.
2 columns · 1 column when narrow · optional fields · phone prefix
import { cn } from "@/lib/utils";
const input =
"h-9 w-full rounded border border-border-strong bg-bg px-3 text-sm text-fg outline-none transition placeholder:text-fg-subtle focus:border-primary focus:ring-[3px] focus:ring-primary/20";
function Field({ label, optional, help, className, children }:
{ label: string; optional?: boolean; help?: string; className?: string; children: React.ReactNode }) {
return (
<label className={cn("grid gap-1.5", className)}>
<span className="text-[13px] font-medium text-fg">
{label} {optional && <span className="font-normal text-fg-subtle">(optional)</span>}
</span>
{children}
{help && <span className="text-xs text-fg-subtle">{help}</span>}
</label>
);
}
export function BillingDetailsForm({ onSubmit }: { onSubmit: (data: FormData) => void }) {
return (
<form
onSubmit={(e) => { e.preventDefault(); onSubmit(new FormData(e.currentTarget)); }}
className="w-full max-w-[640px] rounded-lg border border-border bg-bg p-5"
>
<div className="mb-5">
<h3 className="text-base font-medium tracking-tight text-fg">Billing details</h3>
<p className="mt-0.5 text-[13px] text-fg-subtle">These appear on every invoice we send you.</p>
</div>
<div className="grid grid-cols-1 gap-x-3 gap-y-4 sm:grid-cols-2">
<Field label="Full name"><input name="name" required autoComplete="name" className={input} /></Field>
<Field label="Company" optional><input name="company" autoComplete="organization" className={input} /></Field>
<Field label="Email"><input name="email" type="email" required autoComplete="email" className={input} /></Field>
<Field label="Phone">
<span className="flex h-9 overflow-hidden rounded border border-border-strong bg-bg transition focus-within:border-primary focus-within:ring-[3px] focus-within:ring-primary/20">
<span className="flex items-center border-r border-border bg-surface px-3 text-sm text-fg-muted">+91</span>
<input name="phone" type="tel" required autoComplete="tel-national" className="min-w-0 flex-1 bg-transparent px-3 text-sm text-fg outline-none" />
</span>
</Field>
<Field label="GSTIN" optional help="15 characters, from your GST certificate. Leave blank if you aren’t registered." className="sm:col-span-2">
<input name="gstin" maxLength={15} pattern="[0-9A-Z]{15}" className={cn(input, "uppercase tabular-nums tracking-wide")} />
</Field>
<Field label="Address" className="sm:col-span-2"><input name="address" required autoComplete="street-address" className={input} /></Field>
<Field label="City"><input name="city" required autoComplete="address-level2" className={input} /></Field>
<Field label="PIN code"><input name="pin" required inputMode="numeric" pattern="[0-9]{6}" autoComplete="postal-code" className={input} /></Field>
<Field label="State">
<select name="state" defaultValue="KA" className={cn(input, "appearance-none")}>
<option value="KA">Karnataka</option><option value="KL">Kerala</option><option value="MH">Maharashtra</option><option value="TN">Tamil Nadu</option>
</select>
</Field>
<Field label="Country">
<select name="country" defaultValue="IN" className={cn(input, "appearance-none")}>
<option value="IN">India</option><option value="AE">United Arab Emirates</option><option value="SG">Singapore</option>
</select>
</Field>
</div>
<div className="mt-5 flex flex-wrap items-center justify-between gap-3 border-t border-border pt-4">
<label className="inline-flex cursor-pointer items-center gap-2 text-sm text-fg">
<input type="checkbox" name="shipSame" defaultChecked className="size-4 accent-primary" /> Ship to this address
</label>
<div className="flex gap-2">
<button type="reset" className="h-9 rounded px-3.5 text-sm font-medium text-fg transition hover:bg-surface-2">Cancel</button>
<button type="submit" className="h-9 rounded bg-primary px-3.5 text-sm font-medium text-primary-fg transition hover:bg-primary-hover">Save details</button>
</div>
</div>
</form>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.