refactor: refactor TextField component

This commit is contained in:
Hossein Mehrabi 2023-02-23 23:50:11 +03:30
parent 242868b6d9
commit b865ef30e8
5 changed files with 77 additions and 47 deletions

View File

@ -4,8 +4,6 @@ import { iconButtonClasses } from './IconButton.classes'
export const IconButtonStyles = css`
.${iconButtonClasses.root} {
display: flex;
width: 32px;
height: 28px;
flex-direction: row;
align-items: center;
justify-content: center;

View File

@ -1,15 +1,16 @@
export const textFieldClasses = {
root: `lsd-textField`,
root: `lsd-text-field`,
input: `lsd-textField__input`,
icon: `lsd-textField__icon`,
inputContainer: `lsd-text-field-input-container`,
input: `lsd-text-field-input-container__input`,
icon: `lsd-text-field-input-container__icon`,
clearButton: `lsd-text-field-input-container__clear-button`,
supportingText: 'lsd-textField__supporting-text',
supportingText: 'lsd-text-field__supporting-text',
disabled: `lsd-textField--disabled`,
error: 'lsd-textField--error',
disabled: `lsd-text-field--disabled`,
error: 'lsd-text-field--error',
large: `lsd-textField--large`,
medium: `lsd-textField--medium`,
withIcon: `lsd-textField--with-icon`,
large: `lsd-text-field--large`,
medium: `lsd-text-field--medium`,
}

View File

@ -1,4 +1,5 @@
import { Meta, Story } from '@storybook/react'
import { useStorybookIconComponent } from '../../utils/storybook.utils'
import { TextField, TextFieldProps } from './TextField'
export default {
@ -12,18 +13,37 @@ export default {
},
defaultValue: 'large',
},
icon: {
type: {
name: 'enum',
value: useStorybookIconComponent.options,
},
defaultValue: 'FolderIcon',
},
},
} as Meta
export const Root: Story<TextFieldProps> = (args) => (
<TextField {...args}>TextField</TextField>
)
export const Root: Story<Omit<TextFieldProps, 'icon'> & { icon: string }> = ({
icon,
...args
}) => {
const Icon = useStorybookIconComponent(icon)
return (
<TextField {...args} icon={Icon && <Icon color="primary" />}>
TextField
</TextField>
)
}
Root.args = {
size: 'large',
supportingText: 'Supporting text',
disabled: false,
withIcon: false,
error: false,
errorIcon: false,
icon: 'None',
clearButton: true,
placeholder: 'Placeholder',
defaultValue: 'default value',
onChange: undefined,

View File

@ -6,11 +6,11 @@ export const TextFieldStyles = css`
width: auto;
border-bottom: 1px solid rgb(var(--lsd-border-primary));
box-sizing: border-box;
align-items: center;
}
.${textFieldClasses.root} > div {
.${textFieldClasses.inputContainer} {
display: flex;
align-items: center;
justify-content: space-between;
}
@ -36,7 +36,7 @@ export const TextFieldStyles = css`
opacity: 0.3;
}
.${textFieldClasses.error} {
.${textFieldClasses.error} .${textFieldClasses.input} {
text-decoration: line-through;
}
@ -57,12 +57,19 @@ export const TextFieldStyles = css`
padding: 6px 12px;
}
.${textFieldClasses.withIcon} {
.${textFieldClasses.clearButton} {
padding: 0;
width: auto;
height: auto;
margin: 0;
border: 0;
svg {
width: 100%;
height: auto;
}
}
.${textFieldClasses.icon} {
cursor: pointer;
display: flex;
align-items: center;
}
`

View File

@ -1,7 +1,8 @@
import clsx from 'clsx'
import React, { useRef } from 'react'
import { useInput } from '../../utils/useInput'
import { CheckIcon, CloseIcon, ErrorIcon } from '../Icons'
import { IconButton } from '../IconButton'
import { CloseIcon, ErrorIcon } from '../Icons'
import { Typography } from '../Typography'
import { textFieldClasses } from './TextField.classes'
@ -11,8 +12,10 @@ export type TextFieldProps = Omit<
> &
Pick<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> & {
size?: 'large' | 'medium'
withIcon?: boolean
icon?: React.ReactNode
error?: boolean
errorIcon?: boolean
clearButton?: boolean
disabled?: boolean
supportingText?: string
value?: string
@ -25,13 +28,16 @@ export const TextField: React.FC<TextFieldProps> & {
classes: typeof textFieldClasses
} = ({
size = 'large',
withIcon = false,
supportingText,
icon,
error = false,
errorIcon = false,
clearButton,
supportingText,
children,
value,
placeholder,
defaultValue,
disabled,
onChange,
inputProps = {},
...props
@ -43,41 +49,39 @@ export const TextField: React.FC<TextFieldProps> & {
return (
<div
aria-disabled={disabled ? 'true' : 'false'}
className={clsx(
props.className,
textFieldClasses.root,
textFieldClasses[size],
props.disabled && textFieldClasses.disabled,
withIcon && textFieldClasses.withIcon,
disabled && textFieldClasses.disabled,
error && textFieldClasses.error,
)}
{...props}
>
<div>
<div className={textFieldClasses.inputContainer}>
<input
placeholder={placeholder}
{...inputProps}
ref={ref}
value={input.value}
onChange={input.onChange}
className={clsx(
inputProps.className,
textFieldClasses.input,
error && textFieldClasses.error,
)}
className={clsx(inputProps.className, textFieldClasses.input)}
/>
{withIcon && error ? (
<span className={textFieldClasses.icon} onClick={onCancel}>
<ErrorIcon color="primary" className={textFieldClasses.icon} />
</span>
) : withIcon && !input.filled ? (
<span className={textFieldClasses.icon}>
<CheckIcon color="primary" />
</span>
) : withIcon && input.filled ? (
<span className={textFieldClasses.icon} onClick={onCancel}>
<CloseIcon color="primary" />
</span>
) : null}
{error && errorIcon ? (
<ErrorIcon color="primary" className={textFieldClasses.icon} />
) : clearButton && input.filled ? (
<IconButton
disabled={disabled}
onClick={() => !disabled && onCancel()}
aria-label="clear"
className={textFieldClasses.clearButton}
>
<CloseIcon color="primary" className={textFieldClasses.icon} />
</IconButton>
) : (
icon
)}
</div>
{supportingText && (
<div className={clsx(textFieldClasses.supportingText)}>