Skip to content

StratIQX Form Styling Guidelines

Document Information

  • Document Title: Comprehensive Form Styling Guidelines for StratIQX Applications
  • Version: 1.0
  • Date: August 25, 2025
  • Purpose: Provide standardized form styling patterns, validation techniques, and implementation guidelines based on proven implementations in the StratIQX onboarding application.

Table of Contents

  1. Overview & Design Philosophy
  2. Form Layout Patterns
  3. Component Structure
  4. Typography & Color System
  5. Validation & Error Handling
  6. State Management
  7. Accessibility Guidelines
  8. Implementation Examples
  9. Best Practices
  10. Common Patterns & Reusable Components

Overview & Design Philosophy

Core Principles

Our form design follows these fundamental principles derived from successful implementations:

  1. Consistency: All forms maintain visual and functional consistency across the application
  2. Clarity: Clear visual hierarchy and intuitive user flow
  3. Professional Appearance: Clean, modern styling that reflects enterprise software quality
  4. Accessibility: WCAG 2.1 compliant with proper focus management and screen reader support
  5. Responsive Design: Forms work seamlessly across all device sizes
  6. Progressive Enhancement: Core functionality works without JavaScript

Design System Integration

Forms integrate with the existing StratIQX design system using:

  • Tailwind CSS with custom CSS variables
  • shadcn/ui component patterns
  • Lucide React icons for visual enhancement
  • Consistent color palette (blues, grays, status colors)

Form Layout Patterns

1. Modal Forms (Complex/Multi-Section)

Use Case: Complex forms with multiple related sections (e.g., CustomIndustryRequestModal)

Structure:

tsx
<div className="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-50">
  <div className="w-full max-w-2xl bg-white rounded-lg shadow-xl flex flex-col max-h-[90vh]">
    {/* Fixed Header */}
    <div className="flex items-center justify-between p-6 border-b border-gray-200 flex-shrink-0">
      <div>
        <h2 className="text-xl font-semibold text-gray-900">Form Title</h2>
        <p className="text-sm text-gray-600 mt-1">Form Description</p>
      </div>
      <Button variant="ghost" size="sm" onClick={onClose}>
        <X className="h-4 w-4" />
      </Button>
    </div>

    {/* Scrollable Content */}
    <div className="flex-1 overflow-y-auto">
      <div className="p-6 space-y-6">
        {/* Info Banner */}
        <InfoBanner />
        
        {/* Form Sections */}
        <FormSections />
      </div>
    </div>

    {/* Fixed Footer */}
    <div className="border-t border-gray-200 p-6 bg-gray-50 flex-shrink-0">
      <FormFooter />
    </div>
  </div>
</div>

Key Features:

  • Fixed header and footer with scrollable content
  • Modal backdrop with proper z-index (z-50)
  • Maximum height constraint (max-h-[90vh]) for small screens
  • Proper modal accessibility (ESC key, click outside to close)

2. Inline Forms (Embedded/Card-Based)

Use Case: Forms embedded within page content (e.g., Support Contact Form)

Structure:

tsx
<Card className="shadow-xl border-0 bg-white max-w-2xl mx-auto">
  <CardContent className="p-8">
    {/* Form Header */}
    <div className="mb-6">
      <h2 className="text-2xl font-bold text-gray-900 mb-2">Form Title</h2>
      <p className="text-gray-600">Form description</p>
    </div>

    {/* Info Banner */}
    <InfoBanner />
    
    {/* Form Content */}
    <div className="space-y-6">
      <FormSections />
    </div>

    {/* Form Footer */}
    <FormFooter />
  </CardContent>
</Card>

Key Features:

  • Card-based container with consistent shadows and borders
  • Integrated within page flow without overlay
  • Responsive width constraints (max-w-2xl mx-auto)
  • Consistent padding (p-8) for content areas

Component Structure

1. Info Banners

Purpose: Provide contextual information and set expectations

tsx
const InfoBanner: React.FC<{ type?: 'info' | 'warning' | 'success' }> = ({ 
  type = 'info' 
}) => (
  <div className={`border rounded-lg p-4 mb-6 ${getBannerStyles(type)}`}>
    <div className="flex items-start gap-3">
      <InfoIcon className="h-5 w-5 mt-0.5 flex-shrink-0" />
      <div>
        <h4 className="font-semibold mb-1">Banner Title</h4>
        <p className="text-sm">Descriptive text explaining the form's purpose or important information.</p>
      </div>
    </div>
  </div>
)

