Google Antigravity Directory

The #1 directory for Google Antigravity prompts, rules, workflows & MCP servers. Optimized for Gemini 3 agentic development.

Resources

PromptsMCP ServersAntigravity RulesGEMINI.md GuideBest Practices

Company

Submit PromptAntigravityAI.directory

Popular Prompts

Next.js 14 App RouterReact TypeScriptTypeScript AdvancedFastAPI GuideDocker Best Practices

Legal

Privacy PolicyTerms of ServiceContact Us
Featured on FazierVerified on Verified ToolsFeatured on WayfindioAntigravity AI - Featured on Startup FameFeatured on Wired BusinessFeatured on Twelve ToolsListed on Turbo0Featured on findly.toolsFeatured on Aura++That App ShowFeatured on FazierVerified on Verified ToolsFeatured on WayfindioAntigravity AI - Featured on Startup FameFeatured on Wired BusinessFeatured on Twelve ToolsListed on Turbo0Featured on findly.toolsFeatured on Aura++That App Show

© 2026 Antigravity AI Directory. All rights reserved.

The #1 directory for Google Antigravity IDE

This website is not affiliated with, endorsed by, or associated with Google LLC. "Google" and "Gemini" are trademarks of Google LLC.

Antigravity AI Directory
PromptsMCPBest PracticesUse CasesLearn
Home
Prompts
Form Validation in React

Form Validation in React

Implement robust form validation with React Hook Form and Zod

FormsValidationReactTypeScript
by Community
⭐1Stars
👁️31Views
📋4Copies
.antigravity
# Form Validation in React for Google Antigravity

Build robust form validation using React Hook Form and Zod in your Google Antigravity projects. This comprehensive guide covers schema validation, error handling, and user-friendly validation feedback.

## Setting Up Form Validation

Configure React Hook Form with Zod resolver:

```typescript
// src/lib/validation.ts
import { z } from "zod";

export const userRegistrationSchema = z.object({
  email: z
    .string()
    .min(1, "Email is required")
    .email("Please enter a valid email address"),
  password: z
    .string()
    .min(8, "Password must be at least 8 characters")
    .regex(/[A-Z]/, "Password must contain at least one uppercase letter")
    .regex(/[a-z]/, "Password must contain at least one lowercase letter")
    .regex(/[0-9]/, "Password must contain at least one number")
    .regex(/[^A-Za-z0-9]/, "Password must contain at least one special character"),
  confirmPassword: z.string().min(1, "Please confirm your password"),
  username: z
    .string()
    .min(3, "Username must be at least 3 characters")
    .max(20, "Username must not exceed 20 characters")
    .regex(/^[a-zA-Z0-9_]+$/, "Username can only contain letters, numbers, and underscores"),
  dateOfBirth: z
    .string()
    .min(1, "Date of birth is required")
    .refine((date) => {
      const birthDate = new Date(date);
      const today = new Date();
      const age = today.getFullYear() - birthDate.getFullYear();
      return age >= 18;
    }, "You must be at least 18 years old"),
  acceptTerms: z.boolean().refine((val) => val === true, "You must accept the terms"),
}).refine((data) => data.password === data.confirmPassword, {
  message: "Passwords do not match",
  path: ["confirmPassword"],
});

export type UserRegistrationInput = z.infer<typeof userRegistrationSchema>;
```

## Building the Registration Form

Create a fully validated registration form:

```typescript
// src/components/Forms/RegistrationForm.tsx
"use client";

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { userRegistrationSchema, UserRegistrationInput } from "@/lib/validation";
import { useState } from "react";

export function RegistrationForm() {
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [submitError, setSubmitError] = useState<string | null>(null);
  
  const {
    register,
    handleSubmit,
    formState: { errors, isValid, dirtyFields },
    watch,
    reset,
  } = useForm<UserRegistrationInput>({
    resolver: zodResolver(userRegistrationSchema),
    mode: "onChange",
    defaultValues: {
      email: "",
      password: "",
      confirmPassword: "",
      username: "",
      dateOfBirth: "",
      acceptTerms: false,
    },
  });
  
  const password = watch("password");
  
  const onSubmit = async (data: UserRegistrationInput) => {
    setIsSubmitting(true);
    setSubmitError(null);
    
    try {
      const response = await fetch("/api/auth/register", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(data),
      });
      
      if (!response.ok) {
        const error = await response.json();
        throw new Error(error.message || "Registration failed");
      }
      
      reset();
      // Redirect or show success message
    } catch (error) {
      setSubmitError(error instanceof Error ? error.message : "An error occurred");
    } finally {
      setIsSubmitting(false);
    }
  };
  
  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-6" noValidate>
      <FormField
        label="Email"
        type="email"
        {...register("email")}
        error={errors.email?.message}
        isDirty={dirtyFields.email}
      />
      
      <FormField
        label="Username"
        {...register("username")}
        error={errors.username?.message}
        isDirty={dirtyFields.username}
      />
      
      <FormField
        label="Password"
        type="password"
        {...register("password")}
        error={errors.password?.message}
        isDirty={dirtyFields.password}
      />
      
      <PasswordStrengthIndicator password={password} />
      
      <FormField
        label="Confirm Password"
        type="password"
        {...register("confirmPassword")}
        error={errors.confirmPassword?.message}
        isDirty={dirtyFields.confirmPassword}
      />
      
      <FormField
        label="Date of Birth"
        type="date"
        {...register("dateOfBirth")}
        error={errors.dateOfBirth?.message}
        isDirty={dirtyFields.dateOfBirth}
      />
      
      <div className="flex items-center gap-2">
        <input
          type="checkbox"
          id="acceptTerms"
          {...register("acceptTerms")}
          className="h-4 w-4 rounded border-gray-600"
        />
        <label htmlFor="acceptTerms" className="text-sm">
          I accept the terms and conditions
        </label>
      </div>
      {errors.acceptTerms && (
        <p className="text-red-500 text-sm">{errors.acceptTerms.message}</p>
      )}
      
      {submitError && (
        <div className="bg-red-500/10 border border-red-500 rounded p-3">
          <p className="text-red-500">{submitError}</p>
        </div>
      )}
      
      <button
        type="submit"
        disabled={!isValid || isSubmitting}
        className="w-full py-3 bg-gradient-to-r from-indigo-500 to-purple-500 rounded-lg font-semibold disabled:opacity-50"
      >
        {isSubmitting ? "Creating Account..." : "Create Account"}
      </button>
    </form>
  );
}
```

