-
Notifications
You must be signed in to change notification settings - Fork 0
Enhance TextField component with ref support and update stories #96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| import type * as React from 'react'; | ||
| import * as React from 'react'; | ||
| import type { Control, FieldPath, FieldValues } from 'react-hook-form'; | ||
| import { | ||
| type FieldComponents, | ||
|
|
@@ -57,64 +57,57 @@ export interface TextInputProps extends Omit<InputProps, 'prefix' | 'suffix'> { | |
| label?: string; | ||
| description?: string; | ||
| components?: Partial<FieldComponents> & { | ||
| Input?: React.ComponentType<InputProps>; | ||
| Input?: React.ComponentType<InputProps & React.RefAttributes<HTMLInputElement>>; | ||
| }; | ||
| prefix?: React.ReactNode; | ||
| suffix?: React.ReactNode; | ||
| className?: string; | ||
| } | ||
|
|
||
| export const TextField = ({ | ||
| control, | ||
| name, | ||
| label, | ||
| description, | ||
| className, | ||
| components, | ||
| prefix, | ||
| suffix, | ||
| ...props | ||
| }: TextInputProps) => { | ||
| // Use the custom Input component if provided, otherwise use the default TextInput | ||
| const InputComponent = components?.Input || TextInput; | ||
| export const TextField = React.forwardRef<HTMLInputElement, TextInputProps>( | ||
| ({ control, name, label, description, className, components, prefix, suffix, ...props }, ref) => { | ||
| // Use the custom Input component if provided, otherwise use the default TextInput | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of adding forward ref, can we pass in ref as a prop for React 19 patterns? |
||
| const InputComponent = components?.Input || TextInput; | ||
|
|
||
| return ( | ||
| <FormField | ||
| control={control} | ||
| name={name} | ||
| render={({ field, fieldState }) => { | ||
| return ( | ||
| <FormItem className={className}> | ||
| {label && <FormLabel Component={components?.FormLabel}>{label}</FormLabel>} | ||
| <div | ||
| className={cn('flex group transition-all duration-200 rounded-md', { | ||
| 'field__input--with-prefix': prefix, | ||
| 'field__input--with-suffix': suffix, | ||
| 'focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background': true, | ||
| })} | ||
| > | ||
| {prefix && <FieldPrefix>{prefix}</FieldPrefix>} | ||
| <FormControl Component={components?.FormControl}> | ||
| <InputComponent | ||
| {...field} | ||
| {...props} | ||
| className={cn('focus-visible:ring-0 focus-visible:ring-offset-0 border-input', { | ||
| 'rounded-l-none border-l-0': prefix, | ||
| 'rounded-r-none border-r-0': suffix, | ||
| })} | ||
| /> | ||
| </FormControl> | ||
| {suffix && <FieldSuffix>{suffix}</FieldSuffix>} | ||
| </div> | ||
| {description && <FormDescription Component={components?.FormDescription}>{description}</FormDescription>} | ||
| {fieldState.error && ( | ||
| <FormMessage Component={components?.FormMessage}>{fieldState.error.message}</FormMessage> | ||
| )} | ||
| </FormItem> | ||
| ); | ||
| }} | ||
| /> | ||
| ); | ||
| }; | ||
| return ( | ||
| <FormField | ||
| control={control} | ||
| name={name} | ||
| render={({ field, fieldState }) => { | ||
| return ( | ||
| <FormItem className={className}> | ||
| {label && <FormLabel Component={components?.FormLabel}>{label}</FormLabel>} | ||
| <div | ||
| className={cn('flex group transition-all duration-200 rounded-md', { | ||
| 'field__input--with-prefix': prefix, | ||
| 'field__input--with-suffix': suffix, | ||
| 'focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background': true, | ||
| })} | ||
| > | ||
| {prefix && <FieldPrefix>{prefix}</FieldPrefix>} | ||
| <FormControl Component={components?.FormControl}> | ||
| <InputComponent | ||
| {...field} | ||
| {...props} | ||
| ref={ref} | ||
| className={cn('focus-visible:ring-0 focus-visible:ring-offset-0 border-input', { | ||
| 'rounded-l-none border-l-0': prefix, | ||
| 'rounded-r-none border-r-0': suffix, | ||
| })} | ||
| /> | ||
| </FormControl> | ||
| {suffix && <FieldSuffix>{suffix}</FieldSuffix>} | ||
| </div> | ||
| {description && <FormDescription Component={components?.FormDescription}>{description}</FormDescription>} | ||
| {fieldState.error && ( | ||
| <FormMessage Component={components?.FormMessage}>{fieldState.error.message}</FormMessage> | ||
| )} | ||
| </FormItem> | ||
| ); | ||
| }} | ||
| /> | ||
| ); | ||
| }, | ||
| ); | ||
|
|
||
| TextField.displayName = 'TextField'; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,12 @@ | ||
| import type * as React from 'react'; | ||
| import * as React from 'react'; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this line could still be "type" right? |
||
| import { cn } from './utils'; | ||
|
|
||
| export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {} | ||
|
|
||
| function TextInput({ className, type, ...props }: InputProps) { | ||
| const TextInput = React.forwardRef<HTMLInputElement, InputProps>(({ className, type, ...props }, ref) => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lcmohsen instead of using forward Ref, can we follow React 19's patterns for passing in refs? |
||
| return ( | ||
| <input | ||
| ref={ref} | ||
| type={type} | ||
| className={cn( | ||
| 'flex h-10 w-full text-base sm:text-sm rounded-md border border-input bg-background px-3 py-2 ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', | ||
|
|
@@ -15,6 +16,7 @@ function TextInput({ className, type, ...props }: InputProps) { | |
| {...props} | ||
| /> | ||
| ); | ||
| } | ||
| }); | ||
| TextInput.displayName = 'TextInput'; | ||
|
|
||
| export { TextInput }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of using forwardRef let's use ref for React 19 patterns