mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-11 09:51:30 +00:00
* refactor: replace old Checkbox component and Added new TextInput, MaskedInput, and Select components - Deleted the old Checkbox and StyledWrapper components from the components directory. - Introduced a new Checkbox component with enhanced features including indeterminate state and customizable icons. - Added a new StyledWrapper for the Checkbox to manage styles and layout. - Created InputWrapper and StyledWrapper components for consistent form field handling. - Added new TextInput, MaskedInput, and Select components with their respective styles for improved UI consistency. * refactor: enhance Checkbox, InputWrapper, and Select components with accessibility improvements - Added useId for unique ID generation in Checkbox and Select components, improving accessibility. - Updated Checkbox to use generated IDs for aria attributes and labels. - Refactored InputWrapper to accept and apply generated IDs for label, description, and error elements. - Modified Select component to include aria attributes for better screen reader support. - Adjusted StyledWrapper imports to reference constants for consistent styling across components.
109 lines
3.3 KiB
JavaScript
109 lines
3.3 KiB
JavaScript
import React, { useState } from 'react';
|
|
import InputWrapper from 'ui/InputWrapper';
|
|
import StyledWrapper from './StyledWrapper';
|
|
|
|
/**
|
|
* TextInput - A form text input component
|
|
*
|
|
* @param {string} props.value - Controlled input value
|
|
* @param {function} props.onChange - Called with the input change event
|
|
* @param {string} props.id - Input id attribute
|
|
* @param {string} props.name - Input name attribute (defaults to id)
|
|
* @param {string} props.type - Input type: 'text' | 'number' | 'email' | 'url' (default: 'text')
|
|
* @param {string} props.placeholder - Placeholder text
|
|
* @param {boolean} props.disabled - Disables the input
|
|
* @param {string} props.error - Error message displayed below the input
|
|
* @param {string} props.label - Label text displayed above the input
|
|
* @param {string} props.description - Description text below the label
|
|
* @param {boolean} props.required - Shows asterisk on label
|
|
* @param {ReactNode} props.leftSection - Element rendered on the left side
|
|
* @param {ReactNode} props.rightSection - Element rendered on the right side
|
|
* @param {string} props.size - Input size: 'sm' | 'md' (default: 'md')
|
|
* @param {string} props.className - Additional CSS class for the wrapper
|
|
* @param {boolean} props.autoFocus - Auto-focus on mount
|
|
* @param {boolean} props.readOnly - Makes input read-only
|
|
* @param {string} props.autoComplete - HTML autoComplete attribute
|
|
* @param {number} props.maxLength - Max character length
|
|
* @param {number} props.min - Min value for type="number"
|
|
* @param {number} props.max - Max value for type="number"
|
|
* @param {number} props.step - Step value for type="number"
|
|
*/
|
|
const TextInput = ({
|
|
value,
|
|
onChange,
|
|
id,
|
|
name,
|
|
type = 'text',
|
|
placeholder,
|
|
disabled = false,
|
|
error,
|
|
label,
|
|
description,
|
|
required = false,
|
|
leftSection,
|
|
rightSection,
|
|
size = 'md',
|
|
className,
|
|
autoFocus,
|
|
readOnly,
|
|
autoComplete,
|
|
maxLength,
|
|
min,
|
|
max,
|
|
step,
|
|
'data-testid': testId
|
|
}) => {
|
|
const [isFocused, setIsFocused] = useState(false);
|
|
|
|
const wrapperClasses = [
|
|
'text-input-wrapper',
|
|
'textbox',
|
|
isFocused ? 'text-input-focused' : '',
|
|
error ? 'text-input-error' : '',
|
|
disabled ? 'text-input-disabled' : ''
|
|
]
|
|
.filter(Boolean)
|
|
.join(' ');
|
|
|
|
return (
|
|
<InputWrapper
|
|
label={label}
|
|
description={description}
|
|
error={error}
|
|
htmlFor={id}
|
|
required={required}
|
|
size={size}
|
|
className={className}
|
|
>
|
|
<StyledWrapper $size={size}>
|
|
<div className={wrapperClasses}>
|
|
{leftSection && <span className="text-input-left-section">{leftSection}</span>}
|
|
<input
|
|
id={id}
|
|
type={type}
|
|
name={name || id}
|
|
className="text-input-field"
|
|
value={value}
|
|
onChange={onChange}
|
|
placeholder={placeholder}
|
|
disabled={disabled}
|
|
data-testid={testId}
|
|
readOnly={readOnly}
|
|
autoFocus={autoFocus}
|
|
autoComplete={autoComplete}
|
|
maxLength={maxLength}
|
|
min={min}
|
|
max={max}
|
|
step={step}
|
|
onFocus={() => setIsFocused(true)}
|
|
onBlur={() => setIsFocused(false)}
|
|
/>
|
|
{rightSection && <span className="text-input-right-section">{rightSection}</span>}
|
|
</div>
|
|
</StyledWrapper>
|
|
</InputWrapper>
|
|
);
|
|
};
|
|
|
|
export default TextInput;
|