Skip to main content

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.

Issue categorization (Shipping, Bug, Billing, Account)
Order number & reference ID tracking
Urgency and priority level selection
Invisible honeypot (_gotcha) spam trap
Instant ticket forwarding to Email, Slack & Zendesk
Live Form PreviewComponent Sandbox

Help Desk Support Ticket

Pre-classified intake form with order number lookup, severity tagging, and automatic ticket assignment.

Issue Urgency & Priority
Pre-configured for Backforms endpoint with Slack, Zendesk, and Telegram routing
Honeypot anti-spam active
Zero backend needed
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>
  );
}
Replace YOUR_FORM_ID with your Backforms key

Connect this component to your Backforms endpoint

Create a free form endpoint in under 30 seconds. Zero backend servers or databases required.

Get Free Endpoint Key

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.