Help Desk & Support Ticket Form
A modern customer support and help desk intake form styled with Tailwind CSS. Includes pre-classified issue categories, optional order/reference ID, priority urgency levels, invisible honeypot anti-spam defense, and instant ticket forwarding to Slack, Zendesk, or email via Backforms.
Help Desk Support Ticket
Pre-classified intake form with order number lookup, severity tagging, and automatic ticket assignment.
style="color:#9ece6a;">"use client";
import { useState } from style="color:#9ece6a;">"react";
import { LifeBuoy, Check, AlertCircle } from style="color:#9ece6a;">"lucide-react";
export default function HelpDeskSupportForm() {
const [formData, setFormData] = useState({
name: style="color:#9ece6a;">"",
email: style="color:#9ece6a;">"",
orderNumber: style="color:#9ece6a;">"",
category: style="color:#9ece6a;">"Order Status & Shipping",
priority: style="color:#9ece6a;">"Normal",
subject: style="color:#9ece6a;">"",
description: style="color:#9ece6a;">"",
});
const [status, setStatus] = useState<style="color:#9ece6a;">"idle" | style="color:#9ece6a;">"loading" | style="color:#9ece6a;">"success" | style="color:#9ece6a;">"error">(style="color:#9ece6a;">"idle");
const [ticketId, setTicketId] = useState(style="color:#9ece6a;">"");
const [errorMessage, setErrorMessage] = useState(style="color:#9ece6a;">"");
const categories = [
style="color:#9ece6a;">"Order Status & Shipping",
style="color:#9ece6a;">"Technical Bug & API",
style="color:#9ece6a;">"Billing & Invoice",
style="color:#9ece6a;">"Returns & Refunds",
style="color:#9ece6a;">"Account Access & Security",
];
const priorities = [style="color:#9ece6a;">"Low", style="color:#9ece6a;">"Normal", style="color:#9ece6a;">"High", style="color:#9ece6a;">"Urgent"];
async function handleSubmit(e: React.FormEvent<style="color:#f7768e;font-weight:600;">HTMLFormElement>) {
e.preventDefault();
setStatus(style="color:#9ece6a;">"loading");
setErrorMessage(style="color:#9ece6a;">"");
const form = e.currentTarget;
const body = new FormData(form);
try {
style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">// Replace YOUR_FORM_ID with your actual endpoint ID from https://app.backforms.com
const res = await fetch(style="color:#9ece6a;">"https:style="color:#565f89;font-style:italic;style="color:#9ece6a;">">//backforms.com/f/YOUR_FORM_ID", {
method: style="color:#9ece6a;">"POST",
headers: { Accept: style="color:#9ece6a;">"application/json" },
body,
});
if (res.ok) {
setTicketId(`TKT-${Math.floor(10000 + Math.random() * 90000)}`);
setStatus(style="color:#9ece6a;">"success");
} else {
const data = await res.json().catch(() => ({}));
setErrorMessage(data.error || style="color:#9ece6a;">"Failed to submit support ticket. Please try again.");
setStatus(style="color:#9ece6a;">"error");
}
} catch {
setErrorMessage(style="color:#9ece6a;">"Network error occurred. Please check your connection.");
setStatus(style="color:#9ece6a;">"error");
}
}
if (status === style="color:#9ece6a;">"success") {
return (
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"max-w-xl mx-auto p-8 bg-[#0f1117] border border-zinc-800 rounded-2xl text-center space-y-3">
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"size-10 mx-auto rounded-full bg-teal-950/60 border border-teal-500/30 flex items-center justify-center text-teal-400">
<style="color:#f7768e;font-weight:600;">Check className=style="color:#9ece6a;">"size-5 stroke-[2.5]" />
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">h3 className=style="color:#9ece6a;">"text-xl font-bold text-white">Ticket #{ticketId} Created</style="color:#f7768e;font-weight:600;">h3>
<style="color:#f7768e;font-weight:600;">p className=style="color:#9ece6a;">"text-xs text-zinc-400 max-w-sm mx-auto">
We have routed your ticket to our support queue. A confirmation email has been dispatched.
</style="color:#f7768e;font-weight:600;">p>
<style="color:#f7768e;font-weight:600;">button
onClick={() => {
setFormData({ name: style="color:#9ece6a;">"", email: style="color:#9ece6a;">"", orderNumber: style="color:#9ece6a;">"", category: categories[0], priority: style="color:#9ece6a;">"Normal", subject: style="color:#9ece6a;">"", description: style="color:#9ece6a;">"" });
setStatus(style="color:#9ece6a;">"idle");
}}
className=style="color:#9ece6a;">"mt-3 px-4 py-2 bg-zinc-800 hover:bg-zinc-700 text-white text-xs font-medium rounded-lg"
>
Submit Another Request
</style="color:#f7768e;font-weight:600;">button>
</style="color:#f7768e;font-weight:600;">div>
);
}
return (
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"max-w-xl mx-auto p-6 sm:p-8 bg-[#0f1117] border border-zinc-800 rounded-2xl text-zinc-200">
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"mb-6">
<style="color:#f7768e;font-weight:600;">h2 className=style="color:#9ece6a;">"text-2xl font-bold text-white tracking-tight">Help Desk Support</style="color:#f7768e;font-weight:600;">h2>
<style="color:#f7768e;font-weight:600;">p className=style="color:#9ece6a;">"text-xs text-zinc-400 mt-1">Pre-classified support intake with automated ticket routing.</style="color:#f7768e;font-weight:600;">p>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">form onSubmit={handleSubmit} className=style="color:#9ece6a;">"space-y-4">
{style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">/* Invisible Honeypot Spam Trap */}
<style="color:#f7768e;font-weight:600;">input type=style="color:#9ece6a;">"text" name=style="color:#9ece6a;">"_gotcha" style={{ display: style="color:#9ece6a;">"none" }} tabIndex={-1} autoComplete=style="color:#9ece6a;">"off" />
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"grid grid-cols-1 sm:grid-cols-2 gap-3.5">
<style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Your Full Name</style="color:#f7768e;font-weight:600;">label>
<style="color:#f7768e;font-weight:600;">input
type=style="color:#9ece6a;">"text"
name=style="color:#9ece6a;">"name"
required
placeholder=style="color:#9ece6a;">"Morgan Reed"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
className=style="color:#9ece6a;">"w-full bg-[#161822] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs placeholder:text-zinc-500 focus:outline-none focus:border-teal-500 transition-colors"
/>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Account Email</style="color:#f7768e;font-weight:600;">label>
<style="color:#f7768e;font-weight:600;">input
type=style="color:#9ece6a;">"email"
name=style="color:#9ece6a;">"email"
required
placeholder=style="color:#9ece6a;">"morgan@example.com"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
className=style="color:#9ece6a;">"w-full bg-[#161822] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs placeholder:text-zinc-500 focus:outline-none focus:border-teal-500 transition-colors"
/>
</style="color:#f7768e;font-weight:600;">div>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"grid grid-cols-1 sm:grid-cols-2 gap-3.5">
<style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Support Category</style="color:#f7768e;font-weight:600;">label>
<style="color:#f7768e;font-weight:600;">select
name=style="color:#9ece6a;">"category"
value={formData.category}
onChange={(e) => setFormData({ ...formData, category: e.target.value })}
className=style="color:#9ece6a;">"w-full bg-[#161822] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs focus:outline-none focus:border-teal-500 transition-colors"
>
{categories.map((c) => (
<style="color:#f7768e;font-weight:600;">option key={c} value={c}>{c}</style="color:#f7768e;font-weight:600;">option>
))}
</style="color:#f7768e;font-weight:600;">select>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Order Number (Optional)</style="color:#f7768e;font-weight:600;">label>
<style="color:#f7768e;font-weight:600;">input
type=style="color:#9ece6a;">"text"
name=style="color:#9ece6a;">"orderNumber"
placeholder=style="color:#9ece6a;">"e.g. ORD-98241"
value={formData.orderNumber}
onChange={(e) => setFormData({ ...formData, orderNumber: e.target.value })}
className=style="color:#9ece6a;">"w-full bg-[#161822] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs placeholder:text-zinc-500 focus:outline-none focus:border-teal-500 transition-colors font-mono"
/>
</style="color:#f7768e;font-weight:600;">div>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">span className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1.5">Priority Level</style="color:#f7768e;font-weight:600;">span>
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"grid grid-cols-4 gap-2">
{priorities.map((p) => (
<style="color:#f7768e;font-weight:600;">button
key={p}
type=style="color:#9ece6a;">"button"
onClick={() => setFormData({ ...formData, priority: p })}
className={`py-2 text-xs font-medium rounded-lg border text-center transition-colors cursor-pointer ${
formData.priority === p
? style="color:#9ece6a;">"bg-teal-950/60 text-teal-300 border-teal-500 font-semibold"
: style="color:#9ece6a;">"bg-[#161822] text-zinc-400 border-zinc-800 hover:border-zinc-700 hover:text-zinc-200"
}`}
>
{p}
</style="color:#f7768e;font-weight:600;">button>
))}
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">input type=style="color:#9ece6a;">"hidden" name=style="color:#9ece6a;">"priority" value={formData.priority} />
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Subject</style="color:#f7768e;font-weight:600;">label>
<style="color:#f7768e;font-weight:600;">input
type=style="color:#9ece6a;">"text"
name=style="color:#9ece6a;">"subject"
required
placeholder=style="color:#9ece6a;">"Brief summary of the issue..."
value={formData.subject}
onChange={(e) => setFormData({ ...formData, subject: e.target.value })}
className=style="color:#9ece6a;">"w-full bg-[#161822] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs placeholder:text-zinc-500 focus:outline-none focus:border-teal-500 transition-colors"
/>
</style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">div>
<style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Description & Reproduction Steps</style="color:#f7768e;font-weight:600;">label>
<style="color:#f7768e;font-weight:600;">textarea
name=style="color:#9ece6a;">"description"
rows={3}
required
placeholder=style="color:#9ece6a;">"Provide context, error messages, or order details..."
value={formData.description}
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
className=style="color:#9ece6a;">"w-full bg-[#161822] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs placeholder:text-zinc-500 focus:outline-none focus:border-teal-500 transition-colors resize-none"
/>
</style="color:#f7768e;font-weight:600;">div>
{status === style="color:#9ece6a;">"error" && (
<style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"p-3 bg-red-950/40 border border-red-500/30 rounded-lg flex items-center gap-2 text-xs text-red-300">
<style="color:#f7768e;font-weight:600;">AlertCircle className=style="color:#9ece6a;">"size-4 shrink-0" />
<style="color:#f7768e;font-weight:600;">span>{errorMessage}</style="color:#f7768e;font-weight:600;">span>
</style="color:#f7768e;font-weight:600;">div>
)}
<style="color:#f7768e;font-weight:600;">button
type=style="color:#9ece6a;">"submit"
disabled={status === style="color:#9ece6a;">"loading"}
className=style="color:#9ece6a;">"w-full mt-2 bg-teal-600 hover:bg-teal-500 text-white font-medium text-xs py-2.5 px-4 rounded-lg active:scale-[0.99] transition duration-150 cursor-pointer disabled:opacity-60 flex items-center justify-center gap-2"
>
<style="color:#f7768e;font-weight:600;">LifeBuoy className=style="color:#9ece6a;">"size-4 shrink-0" />
<style="color:#f7768e;font-weight:600;">span>{status === style="color:#9ece6a;">"loading" ? style="color:#9ece6a;">"Submitting Ticket..." : style="color:#9ece6a;">"Submit Support Ticket"}</style="color:#f7768e;font-weight:600;">span>
</style="color:#f7768e;font-weight:600;">button>
</style="color:#f7768e;font-weight:600;">form>
</style="color:#f7768e;font-weight:600;">div>
);
}Connect this component to your Backforms endpoint
Create a free form endpoint in under 30 seconds. Zero backend servers or databases required.
Frequently Asked Questions & Technical Integration
How does pre-classification work with Backforms webhooks?
Backforms parses the 'category', 'priority', and 'orderNumber' fields directly into the webhook JSON payload. You can use this to route urgent tickets directly to PagerDuty or Slack, and order issues directly into Zendesk or Linear.
Can I connect this form to Zendesk, Linear, or Freshdesk?
Yes! Backforms webhooks can be forwarded directly or via Zapier / Make / Webhook pipes to automatically create tickets with pre-filled tags and priority values.
Is the order number field optional?
Yes, customers reaching out about pre-sale inquiries or general account questions can leave it blank, while order-related requests capture the exact order ID.