## Reusable Form Field Component

Create a flexible form field component:

```typescript
// src/components/Forms/FormField.tsx
import { forwardRef, InputHTMLAttributes } from "react";
import { cn } from "@/lib/utils";

interface FormFieldProps extends InputHTMLAttributes<HTMLInputElement> {
  label: string;
  error?: string;
  isDirty?: boolean;
  helpText?: string;
}

export const FormField = forwardRef<HTMLInputElement, FormFieldProps>(
  ({ label, error, isDirty, helpText, className, ...props }, ref) => {
    const hasError = error && isDirty;
    const isValid = isDirty && !error;
    
    return (
      <div className="space-y-2">
        <label className="block text-sm font-medium text-gray-200">
          {label}
          {props.required && <span className="text-red-500 ml-1">*</span>}
        </label>
        
        <div className="relative">
          <input
            ref={ref}
            className={cn(
              "w-full px-4 py-3 bg-gray-800 border rounded-lg transition-colors",
              "focus:outline-none focus:ring-2 focus:ring-indigo-500",
              hasError && "border-red-500 focus:ring-red-500",
              isValid && "border-green-500",
              !hasError && !isValid && "border-gray-700",
              className
            )}
            {...props}
          />
          
          {isValid && (
            <span className="absolute right-3 top-1/2 -translate-y-1/2 text-green-500">
              ✓
            </span>
          )}
        </div>
        
        {helpText && !error && (
          <p className="text-sm text-gray-400">{helpText}</p>
        )}
        
        {hasError && (
          <p className="text-sm text-red-500 flex items-center gap-1">
            <span>⚠</span> {error}
          </p>
        )}
      </div>
    );
  }
);
```

## Password Strength Indicator

Build visual password strength feedback:

```typescript
// src/components/Forms/PasswordStrengthIndicator.tsx
import { useMemo } from "react";

interface PasswordStrengthIndicatorProps {
  password: string;
}

export function PasswordStrengthIndicator({ password }: PasswordStrengthIndicatorProps) {
  const strength = useMemo(() => {
    if (!password) return { score: 0, label: "", color: "" };
    
    let score = 0;
    if (password.length >= 8) score++;
    if (password.length >= 12) score++;
    if (/[A-Z]/.test(password)) score++;
    if (/[a-z]/.test(password)) score++;
    if (/[0-9]/.test(password)) score++;
    if (/[^A-Za-z0-9]/.test(password)) score++;
    
    const labels = ["Very Weak", "Weak", "Fair", "Good", "Strong", "Very Strong"];
    const colors = ["bg-red-500", "bg-orange-500", "bg-yellow-500", "bg-lime-500", "bg-green-500", "bg-emerald-500"];
    
    return {
      score,
      label: labels[Math.min(score, 5)],
      color: colors[Math.min(score, 5)],
    };
  }, [password]);
  
  if (!password) return null;
  
  return (
    <div className="space-y-2">
      <div className="flex gap-1">
        {[...Array(6)].map((_, i) => (
          <div
            key={i}
            className={cn(
              "h-1 flex-1 rounded transition-colors",
              i < strength.score ? strength.color : "bg-gray-700"
            )}
          />
        ))}
      </div>
      <p className="text-xs text-gray-400">
        Password strength: <span className="font-medium">{strength.label}</span>
      </p>
    </div>
  );
}
```

Google Antigravity generates comprehensive form validation code that ensures data integrity while providing excellent user experience through real-time feedback.

When to Use This Prompt

This Forms prompt is ideal for developers working on:

  • Forms applications requiring modern best practices and optimal performance
  • Projects that need production-ready Forms code with proper error handling
  • Teams looking to standardize their forms development workflow
  • Developers wanting to learn industry-standard Forms patterns and techniques

By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their forms implementations.

How to Use

  1. Copy the prompt - Click the copy button above to copy the entire prompt to your clipboard
  2. Paste into your AI assistant - Use with Claude, ChatGPT, Cursor, or any AI coding tool
  3. Customize as needed - Adjust the prompt based on your specific requirements
  4. Review the output - Always review generated code for security and correctness
💡 Pro Tip: For best results, provide context about your project structure and any specific constraints or preferences you have.

Best Practices

  • ✓ Always review generated code for security vulnerabilities before deploying
  • ✓ Test the Forms code in a development environment first
  • ✓ Customize the prompt output to match your project's coding standards
  • ✓ Keep your AI assistant's context window in mind for complex requirements
  • ✓ Version control your prompts alongside your code for reproducibility

Frequently Asked Questions

Can I use this Forms prompt commercially?

Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.

Which AI assistants work best with this prompt?

This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.

How do I customize this prompt for my specific needs?

You can modify the prompt by adding specific requirements, constraints, or preferences. For Forms projects, consider mentioning your framework version, coding style, and any specific libraries you're using.

Related Prompts

💬 Comments

Loading comments...