Rafi Wirana

Design Engineer

Preview
0%
Back to philosophy
Copy link

Dynamic Validation

Real-time validation feedback that guides users as they type, preventing errors before they happen. Perfect for password fields, forms, and complex input requirements.

Use at least 8 characters, including a number and a special character.

Installation

✨ No external dependencies required

Component location

components/craft/DynamicValidation/index.tsx

Usage

Basic example

import { DynamicValidation } from '@/components/craft/DynamicValidation';
import { useState } from 'react';

const passwordRules = [
  { id: "length", label: "At least 8 characters", validator: (v: string) => v.length >= 8 },
  { id: "uppercase", label: "Contains uppercase letter", validator: (v: string) => /[A-Z]/.test(v) },
  { id: "number", label: "Contains number", validator: (v: string) => /\d/.test(v) }
];

export function Example() {
  const [isValid, setIsValid] = useState(false);
  const [value, setValue] = useState("");

  return (
    <DynamicValidation
      label="Password"
      placeholder="Enter your password"
      validationRules={passwordRules}
      onValidationChange={(valid) => setIsValid(valid)}
      value={value}
      onChange={(e) => setValue(e.target.value)}
    />
  );
}

More Examples

Basic Password Validation

Basic password field with common validation rules

const passwordRules = [
  { id: "length", label: "At least 8 characters", validator: (v: string) => v.length >= 8 },
  { id: "uppercase", label: "Contains uppercase letter", validator: (v: string) => /[A-Z]/.test(v) },
  { id: "lowercase", label: "Contains lowercase letter", validator: (v: string) => /[a-z]/.test(v) },
  { id: "number", label: "Contains number", validator: (v: string) => /\d/.test(v) }
];

<DynamicValidation
  label="Password"
  placeholder="Enter your password"
  validationRules={passwordRules}
  onValidationChange={(isValid) => console.log(isValid)}
/>

With Helper Text

Add helper text that appears before validation rules

<DynamicValidation
  label="Password"
  placeholder="Enter your password"
  validationRules={passwordRules}
  helperText="Use at least 8 characters, including a number and a special character."
  onValidationChange={(isValid) => console.log(isValid)}
/>

Controlled Component

Control the input value and validation state externally

const [password, setPassword] = useState("");
const [isValid, setIsValid] = useState(false);

<DynamicValidation
  label="Password"
  value={password}
  onChange={(e) => setPassword(e.target.value)}
  validationRules={passwordRules}
  onValidationChange={setIsValid}
/>

<Button disabled={!isValid}>Submit</Button>

Custom Debounce Timing

Adjust debounce delay for validation (default: 150ms)

<DynamicValidation
  label="Password"
  validationRules={passwordRules}
  debounceMs={300}
  onValidationChange={(isValid) => console.log(isValid)}
/>

Complex Validation Rules

Use multiple validation rules with custom success message

const advancedRules = [
  { id: "length", label: "At least 12 characters", validator: (v: string) => v.length >= 12 },
  { id: "uppercase", label: "Contains uppercase letter", validator: (v: string) => /[A-Z]/.test(v) },
  { id: "lowercase", label: "Contains lowercase letter", validator: (v: string) => /[a-z]/.test(v) },
  { id: "number", label: "Contains number", validator: (v: string) => /\d/.test(v) },
  { id: "special", label: "Contains special character", validator: (v: string) => /[!@#$%^&*(),.?":{}|<>]/.test(v) },
  { id: "noSpaces", label: "No spaces", validator: (v: string) => !/\s/.test(v) }
];

<DynamicValidation
  label="Secure Password"
  validationRules={advancedRules}
  successText="Password meets all security requirements"
  onValidationChange={(isValid) => console.log(isValid)}
/>

Track Valid Rules

Access list of currently valid rule IDs

const [validRules, setValidRules] = useState<string[]>([]);

<DynamicValidation
  label="Password"
  validationRules={passwordRules}
  onValidationChange={(isValid, validRuleIds) => {
    setValidRules(validRuleIds);
    console.log('Valid rules:', validRuleIds);
  }}
/>

Email Validation

Adapt for email validation or other input types

const emailRules = [
  { id: "format", label: "Valid email format", validator: (v: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v) },
  { id: "domain", label: "From company domain", validator: (v: string) => v.endsWith("@company.com") }
];

<DynamicValidation
  label="Work Email"
  placeholder="you@company.com"
  validationRules={emailRules}
  onValidationChange={(isValid) => console.log(isValid)}
/>

API Reference

PropTypeDefaultDescription
label
stringLabel text displayed above the input field
validationRules
ValidationRule[]Array of validation rules with id, label, and validator function. Each rule checks a specific requirement.
showValidation
booleantrueWhether to show validation rules below the input
onValidationChange
(isValid: boolean, validRules: string[]) => voidCallback fired when validation state changes. Receives overall validity and array of valid rule IDs.
className
stringAdditional CSS classes for the input element
containerClassName
stringAdditional CSS classes for the root container
debounceMs
number150Debounce delay in milliseconds before running validation
helperText
stringHelper text shown below input before validation rules appear
successText
string"All requirements met"Message displayed when all validation rules pass
value
stringControlled input value. Makes component operate in controlled mode.
onChange
(e: React.ChangeEvent<HTMLInputElement>) => voidCallback fired when input value changes
id
stringCustom input ID. Auto-generated if not provided.