diff --git a/src/shared/components/Input.js b/src/shared/components/Input.js index 80d820a..aa623f3 100644 --- a/src/shared/components/Input.js +++ b/src/shared/components/Input.js @@ -1,6 +1,6 @@ 'use client'; -import React from 'react'; +import React, { useState } from 'react'; const Input = ({ type = 'text', @@ -16,15 +16,37 @@ const Input = ({ min, max, step, + size = 'md', + variant = 'default', + onFocus, + onBlur, ...props }) => { - const baseInputClassName = `w-full px-[10px] py-[7px] rounded-lg text-[13px] focus:outline-none transition-all duration-[120ms] ease-out disabled:opacity-50 disabled:cursor-not-allowed bg-white border border-neutral-300 text-neutral-900 placeholder-neutral-400 focus:border-neutral-500 focus:ring-1 focus:ring-neutral-500/20 dark:bg-neutral-900/60 dark:border-neutral-700/50 dark:text-white dark:placeholder-neutral-500 dark:focus:border-neutral-600 dark:focus:ring-neutral-600/20 ${ - error ? 'border-red-500/50 dark:border-red-500/50' : '' - } ${className}`; + const [focused, setFocused] = useState(false); + + const sizeClasses = { + sm: 'px-[8px] py-[5px] text-[12px]', + md: 'px-[10px] py-[7px] text-[13px]', + lg: 'px-[14px] py-[10px] text-[20px] font-semibold', + }; + + const defaultVariant = 'bg-white border border-neutral-300 text-neutral-900 placeholder-neutral-400 focus:border-neutral-500 focus:ring-1 focus:ring-neutral-500/20 dark:bg-neutral-900/60 dark:border-neutral-700/50 dark:text-white dark:placeholder-neutral-500 dark:focus:border-neutral-600 dark:focus:ring-neutral-600/20'; + + // Ghost : bordure transparente + texte gris au repos. Au focus, prend l'apparence default. + const ghostRest = 'bg-transparent border border-transparent text-neutral-500 placeholder-neutral-400 dark:text-neutral-400 dark:placeholder-neutral-600'; + const ghostFocus = defaultVariant; + + const variantClasses = variant === 'ghost' + ? (focused ? ghostFocus : ghostRest) + : defaultVariant; + + const errorClasses = error ? 'border-red-500/50 dark:border-red-500/50' : ''; + + const baseInputClassName = `w-full rounded-lg focus:outline-none transition-all duration-[120ms] ease-out disabled:opacity-50 disabled:cursor-not-allowed ${sizeClasses[size] || sizeClasses.md} ${variantClasses} ${errorClasses} ${className}`; const handleChange = (e) => { let newValue = e.target.value; - + // Handle number type conversions if (type === 'number') { // Convert empty string to 0 for numeric inputs to prevent database errors @@ -38,11 +60,23 @@ const Input = ({ } } } - + onChange?.(newValue); }; - // Enhanced color input renderer + const handleFocus = (e) => { + setFocused(true); + onFocus?.(e); + }; + + const handleBlur = (e) => { + setFocused(false); + onBlur?.(e); + }; + + // Color input — non concerné par size/variant, garde son apparence dédiée. + const colorBaseClassName = `w-full px-[10px] py-[7px] rounded-lg text-[13px] focus:outline-none transition-all duration-[120ms] ease-out disabled:opacity-50 disabled:cursor-not-allowed ${defaultVariant} ${errorClasses}`; + const renderColorInput = () => { return (
{error}
)} - + {description && !error && ({description}
)} @@ -112,4 +148,4 @@ const Input = ({ ); }; -export default Input; \ No newline at end of file +export default Input;