feat(ui): add size and variant props to Input component
- add `size` prop (sm | md | lg) with corresponding tailwind size classes - add `variant` prop supporting `default` and `ghost` styles - add focus state tracking to enable ghost→default transition on focus - forward `onFocus` and `onBlur` callbacks with internal focus handling - isolate color input styling from size/variant logic
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const Input = ({
|
||||
type = 'text',
|
||||
@@ -16,11 +16,33 @@ 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;
|
||||
@@ -42,7 +64,19 @@ 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 (
|
||||
<div className="flex gap-2">
|
||||
@@ -64,7 +98,7 @@ const Input = ({
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
className={`${baseInputClassName} flex-1 min-w-0`}
|
||||
className={`${colorBaseClassName} flex-1 min-w-0`}
|
||||
value={value || ''}
|
||||
onChange={handleChange}
|
||||
placeholder={placeholder || 'Enter hex color'}
|
||||
@@ -91,6 +125,8 @@ const Input = ({
|
||||
type={type}
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
placeholder={placeholder}
|
||||
className={baseInputClassName}
|
||||
disabled={disabled}
|
||||
|
||||
Reference in New Issue
Block a user