const getBannerStyles = (type: string) => {
  switch (type) {
    case 'info': return 'bg-blue-50 border-blue-200 text-blue-900'
    case 'warning': return 'bg-yellow-50 border-yellow-200 text-yellow-900'
    case 'success': return 'bg-green-50 border-green-200 text-green-900'
    default: return 'bg-blue-50 border-blue-200 text-blue-900'
  }
}

2. Form Sections

Purpose: Organize related form fields with clear visual hierarchy

tsx
const FormSection: React.FC<{ title: string; icon: React.ReactNode; children: React.ReactNode }> = ({
  title,
  icon,
  children
}) => (
  <div className="space-y-4">
    <h3 className="text-lg font-semibold text-gray-900 flex items-center gap-2">
      <div className="text-blue-600">{icon}</div>
      {title}
    </h3>
    <div className="space-y-4">
      {children}
    </div>
  </div>
)

3. Form Fields

Purpose: Consistent field styling with proper validation states

Input Fields:

tsx
<div className="space-y-2">
  <Label htmlFor="fieldId">Field Label {required && '*'}</Label>
  <Input
    id="fieldId"
    type="text"
    placeholder="Placeholder text"
    value={value}
    onChange={(e) => handleInputChange('fieldName', e.target.value)}
    className={errors.fieldName ? 'border-red-300' : ''}
  />
  {errors.fieldName && (
    <p className="text-sm text-red-600">{errors.fieldName}</p>
  )}
</div>

Select Fields:

tsx
<div className="space-y-2">
  <Label htmlFor="selectId">Select Label *</Label>
  <select
    id="selectId"
    value={value}
    onChange={(e) => handleInputChange('fieldName', e.target.value)}
    className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
  >
    <option value="">Select an option...</option>
    {options.map(option => (
      <option key={option.id} value={option.value}>
        {option.label}
      </option>
    ))}
  </select>
  {errors.fieldName && (
    <p className="text-sm text-red-600">{errors.fieldName}</p>
  )}
</div>

Textarea Fields:

tsx
<div className="space-y-2">
  <Label htmlFor="textareaId">Message *</Label>
  <Textarea
    id="textareaId"
    placeholder="Detailed description..."
    value={value}
    onChange={(e) => handleInputChange('fieldName', e.target.value)}
    className={cn("min-h-[120px] resize-none", errors.fieldName ? 'border-red-300' : '')}
  />
  {errors.fieldName && (
    <p className="text-sm text-red-600">{errors.fieldName}</p>
  )}
  <p className="text-xs text-gray-500">
    Character count: {value.length} {minLength && `(minimum ${minLength})`}
  </p>
</div>

Purpose: Consistent action area with proper button hierarchy

tsx
const FormFooter: React.FC<{ 
  isSubmitting: boolean
  onSubmit: () => void
  onCancel?: () => void 
}> = ({ isSubmitting, onSubmit, onCancel }) => (
  <div className="border-t border-gray-200 pt-6 mt-6 bg-gray-50 -mx-8 px-8 pb-8 rounded-b-lg">
    <div className="flex items-center justify-between">
      <p className="text-sm text-gray-600">* Required fields</p>
      <div className="flex gap-3">
        {onCancel && (
          <Button type="button" variant="outline" onClick={onCancel} disabled={isSubmitting}>
            Cancel
          </Button>
        )}
        <Button onClick={onSubmit} disabled={isSubmitting} className="flex items-center gap-2">
          {isSubmitting ? (
            <>
              <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
              Submitting...
            </>
          ) : (
            <>
              <Send className="w-4 h-4" />
              Submit
            </>
          )}
        </Button>
      </div>
    </div>
    <p className="text-xs text-gray-500 text-center mt-4">
      Privacy notice or additional information
    </p>
  </div>
)

Typography & Color System

Typography Hierarchy

css
/* Form Titles */
.form-title {
  @apply text-xl font-semibold text-gray-900;
}

/* Section Headers */
.section-header {
  @apply text-lg font-semibold text-gray-900;
}

