because I got bored of customising my CV for every job
at main 89 lines 2.3 kB view raw
1import { cva, type VariantProps } from "class-variance-authority"; 2import { cn } from "../lib/cn"; 3 4const inputVariants = cva( 5 "flex h-10 w-full rounded-md border bg-transparent px-3 py-2 text-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-ctp-subtext0 focus-visible:outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50", 6 { 7 variants: { 8 state: { 9 default: "border-ctp-surface1 focus-visible:ring-ctp-blue", 10 success: "border-ctp-green focus-visible:ring-ctp-green", 11 error: "border-ctp-red focus-visible:ring-ctp-red", 12 }, 13 }, 14 defaultVariants: { 15 state: "default", 16 }, 17 }, 18); 19 20interface TextInputProps 21 extends Omit<VariantProps<typeof inputVariants>, "state"> { 22 label?: string; 23 placeholder?: string; 24 value?: string; 25 onChange?: (value: string) => void; 26 disabled?: boolean; 27 error?: string; 28 state?: "default" | "success" | "error"; 29 type?: 30 | "text" 31 | "email" 32 | "password" 33 | "number" 34 | "tel" 35 | "url" 36 | "date" 37 | "datetime-local"; 38 className?: string; 39 id?: string; 40 required?: boolean; 41 autoComplete?: string; 42 minLength?: number; 43 pattern?: string; 44} 45 46export const TextInput = ({ 47 label, 48 placeholder, 49 value, 50 onChange, 51 disabled = false, 52 error, 53 state = "default", 54 type = "text", 55 className = "", 56 id, 57 required = false, 58 autoComplete, 59 minLength, 60 pattern, 61}: TextInputProps) => { 62 const inputId = 63 id || (label ? label.toLowerCase().replace(/\s+/g, "-") : undefined); 64 const inputState = error ? "error" : state; 65 66 return ( 67 <div className="space-y-1"> 68 {label && ( 69 <label htmlFor={inputId} className="text-sm font-medium text-ctp-text"> 70 {label} 71 </label> 72 )} 73 <input 74 id={inputId} 75 type={type} 76 placeholder={placeholder} 77 value={value} 78 onChange={(e) => onChange?.(e.target.value)} 79 disabled={disabled} 80 required={required} 81 autoComplete={autoComplete} 82 minLength={minLength} 83 pattern={pattern} 84 className={cn(inputVariants({ state: inputState }), className)} 85 /> 86 {error && <p className="text-sm text-ctp-red">{error}</p>} 87 </div> 88 ); 89};