From b269728ecdc9e62fa8fb43255fc2908127f756b0 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 21 Oct 2025 10:38:07 +0700 Subject: [PATCH] feat(FE-114): add CheckboxInput component with customizable props and styling --- src/components/input/CheckboxInput.tsx | 279 +++++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 src/components/input/CheckboxInput.tsx diff --git a/src/components/input/CheckboxInput.tsx b/src/components/input/CheckboxInput.tsx new file mode 100644 index 00000000..b8d5ba5e --- /dev/null +++ b/src/components/input/CheckboxInput.tsx @@ -0,0 +1,279 @@ +'use client'; + +import { ChangeEventHandler, FocusEventHandler, ReactNode } from 'react'; + +import { cn } from '@/lib/helper'; +import FieldMessage from '@/components/helper/FieldMessage'; + +export interface CheckboxInputProps { + // Basic Props + name: string; + label?: string; + bottomLabel?: string; + checked?: boolean; + value?: string | number; + indeterminate?: boolean; + naked?: boolean; // New prop for checkbox-only mode + + // Styling Props + className?: { + wrapper?: string; + label?: string; + checkbox?: string; + input?: string; + }; + + // State Props + isError?: boolean; + isValid?: boolean; + errorMessage?: string; + disabled?: boolean; + readOnly?: boolean; + required?: boolean; + isLoading?: boolean; + + // Adornment Props + startAdornment?: ReactNode; + endAdornment?: ReactNode; + + // Event Handlers + onChange?: ChangeEventHandler; + onBlur?: FocusEventHandler; + onFocus?: FocusEventHandler; + + // Additional Props + tooltip?: string; + description?: string; + size?: 'sm' | 'md' | 'lg'; + variant?: + | 'default' + | 'primary' + | 'secondary' + | 'success' + | 'warning' + | 'info' + | 'error'; +} + +const CheckboxInput = ({ + name, + label, + bottomLabel, + checked = false, + value, + indeterminate = false, + naked = false, + className, + isError, + errorMessage, + disabled = false, + readOnly = false, + required = false, + isLoading = false, + startAdornment, + endAdornment, + onChange, + onBlur, + onFocus, + tooltip, + description, + size = 'md', + variant = 'default', +}: CheckboxInputProps) => { + const showErrorMessage = Boolean(isError && errorMessage); + const feedbackMessage = showErrorMessage ? errorMessage : bottomLabel; + + // Size classes + const sizeClasses = { + sm: 'checkbox-sm', + md: 'checkbox-md', + lg: 'checkbox-lg', + }; + + // Variant classes + const variantClasses = { + default: '', + primary: 'checkbox-primary', + secondary: 'checkbox-secondary', + success: 'checkbox-success', + warning: 'checkbox-warning', + info: 'checkbox-info', + error: 'checkbox-error', + }; + + // Generate unique ID for accessibility + const checkboxId = `checkbox-${name}-${Math.random().toString(36).substr(2, 9)}`; + + // Naked mode - only checkbox, no wrapper structure + if (naked) { + return ( +
+ { + if (input) { + input.indeterminate = indeterminate; + } + }} + /> + + {/* Loading State */} + {isLoading && ( +
+ +
+ )} +
+ ); + } + + return ( +
+ {/* Label with Tooltip Support */} + {label && ( + + )} + + {/* Description */} + {description && ( +

+ {description} +

+ )} + + {/* Field Message */} + +
+ ); +}; + +export default CheckboxInput;