All Taste components
Contact
Contact — form with contact channels
A contact form with topic chips on one side and separate cards for sales, support and press on the other.
topic chips · 2-column fields · channel cards · stacks on mobile
Contact
Talk to a person, not a ticket queue
Tell us what you need and the right team will write back within one working day.
- SalesPlans for teams of 10 or more.sales@tallybook.example
- SupportHelp with your account, any time.help@tallybook.example
- PressStories, interviews and assets.press@tallybook.example
"use client";
import { useState } from "react";
import { BarChart3, FileText, MessageCircle, type LucideIcon } from "lucide-react";
import { cn } from "@/lib/utils";
const channels: { icon: LucideIcon; title: string; note: string; email: string }[] = [
{ icon: BarChart3, title: "Sales", note: "Plans for teams of 10 or more.", email: "sales@tallybook.example" },
{ icon: MessageCircle, title: "Support", note: "Help with your account, any time.", email: "help@tallybook.example" },
{ icon: FileText, title: "Press", note: "Stories, interviews and assets.", email: "press@tallybook.example" },
];
const topics = ["A demo", "Pricing", "Moving from another tool", "Something else"];
const field = "h-9 w-full rounded border border-border-strong bg-bg px-3 text-sm text-fg outline-none placeholder:text-fg-subtle focus:border-primary focus:ring-[3px] focus:ring-primary/20";
export function ContactWithChannels({ onSubmit }: { onSubmit?: (data: FormData) => void }) {
const [topic, setTopic] = useState(topics[0]);
return (
<section aria-labelledby="contact-channels-title" className="bg-surface px-5 py-16 font-sans sm:px-10 sm:py-20">
<div className="mx-auto grid max-w-6xl gap-9 lg:grid-cols-[0.9fr_1.1fr] lg:gap-16">
<div>
<p className="text-[13px] font-medium text-primary">Contact</p>
<h2 id="contact-channels-title" className="mt-3 text-3xl font-semibold tracking-tight text-fg sm:text-4xl">Talk to a person, not a ticket queue</h2>
<p className="mt-4 text-base text-fg-muted sm:text-lg">Tell us what you need and the right team will write back within one working day.</p>
<ul className="mt-7 grid gap-3">
{channels.map(({ icon: Icon, title, note, email }) => (
<li key={title} className="flex items-start gap-3.5 rounded-lg border border-border bg-bg p-[18px]">
<span className="grid size-10 shrink-0 place-items-center rounded bg-primary-soft text-primary-soft-fg"><Icon className="size-[19px]" aria-hidden /></span>
<div className="grid min-w-0 gap-0.5">
<p className="text-sm font-semibold text-fg">{title}</p>
<p className="text-[13px] text-fg-subtle">{note}</p>
<a href={"mailto:" + email} className="break-all text-sm font-medium text-primary hover:underline">{email}</a>
</div>
</li>
))}
</ul>
</div>
<form
onSubmit={(e) => { e.preventDefault(); const data = new FormData(e.currentTarget); data.set("topic", topic); onSubmit?.(data); }}
className="grid gap-4 rounded-xl border border-border bg-bg p-7 shadow-xl"
>
<fieldset>
<legend className="mb-2 text-[13px] font-medium text-fg">What can we help with?</legend>
<div className="flex flex-wrap gap-2">
{topics.map((t) => (
<button key={t} type="button" aria-pressed={topic === t} onClick={() => setTopic(t)}
className={cn("h-[34px] rounded-full border px-3.5 text-[13px] font-medium transition",
topic === t ? "border-primary bg-primary-soft text-primary-soft-fg" : "border-border-strong bg-bg text-fg-muted hover:text-fg")}>
{t}
</button>
))}
</div>
</fieldset>
<div className="grid gap-4 sm:grid-cols-2">
<label className="grid gap-1.5"><span className="text-[13px] font-medium text-fg">Full name</span><input name="name" required autoComplete="name" className={field} /></label>
<label className="grid gap-1.5"><span className="text-[13px] font-medium text-fg">Work email</span><input name="email" type="email" required autoComplete="email" placeholder="you@company.com" className={field} /></label>
</div>
<div className="grid gap-4 sm:grid-cols-2">
<label className="grid gap-1.5"><span className="text-[13px] font-medium text-fg">Company</span><input name="company" autoComplete="organization" className={field} /></label>
<label className="grid gap-1.5">
<span className="text-[13px] font-medium text-fg">Team size</span>
<select name="size" defaultValue="2-10" className={field}>
<option value="1">Just me</option><option value="2-10">2–10 people</option><option value="11-50">11–50 people</option><option value="51+">51 or more</option>
</select>
</label>
</div>
<label className="grid gap-1.5">
<span className="text-[13px] font-medium text-fg">Message</span>
<textarea name="message" rows={4} placeholder="A little about how you invoice today…" className={cn(field, "h-auto py-2.5")} />
</label>
<div className="flex flex-wrap items-center justify-between gap-3">
<span className="text-[13px] text-fg-subtle">We reply within one working day.</span>
<button type="submit" className="inline-flex h-9 items-center rounded bg-primary px-4 text-sm font-medium text-primary-fg transition hover:bg-primary-hover">Send message</button>
</div>
</form>
</div>
</section>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.