/* Field Labels */
.field-label {
  @apply text-sm font-medium text-gray-700;
}

/* Help Text */
.help-text {
  @apply text-xs text-gray-500;
}

/* Error Text */
.error-text {
  @apply text-sm text-red-600;
}

Color Palette

tsx
const formColors = {
  // Text Colors
  primary: 'text-gray-900',        // Main headings
  secondary: 'text-gray-600',      // Descriptions
  muted: 'text-gray-500',          // Help text
  error: 'text-red-600',           // Error messages
  success: 'text-green-600',       // Success states

  // Background Colors
  cardBg: 'bg-white',              // Form containers
  footerBg: 'bg-gray-50',          // Footer sections
  infoBg: 'bg-blue-50',            // Info banners
  errorBg: 'bg-red-50',            // Error states

  // Border Colors
  border: 'border-gray-300',       // Default borders
  focusBorder: 'border-blue-500',  // Focus states
  errorBorder: 'border-red-300',   // Error states

  // Icon Colors
  iconPrimary: 'text-blue-600',    // Section icons
  iconMuted: 'text-gray-400',      // Supporting icons
}

Validation & Error Handling

1. Validation Function Pattern

tsx
const validateForm = (): boolean => {
  const newErrors: Partial<FormData> = {}
  
  // Required field validation
  if (!formData.email.trim()) {
    newErrors.email = 'Email is required'
  } else if (!/\S+@\S+\.\S+/.test(formData.email)) {
    newErrors.email = 'Please enter a valid email address'
  }
  
  if (!formData.message.trim()) {
    newErrors.message = 'Message is required'
  } else if (formData.message.trim().length < 10) {
    newErrors.message = 'Message must be at least 10 characters long'
  }
  
  setErrors(newErrors)
  return Object.keys(newErrors).length === 0
}

2. Real-Time Validation

tsx
const handleInputChange = (field: keyof FormData, value: string) => {
  setFormData(prev => ({ ...prev, [field]: value }))
  
  // Clear error when user starts typing
  if (errors[field]) {
    setErrors(prev => ({ ...prev, [field]: undefined }))
  }
}

3. Error Display Pattern

tsx
// Field-level errors
{errors.fieldName && (
  <p className="text-sm text-red-600 flex items-center gap-1">
    <AlertCircle className="h-4 w-4" />
    {errors.fieldName}
  </p>
)}

// Form-level error summary
{Object.keys(errors).length > 0 && (
  <div className="bg-red-50 border border-red-200 rounded-lg p-4 mb-6">
    <div className="flex items-start gap-3">
      <AlertCircle className="h-5 w-5 text-red-600 mt-0.5 flex-shrink-0" />
      <div>
        <h4 className="font-semibold text-red-900 mb-1">Please fix the following errors:</h4>
        <ul className="text-sm text-red-800 list-disc list-inside space-y-1">
          {Object.values(errors).map((error, index) => (
            <li key={index}>{error}</li>
          ))}
        </ul>
      </div>
    </div>
  </div>
)}

4. Success States

tsx
const SuccessState: React.FC<{ onReset: () => void }> = ({ onReset }) => (
  <div className="text-center">
    <div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
      <CheckCircle className="w-8 h-8 text-green-600" />
    </div>
    <h3 className="text-xl font-semibold text-gray-900 mb-2">
      Success Message
    </h3>
    <p className="text-gray-600 mb-4">
      Detailed success description
    </p>
    <p className="text-sm text-gray-500 mb-6">
      Additional instructions or next steps
    </p>
    <Button variant="outline" onClick={onReset}>
      Continue
    </Button>
  </div>
)

State Management

1. Form State Hook Pattern

tsx
interface FormState<T> {
  data: T
  errors: Partial<T>
  isSubmitting: boolean
  isSuccess: boolean
}

