Lê Phi Nam
Deploy to HF Space
94004a2
Raw
History Blame Contribute Delete
2.44 kB
import React, { forwardRef, useId } from 'react';
import './Input.css';
/**
* Field — optional wrapper for label + input + hint/error.
*
* @param label string rendered above the control
* @param hint small muted helper text below
* @param error string error message (overrides hint, adds error state)
* @param icon optional leading icon node (for Input variant)
*/
export function Field({ label, hint, error, icon, children }) {
const id = useId();
const describedBy = error ? `${id}-err` : hint ? `${id}-hint` : undefined;
const enriched = React.Children.map(children, (child) => {
if (!React.isValidElement(child)) return child;
return React.cloneElement(child, {
id: child.props.id || id,
'aria-invalid': error ? true : undefined,
'aria-describedby': describedBy,
});
});
return (
<div className={`ui-field ${error ? 'is-error' : ''}`}>
{label && <label htmlFor={id} className="ui-field__label">{label}</label>}
<div className="ui-field__control">
{icon && <span className="ui-field__icon" aria-hidden="true">{icon}</span>}
{enriched}
</div>
{error && <div id={`${id}-err`} className="ui-field__error">{error}</div>}
{!error && hint && <div id={`${id}-hint`} className="ui-field__hint">{hint}</div>}
</div>
);
}
/**
* Input — text / number / email / url input.
* Replaces bare <input className="input-base" />.
*/
export const Input = forwardRef(function Input(
{ size = 'md', className = '', ...rest },
ref,
) {
return (
<input
ref={ref}
className={`ui-input ui-input--size-${size} ${className}`}
{...rest}
/>
);
});
/**
* Textarea — multi-line input with optional auto-sizing.
*/
export const Textarea = forwardRef(function Textarea(
{ size = 'md', rows = 3, className = '', ...rest },
ref,
) {
return (
<textarea
ref={ref}
rows={rows}
className={`ui-input ui-textarea ui-input--size-${size} ${className}`}
{...rest}
/>
);
});
/**
* Select — styled native select (keeps keyboard + accessibility for free).
*/
export const Select = forwardRef(function Select(
{ size = 'md', className = '', children, ...rest },
ref,
) {
return (
<select
ref={ref}
className={`ui-input ui-select ui-input--size-${size} ${className}`}
{...rest}
>
{children}
</select>
);
});
export default Input;