Checkout Forms

PreviousNext

Streamline the purchasing process with Tailwind CSS checkout form sections. These layouts feature organized fields, clear labels, and responsive design to ensure smooth and user-friendly transactions. Perfect for online stores and marketplaces aiming for modern, secure, and conversion-optimized checkout experiences.

Docs
bunduicomponent

Preview

Loading preview…
examples/blocks/ecommerce/checkout-forms/01/page.tsx
"use client";

import { useState } from "react";
import { Card, CardContent, CardFooter } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Check, Gift } from "lucide-react";
import { Separator } from "@/components/ui/separator";

export default function Page() {
  const [selectedPayment, setSelectedPayment] = useState("card");
  const [formData, setFormData] = useState({
    cardName: "John Cena",
    cardNumber: "1234 5678 9012 3456",
    expiryDate: "09/27",
    cvc: "123",
    agreeTerms: true
  });

  const paymentMethods = [
    {
      id: "card",
      name: "Credit/Debit Card",
      logos: ["Visa", "Mastercard"],
      component: "card"
    },
    {
      id: "paypal",
      name: "Paypal",
      logos: ["PayPal"],
      component: "external"
    },
    {
      id: "bank-transfer",
      name: "Bank Transfer",
      logos: ["GoPay"],
      component: "external"
    }
  ];

  const handleInputChange = (field: string, value: string) => {
    setFormData((prev) => ({ ...prev, [field]: value }));
  };

  return (
    <section className="py-10 lg:py-20">
      <div className="container mx-auto px-4">
        <div className="grid grid-cols-1 gap-8 lg:grid-cols-2">
          {/* Payment Method Section */}
          <div className="space-y-6">
            <h2 className="font-semibold">Payment Method</h2>

            <div className="space-y-4">
              {paymentMethods.map((method) => (
                <Card
                  key={method.id}
                  className={`cursor-pointer shadow-none transition-all duration-200 ${
                    selectedPayment === method.id
                      ? "ring-primary ring"
                      : "hover:border-muted-foreground/20"
                  }`}
                  onClick={() => setSelectedPayment(method.id)}>
                  <CardContent>
                    <div className="flex items-center justify-between">
                      <div className="flex items-center space-x-3">
                        <div
                          className={`flex h-4 w-4 items-center justify-center rounded-full border-2 ${
                            selectedPayment === method.id
                              ? "border-primary bg-primary"
                              : "border-muted-foreground"
                          }`}>
                          {selectedPayment === method.id && (
                            <div className="bg-primary-foreground h-2 w-2 rounded-full"></div>
                          )}
                        </div>
                        <span className="font-medium">{method.name}</span>
                      </div>
                      <div className="flex items-center space-x-2">
                        {method.logos.map((logo) => (
                          <div
                            key={logo}
                            className="bg-muted text-muted-foreground rounded px-2 py-1 text-xs font-semibold">
                            {logo}
                          </div>
                        ))}
                      </div>
                    </div>

                    {/* Card Form */}
                    {selectedPayment === "card" && method.id === "card" && (
                      <div className="mt-6 space-y-4">
                        <div>
                          <Label htmlFor="cardName" className="text-sm font-medium">
                            Name on Card
                          </Label>
                          <Input
                            id="cardName"
                            value={formData.cardName}
                            onChange={(e) => handleInputChange("cardName", e.target.value)}
                            className="mt-1"
                            placeholder="John Cena"
                          />
                        </div>

                        <div>
                          <Label htmlFor="cardNumber" className="text-sm font-medium">
                            Card Number
                          </Label>
                          <Input
                            id="cardNumber"
                            value={formData.cardNumber}
                            onChange={(e) => handleInputChange("cardNumber", e.target.value)}
                            className="mt-1"
                            placeholder="1234 5678 9012 3456"
                          />
                        </div>

                        <div className="grid grid-cols-2 gap-4">
                          <div>
                            <Label htmlFor="expiryDate" className="text-sm font-medium">
                              Expiry Date
                            </Label>
                            <Input
                              id="expiryDate"
                              value={formData.expiryDate}
                              onChange={(e) => handleInputChange("expiryDate", e.target.value)}
                              className="mt-1"
                              placeholder="09/27"
                            />
                          </div>
                          <div>
                            <Label htmlFor="cvc" className="text-sm font-medium">
                              CVC
                            </Label>
                            <Input
                              id="cvc"
                              value={formData.cvc}
                              onChange={(e) => handleInputChange("cvc", e.target.value)}
                              className="ring-primary/20 border-primary/30 mt-1 ring-2"
                              placeholder="123"
                            />
                          </div>
                        </div>
                      </div>
                    )}
                  </CardContent>
                </Card>
              ))}
            </div>
          </div>

          {/* Order Details Section */}
          <div className="space-y-4">
            <h2 className="font-semibold">Order Details</h2>

            {/* Course Card */}
            <Card className="bg-muted/50 border-0 shadow-none">
              <CardContent className="space-y-4">
                <div className="flex gap-4">
                  <img
                    src="/images/products/list1.png"
                    alt="Mastering Illustration Course"
                    className="aspect-square w-20 rounded-md object-cover"
                  />
                  <div className="flex-1 space-y-2">
                    <div>
                      <h3 className="font-semibold">Mastering Illustration</h3>
                      <p className="text-muted-foreground text-xs">25 Lessons • 72 Hours</p>
                    </div>
                    <p className="mt-1">$300</p>
                  </div>
                </div>
                <div className="flex gap-4">
                  <img
                    src="/images/products/list2.png"
                    alt="Mastering Illustration Course"
                    className="aspect-square w-20 rounded-md object-cover"
                  />
                  <div className="flex-1 space-y-2">
                    <div>
                      <h3 className="font-semibold">Mastering Illustration</h3>
                      <p className="text-muted-foreground text-xs">25 Lessons • 72 Hours</p>
                    </div>
                    <p className="mt-1">$300</p>
                  </div>
                </div>
              </CardContent>
            </Card>

            {/* Discount Section */}
            <Card className="bg-muted/50 border-0 shadow-none">
              <CardContent>
                <div className="flex items-center justify-between">
                  <div className="flex items-center space-x-2">
                    <Gift className="text-muted-foreground h-5 w-5" />
                    <span className="font-medium">GWENCHANA</span>
                  </div>
                  <Button variant="secondary">Discount Code</Button>
                </div>
                <p className="text-primary mt-2 text-sm">Yeay, you got $10 discount!</p>
              </CardContent>
            </Card>

            {/* Price Breakdown */}
            <Card className="bg-muted/50 border-0 shadow-none">
              <CardContent className="space-y-3 text-sm">
                <div className="flex items-center justify-between">
                  <span className="">Price</span>
                  <span className="">$300</span>
                </div>
                <div className="flex items-center justify-between">
                  <span className="">Discount</span>
                  <span className="text-destructive">-$10</span>
                </div>
                <div className="flex items-center justify-between">
                  <span className="">Tax</span>
                  <span className="text-green-600">+$1</span>
                </div>
                <Separator />
                <div className="flex items-center justify-between">
                  <span className="font-semibold">Total</span>
                  <span className="font-semibold">$289</span>
                </div>
              </CardContent>
            </Card>

            <div className="space-y-4">
              <div className="flex items-start space-x-2">
                <Checkbox
                  id="terms"
                  checked={formData.agreeTerms}
                  onCheckedChange={(checked) =>
                    setFormData((prev) => ({ ...prev, agreeTerms: checked === true }))
                  }
                  className="mt-1"
                />
                <Label htmlFor="terms" className="text-sm leading-5">
                  By clicking this you are agree to our
                </Label>
              </div>

              <Button size="lg" className="w-full" disabled={!formData.agreeTerms}>
                Checkout Now
              </Button>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

Installation

npx shadcn@latest add @bundui/checkout-forms-01

Usage

import { CheckoutForms01 } from "@/components/checkout-forms-01"
<CheckoutForms01 />