const useFormState = <T extends Record<string, any>>(initialData: T) => {
  const [formState, setFormState] = useState<FormState<T>>({
    data: initialData,
    errors: {},
    isSubmitting: false,
    isSuccess: false
  })

  const setData = (field: keyof T, value: any) => {
    setFormState(prev => ({
      ...prev,
      data: { ...prev.data, [field]: value },
      errors: { ...prev.errors, [field]: undefined }
    }))
  }

  const setErrors = (errors: Partial<T>) => {
    setFormState(prev => ({ ...prev, errors }))
  }

  const setSubmitting = (isSubmitting: boolean) => {
    setFormState(prev => ({ ...prev, isSubmitting }))
  }

  const setSuccess = (isSuccess: boolean) => {
    setFormState(prev => ({ ...prev, isSuccess }))
  }

  const reset = () => {
    setFormState({
      data: initialData,
      errors: {},
      isSubmitting: false,
      isSuccess: false
    })
  }

  return {
    ...formState,
    setData,
    setErrors,
    setSubmitting,
    setSuccess,
    reset
  }
}

2. Form Submission Pattern

tsx
const handleSubmit = async (e: React.FormEvent) => {
  e.preventDefault()
  
  if (!validateForm()) return

  setSubmitting(true)
  
  try {
    await onSubmit(formData)
    setSuccess(true)
    
    // Auto-close modal after success (for modals)
    if (autoClose) {
      setTimeout(() => {
        onClose()
        reset()
      }, 2000)
    }
  } catch (error) {
    console.error('Form submission error:', error)
    // Handle submission errors
  } finally {
    setSubmitting(false)
  }
}

Accessibility Guidelines

1. Keyboard Navigation

  • All interactive elements must be keyboard accessible
  • Proper tab order through form fields
  • ESC key closes modals
  • Enter key submits forms (when appropriate)

2. Screen Reader Support

tsx
// Proper labeling
<Label htmlFor="email">Email Address *</Label>
<Input
  id="email"
  aria-describedby="email-error email-help"
  aria-invalid={!!errors.email}
/>
{errors.email && (
  <p id="email-error" role="alert" className="text-sm text-red-600">
    {errors.email}
  </p>
)}
<p id="email-help" className="text-xs text-gray-500">
  We'll use this to contact you about your request
</p>

3. Focus Management

tsx
// Modal focus management
useEffect(() => {
  if (isOpen && modalRef.current) {
    const focusableElement = modalRef.current.querySelector('[tabindex="0"]')
    if (focusableElement) {
      (focusableElement as HTMLElement).focus()
    }
  }
}, [isOpen])

// Trap focus within modal
const handleKeyDown = (e: KeyboardEvent) => {
  if (e.key === 'Tab') {
    trapFocus(e, modalRef.current)
  }
  if (e.key === 'Escape') {
    onClose()
  }
}

4. Color Contrast

  • All text meets WCAG AA standards (4.5:1 contrast ratio)
  • Error states use sufficient color contrast
  • Focus indicators are clearly visible

Implementation Examples

Complete Modal Form Example

tsx
import React, { useState } from 'react'
import { Button } from '../ui/Button'
import { Input } from '../ui/Input'
import { Textarea } from '../ui/Textarea'
import { Label } from '../ui/Label'
import { X, Send, CheckCircle, Building2, Users } from 'lucide-react'
import { cn } from '../../lib/utils'

interface ModalFormData {
  name: string
  email: string
  message: string
}

interface ModalFormProps {
  isOpen: boolean
  onClose: () => void
  onSubmit?: (data: ModalFormData) => Promise<void>
}

