Skip to content

Flow Form

A theme-aware animated contact form with progress tracking, validation, and micro-interactions.

Installation

pnpm dlx shadcn@latest add https://ui.sanjid.shop/r/flow-form.json

Backend Setup

The form expects an API endpoint at /api/send that accepts a POST request with JSON.

Example: Next.js Route Handler for Nodemailer:

pnpm add nodemailer

1EMAIL_HOST=smtp.example.com2EMAIL_PORT=5873EMAIL_USER=your_email@example.com4EMAIL_PASS=your_email_password5EMAIL_TO=recipient@example.com

1import { NextResponse } from "next/server";2import nodemailer from "nodemailer";3
4export async function POST(request: Request) {5  try {6    const { name, email, subject, message } = await request.json();7
8    if (!name || !email || !subject || !message) {9      return NextResponse.json(10        { error: "All fields are required" },11        { status: 400 },12      );13    }14
15    // Simple email validation16    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {17      return NextResponse.json(18        { error: "Invalid email address" },19        { status: 400 },20      );21    }22
23    const transporter = nodemailer.createTransport({24      host: process.env.EMAIL_HOST,25      port: Number(process.env.EMAIL_PORT),26      secure: Number(process.env.EMAIL_PORT) === 465,27      auth: {28        user: process.env.EMAIL_USER,29        pass: process.env.EMAIL_PASS,30      },31    });32
33    await transporter.sendMail({34      from: `"${name}" <${email}>`,35      to: process.env.EMAIL_TO,36      subject: `[FlowForm] ${subject}`,37      text: message,38      html: `<p>${message}</p><p>From: ${name} (${email})</p>`,39    });40
41    return NextResponse.json({42      success: true,43      message: "Message sent successfully!",44    });45  } catch (error) {46    console.error("FlowForm error:", error);47    return NextResponse.json({ error: "Server error" }, { status: 500 });48  }49}

Props

PropTypeRequiredDefaultDescription
classNamestringNoOptional class name to append to the root form element
onSubmit(data: Record<string,string>) => Promise<{ success: boolean; message?: string }>Nodefault mock submit functionCustom submit handler for backend integration

Usage

1"use client";2
3import FlowForm from "@/components/ui/flow-form";4
5export default function Page() {6  const handleSubmit = async (data: Record<string, string>) => {7    const response = await fetch("/api/send", {8      method: "POST",9      headers: { "Content-Type": "application/json" },10      body: JSON.stringify(data),11    });12    return response.json();13  };14
15  return (16    <div className="flex min-h-screen items-center justify-center bg-neutral-100 p-4 dark:bg-neutral-900">17      <FlowForm onSubmit={handleSubmit} className="w-full max-w-xl" />18    </div>19  );20}

Build your next big idea with us

From lightning-fast landing pages to fully functional SaaS products, we turn your vision into reality. Book a call today and let's make something extraordinary.

They transformed our idea into a fully functional product in record time. Couldn't be happier!

Alex Chen

Founder, StartupX

The team's attention to detail and design expertise set our product apart in the market.

Sarah Kim

CTO, Innovate Inc