Form Components
** Last Built**: September 2, 2025 at 4:19 PM Build beautiful forms with React SuperAdmin's form components.
Basic Form
Live Editor
import React, { useState } from 'react'; function BasicForm() { const [formData, setFormData] = useState({ name: '', email: '', role: '' }); const handleSubmit = (e) => { e.preventDefault(); console.log('Form submitted:', formData); }; return ( <form onSubmit={handleSubmit} className="space-y-4 max-w-md"> <div> <label className="block text-sm font-medium text-gray-700 mb-1"> Name * </label> <input type="text" value={formData.name} onChange={(e) => setFormData({...formData, name: e.target.value})} placeholder="Enter your name" className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" required /> </div> <div> <label className="block text-sm font-medium text-gray-700 mb-1"> Email * </label> <input type="email" value={formData.email} onChange={(e) => setFormData({...formData, email: e.target.value})} placeholder="Enter your email" className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" required /> </div> <div> <label className="block text-sm font-medium text-gray-700 mb-1"> Role </label> <select value={formData.role} onChange={(e) => setFormData({...formData, role: e.target.value})} className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" > <option value="">Select a role</option> <option value="admin">Administrator</option> <option value="user">User</option> <option value="moderator">Moderator</option> </select> </div> <button type="submit" className="w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2" > Submit Form </button> </form> ); }
Result
Loading...
Data Table Example
Live Editor
import React, { useState } from 'react'; function DataTableExample() { const [data] = useState([ { id: 1, name: 'John Doe', email: 'john@example.com', status: 'active', role: 'admin' }, { id: 2, name: 'Jane Smith', email: 'jane@example.com', status: 'inactive', role: 'user' }, { id: 3, name: 'Bob Johnson', email: 'bob@example.com', status: 'active', role: 'moderator' }, ]); const getStatusBadge = (status) => { const baseClasses = "px-2 py-1 text-xs font-medium rounded-full"; if (status === 'active') { return `${baseClasses} bg-green-100 text-green-800`; } return `${baseClasses} bg-yellow-100 text-yellow-800`; }; return ( <div className="overflow-x-auto"> <table className="min-w-full divide-y divide-gray-200"> <thead className="bg-gray-50"> <tr> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> Name </th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> Email </th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> Status </th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> Role </th> <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> Actions </th> </tr> </thead> <tbody className="bg-white divide-y divide-gray-200"> {data.map((user) => ( <tr key={user.id}> <td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900"> {user.name} </td> <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> {user.email} </td> <td className="px-6 py-4 whitespace-nowrap"> <span className={getStatusBadge(user.status)}> {user.status} </span> </td> <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> {user.role} </td> <td className="px-6 py-4 whitespace-nowrap text-sm font-medium"> <div className="space-x-2"> <button className="text-blue-600 hover:text-blue-900"> Edit </button> <button className="text-red-600 hover:text-red-900"> Delete </button> </div> </td> </tr> ))} </tbody> </table> </div> ); }
Result
Loading...
Live CRUD Operations
Live Editor
import React, { useState } from 'react'; function LiveCRUDExample() { const [users, setUsers] = useState([ { id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob', email: 'bob@example.com' }, ]); const [showForm, setShowForm] = useState(false); const [editingUser, setEditingUser] = useState(null); const [formData, setFormData] = useState({ name: '', email: '' }); const addUser = (e) => { e.preventDefault(); const newUser = { ...formData, id: Date.now() }; setUsers([...users, newUser]); setShowForm(false); setFormData({ name: '', email: '' }); }; const updateUser = (id, userData) => { setUsers(users.map(user => user.id === id ? { ...user, ...userData } : user)); setEditingUser(null); setFormData({ name: '', email: '' }); }; const deleteUser = (id) => { setUsers(users.filter(user => user.id !== id)); }; const startEdit = (user) => { setEditingUser(user); setFormData({ name: user.name, email: user.email }); setShowForm(true); }; const handleSubmit = (e) => { e.preventDefault(); if (editingUser) { updateUser(editingUser.id, formData); } else { addUser(e); }; return ( <div className="space-y-4"> <button onClick={() => { setShowForm(true); setEditingUser(null); setFormData({ name: '', email: '' }); }} className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700" > Add New User </button> <div className="space-y-2"> {users.map(user => ( <div key={user.id} className="flex justify-between items-center p-3 border rounded"> <div> <div className="font-medium">{user.name}</div> <div className="text-sm text-gray-600">{user.email}</div> </div> <div className="space-x-2"> <button onClick={() => startEdit(user)} className="px-3 py-1 text-sm border border-gray-300 rounded hover:bg-gray-50" > Edit </button> <button onClick={() => deleteUser(user.id)} className="px-3 py-1 text-sm text-red-600 hover:text-red-900" > Delete </button> </div> ))} </div> {showForm && ( <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4"> <div className="bg-white rounded-lg p-6 max-w-md w-full"> <h3 className="text-lg font-medium mb-4"> {editingUser ? 'Edit User' : 'Add New User'} </h3> <form onSubmit={handleSubmit} className="space-y-4"> <div> <label className="block text-sm font-medium text-gray-700 mb-1"> Name </label> <input type="text" value={formData.name} onChange={(e) => setFormData({...formData, name: e.target.value})} className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" required /> </div> <div> <label className="block text-sm font-medium text-gray-700 mb-1"> Email </label> <input type="email" value={formData.email} onChange={(e) => setFormData({...formData, email: e.target.value})} className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" required /> </div> <div className="flex space-x-2"> <button type="submit" className="flex-1 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700" > {editingUser ? 'Update' : 'Add'} </button> <button type="button" onClick={() => { setShowForm(false); setEditingUser(null); setFormData({ name: '', email: '' }); }} className="flex-1 px-4 py-2 border border-gray-300 text-gray-700 rounded hover:bg-gray-50" > Cancel </button> </div> </form> </div> )} </div> ); }
Result
Loading...
Form Validation
Live Editor
import React, { useState } from 'react'; function FormValidation() { const [formData, setFormData] = useState({ username: '', email: '', password: '', confirmPassword: '' }); const [errors, setErrors] = useState({}); const [touched, setTouched] = useState({}); const validateField = (name, value) => { switch (name) { case 'username': if (value.length < 3) return 'Username must be at least 3 characters'; if (value.length > 20) return 'Username must be less than 20 characters'; return ''; case 'email': const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(value)) return 'Please enter a valid email'; return ''; case 'password': if (value.length < 6) return 'Password must be at least 6 characters'; return ''; case 'confirmPassword': if (value !== formData.password) return 'Passwords do not match'; return ''; default: return ''; }; const handleChange = (name, value) => { setFormData({ ...formData, [name]: value }); if (touched[name]) { const error = validateField(name, value); setErrors({ ...errors, [name]: error }); }; const handleBlur = (name) => { setTouched({ ...touched, [name]: true }); const error = validateField(name, formData[name]); setErrors({ ...errors, [name]: error }); }; const handleSubmit = (e) => { e.preventDefault(); const newErrors = {}; Object.keys(formData).forEach(key => { const error = validateField(key, formData[key]); if (error) newErrors[key] = error; }); if (Object.keys(newErrors).length === 0) { console.log('Form submitted successfully:', formData); } else { setErrors(newErrors); setTouched(Object.keys(formData).reduce((acc, key) => ({ ...acc, [key]: true }), {})); }; return ( <form onSubmit={handleSubmit} className="space-y-4 max-w-md"> <div> <label className="block text-sm font-medium text-gray-700 mb-1"> Username </label> <input type="text" value={formData.username} onChange={(e) => handleChange('username', e.target.value)} onBlur={() => handleBlur('username')} className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ touched.username && errors.username ? 'border-red-500' : 'border-gray-300' }`} /> {touched.username && errors.username && ( <p className="mt-1 text-sm text-red-600">{errors.username}</p> )} </div> <div> <label className="block text-sm font-medium text-gray-700 mb-1"> Email </label> <input type="email" value={formData.email} onChange={(e) => handleChange('email', e.target.value)} onBlur={() => handleBlur('email')} className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ touched.email && errors.email ? 'border-red-500' : 'border-gray-300' }`} /> {touched.email && errors.email && ( <p className="mt-1 text-sm text-red-600">{errors.email}</p> )} </div> <div> <label className="block text-sm font-medium text-gray-700 mb-1"> Password </label> <input type="password" value={formData.password} onChange={(e) => handleChange('password', e.target.value)} onBlur={() => handleBlur('password')} className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ touched.password && errors.password ? 'border-red-500' : 'border-gray-300' }`} /> {touched.password && errors.password && ( <p className="mt-1 text-sm text-red-600">{errors.password}</p> )} </div> <div> <label className="block text-sm font-medium text-gray-700 mb-1"> Confirm Password </label> <input type="password" value={formData.confirmPassword} onChange={(e) => handleChange('confirmPassword', e.target.value)} onBlur={() => handleBlur('confirmPassword')} className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${ touched.confirmPassword && errors.confirmPassword ? 'border-red-500' : 'border-gray-300' }`} /> {touched.confirmPassword && errors.confirmPassword && ( <p className="mt-1 text-sm text-red-600">{errors.confirmPassword}</p> )} </div> <button type="submit" className="w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2" > Submit </button> </form> ); }
Result
Loading...
Key Features
- Real-time Validation: Instant feedback on form errors
- Accessible: Proper labels and error messages
- Responsive: Works on all device sizes
- Customizable: Easy to style and extend
- Type Safe: Full TypeScript support
Best Practices
- Always validate on blur: Don't show errors until user has interacted with a field
- Clear error messages: Tell users exactly what's wrong and how to fix it
- Accessible labels: Use proper
<label>elements for screen readers - Loading states: Show feedback during form submission
- Success feedback: Confirm when forms are submitted successfully