export const ExampleModalForm: React.FC<ModalFormProps> = ({
  isOpen,
  onClose,
  onSubmit
}) => {
  const [formData, setFormData] = useState<ModalFormData>({
    name: '',
    email: '',
    message: ''
  })
  
  const [isSubmitting, setIsSubmitting] = useState(false)
  const [isSuccess, setIsSuccess] = useState(false)
  const [errors, setErrors] = useState<Partial<ModalFormData>>({})

  const validateForm = (): boolean => {
    const newErrors: Partial<ModalFormData> = {}
    
    if (!formData.name.trim()) {
      newErrors.name = 'Name is required'
    }
    if (!formData.email.trim()) {
      newErrors.email = 'Email is required'
    } else if (!/\S+@\S+\.\S+/.test(formData.email)) {
      newErrors.email = 'Please enter a valid email address'
    }
    if (!formData.message.trim()) {
      newErrors.message = 'Message is required'
    }

    setErrors(newErrors)
    return Object.keys(newErrors).length === 0
  }

  const handleInputChange = (field: keyof ModalFormData, value: string) => {
    setFormData(prev => ({ ...prev, [field]: value }))
    if (errors[field]) {
      setErrors(prev => ({ ...prev, [field]: undefined }))
    }
  }

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    
    if (!validateForm()) return

    setIsSubmitting(true)
    
    try {
      if (onSubmit) {
        await onSubmit(formData)
      }
      
      setIsSuccess(true)
      setTimeout(() => {
        onClose()
        resetForm()
      }, 2000)
    } catch (error) {
      console.error('Form submission error:', error)
    } finally {
      setIsSubmitting(false)
    }
  }

  const resetForm = () => {
    setFormData({ name: '', email: '', message: '' })
    setErrors({})
    setIsSuccess(false)
    setIsSubmitting(false)
  }

  if (!isOpen) return null

  if (isSuccess) {
    return (
      <div className="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-50">
        <div className="w-full max-w-md bg-white rounded-lg shadow-xl">
          <div className="p-8 text-center">
            <div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
              <CheckCircle className="w-8 h-8 text-green-600" />
            </div>
            <h3 className="text-xl font-semibold text-gray-900 mb-2">
              Form Submitted Successfully!
            </h3>
            <p className="text-gray-600 mb-4">
              Thank you for your submission. We'll get back to you soon.
            </p>
          </div>
        </div>
      </div>
    )
  }

  return (
    <div className="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-50">
      <div className="w-full max-w-2xl bg-white rounded-lg shadow-xl flex flex-col max-h-[90vh]">
        {/* Header */}
        <div className="flex items-center justify-between p-6 border-b border-gray-200 flex-shrink-0">
          <div>
            <h2 className="text-xl font-semibold text-gray-900">
              Example Modal Form
            </h2>
            <p className="text-sm text-gray-600 mt-1">
              Fill out this form to get in touch
            </p>
          </div>
          <Button variant="ghost" size="sm" onClick={onClose}>
            <X className="h-4 w-4" />
          </Button>
        </div>

        {/* Content */}
        <div className="flex-1 overflow-y-auto">
          <div className="p-6 space-y-6">
            {/* Info Banner */}
            <div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
              <div className="flex items-start gap-3">
                <Building2 className="h-5 w-5 text-blue-600 mt-0.5 flex-shrink-0" />
                <div>
                  <h4 className="font-semibold text-blue-900 mb-1">
                    Quick Contact Form
                  </h4>
                  <p className="text-sm text-blue-800">
                    We'll respond to your message within 24 hours during business days.
                  </p>
                </div>
              </div>
            </div>

            <form onSubmit={handleSubmit} className="space-y-6">
              {/* Contact Information */}
              <div className="space-y-4">
                <h3 className="text-lg font-semibold text-gray-900 flex items-center gap-2">
                  <Users className="h-5 w-5 text-blue-600" />
                  Contact Information
                </h3>
                
                <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                  <div className="space-y-2">
                    <Label htmlFor="name">Name *</Label>
                    <Input
                      id="name"
                      placeholder="Your full name"
                      value={formData.name}
                      onChange={(e) => handleInputChange('name', e.target.value)}
                      className={errors.name ? 'border-red-300' : ''}
                    />
                    {errors.name && (
                      <p className="text-sm text-red-600">{errors.name}</p>
                    )}
                  </div>

                  <div className="space-y-2">
                    <Label htmlFor="email">Email Address *</Label>
                    <Input
                      id="email"
                      type="email"
                      placeholder="your.email@company.com"
                      value={formData.email}
                      onChange={(e) => handleInputChange('email', e.target.value)}
                      className={errors.email ? 'border-red-300' : ''}
                    />
                    {errors.email && (
                      <p className="text-sm text-red-600">{errors.email}</p>
                    )}
                  </div>
                </div>

                <div className="space-y-2">
                  <Label htmlFor="message">Message *</Label>
                  <Textarea
                    id="message"
                    placeholder="Please describe what you need help with..."
                    value={formData.message}
                    onChange={(e) => handleInputChange('message', e.target.value)}
                    className={cn("min-h-[120px] resize-none", errors.message ? 'border-red-300' : '')}
                  />
                  {errors.message && (
                    <p className="text-sm text-red-600">{errors.message}</p>
                  )}
                </div>
              </div>
            </form>
          </div>
        </div>

        {/* Footer */}
        <div className="border-t border-gray-200 p-6 bg-gray-50 flex-shrink-0">
          <div className="flex items-center justify-between">
            <p className="text-sm text-gray-600">* Required fields</p>
            <div className="flex gap-3">
              <Button type="button" variant="outline" onClick={onClose} disabled={isSubmitting}>
                Cancel
              </Button>
              <Button onClick={handleSubmit} disabled={isSubmitting}>
                {isSubmitting ? (
                  <>
                    <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2" />
                    Submitting...
                  </>
                ) : (
                  <>
                    <Send className="w-4 h-4 mr-2" />
                    Submit
                  </>
                )}
              </Button>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

Best Practices

1. Performance Optimization

  • Debounce validation for real-time feedback
  • Memoize validation functions to prevent unnecessary re-renders
  • Lazy load complex form components when needed

2. User Experience

  • Progressive disclosure - show fields as needed
  • Clear error messages with actionable instructions
  • Loading states for all async operations
  • Success feedback with clear next steps

3. Code Organization

  • Separate concerns - validation, submission, UI components
  • Reusable components for common patterns
  • Type safety with TypeScript interfaces
  • Consistent naming conventions

4. Testing Considerations

  • Unit tests for validation functions
  • Integration tests for form submission flows
  • Accessibility tests for screen reader compatibility
  • Visual regression tests for consistent styling

Common Patterns & Reusable Components

1. FormField Wrapper Component

tsx
interface FormFieldProps {
  label: string
  error?: string
  required?: boolean
  helpText?: string
  children: React.ReactNode
}

const FormField: React.FC<FormFieldProps> = ({
  label,
  error,
  required,
  helpText,
  children
}) => (
  <div className="space-y-2">
    <Label className="text-sm font-medium text-gray-700">
      {label} {required && <span className="text-red-500">*</span>}
    </Label>
    {children}
    {error && (
      <p className="text-sm text-red-600 flex items-center gap-1">
        <AlertCircle className="h-4 w-4" />
        {error}
      </p>
    )}
    {helpText && !error && (
      <p className="text-xs text-gray-500">{helpText}</p>
    )}
  </div>
)

2. LoadingButton Component

tsx
interface LoadingButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  loading?: boolean
  loadingText?: string
  icon?: React.ReactNode
}

const LoadingButton: React.FC<LoadingButtonProps> = ({
  loading = false,
  loadingText = 'Loading...',
  icon,
  children,
  disabled,
  ...props
}) => (
  <Button disabled={disabled || loading} {...props}>
    {loading ? (
      <>
        <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2" />
        {loadingText}
      </>
    ) : (
      <>
        {icon && <span className="mr-2">{icon}</span>}
        {children}
      </>
    )}
  </Button>
)

3. FormSection Component

tsx
interface FormSectionProps {
  title: string
  icon?: React.ReactNode
  description?: string
  children: React.ReactNode
}

const FormSection: React.FC<FormSectionProps> = ({
  title,
  icon,
  description,
  children
}) => (
  <div className="space-y-4">
    <div className="border-b border-gray-200 pb-2">
      <h3 className="text-lg font-semibold text-gray-900 flex items-center gap-2">
        {icon && <span className="text-blue-600">{icon}</span>}
        {title}
      </h3>
      {description && (
        <p className="text-sm text-gray-600 mt-1">{description}</p>
      )}
    </div>
    <div className="space-y-4">
      {children}
    </div>
  </div>
)

Conclusion

This guide provides a comprehensive foundation for creating consistent, professional, and accessible forms across the StratIQX application. By following these patterns and guidelines, developers can ensure a unified user experience while maintaining code quality and accessibility standards.

Key Takeaways:

  1. Consistency is crucial - Use the same patterns across all forms
  2. User experience matters - Clear feedback, proper validation, and accessible design
  3. Code quality - Type safety, reusable components, and proper error handling
  4. Performance - Optimize for large forms and complex validation
  5. Accessibility - Design for all users from the beginning

For questions or suggestions regarding these guidelines, please refer to the implementation examples in the codebase or reach out to the development team.


Document Version: 1.0
Last Updated: August 25, 2025
Next Review: December 2025

Strategic Intelligence Hub Documentation