mirror of https://github.com/acid-info/lsd.git
refactor: refactor TextField component
This commit is contained in:
parent
242868b6d9
commit
b865ef30e8
|
@ -4,8 +4,6 @@ import { iconButtonClasses } from './IconButton.classes'
|
||||||
export const IconButtonStyles = css`
|
export const IconButtonStyles = css`
|
||||||
.${iconButtonClasses.root} {
|
.${iconButtonClasses.root} {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 32px;
|
|
||||||
height: 28px;
|
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
export const textFieldClasses = {
|
export const textFieldClasses = {
|
||||||
root: `lsd-textField`,
|
root: `lsd-text-field`,
|
||||||
|
|
||||||
input: `lsd-textField__input`,
|
inputContainer: `lsd-text-field-input-container`,
|
||||||
icon: `lsd-textField__icon`,
|
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`,
|
disabled: `lsd-text-field--disabled`,
|
||||||
error: 'lsd-textField--error',
|
error: 'lsd-text-field--error',
|
||||||
|
|
||||||
large: `lsd-textField--large`,
|
large: `lsd-text-field--large`,
|
||||||
medium: `lsd-textField--medium`,
|
medium: `lsd-text-field--medium`,
|
||||||
withIcon: `lsd-textField--with-icon`,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Meta, Story } from '@storybook/react'
|
import { Meta, Story } from '@storybook/react'
|
||||||
|
import { useStorybookIconComponent } from '../../utils/storybook.utils'
|
||||||
import { TextField, TextFieldProps } from './TextField'
|
import { TextField, TextFieldProps } from './TextField'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -12,18 +13,37 @@ export default {
|
||||||
},
|
},
|
||||||
defaultValue: 'large',
|
defaultValue: 'large',
|
||||||
},
|
},
|
||||||
|
icon: {
|
||||||
|
type: {
|
||||||
|
name: 'enum',
|
||||||
|
value: useStorybookIconComponent.options,
|
||||||
|
},
|
||||||
|
defaultValue: 'FolderIcon',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as Meta
|
} as Meta
|
||||||
|
|
||||||
export const Root: Story<TextFieldProps> = (args) => (
|
export const Root: Story<Omit<TextFieldProps, 'icon'> & { icon: string }> = ({
|
||||||
<TextField {...args}>TextField</TextField>
|
icon,
|
||||||
)
|
...args
|
||||||
|
}) => {
|
||||||
|
const Icon = useStorybookIconComponent(icon)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TextField {...args} icon={Icon && <Icon color="primary" />}>
|
||||||
|
TextField
|
||||||
|
</TextField>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Root.args = {
|
Root.args = {
|
||||||
size: 'large',
|
size: 'large',
|
||||||
supportingText: 'Supporting text',
|
supportingText: 'Supporting text',
|
||||||
disabled: false,
|
disabled: false,
|
||||||
withIcon: false,
|
|
||||||
error: false,
|
error: false,
|
||||||
|
errorIcon: false,
|
||||||
|
icon: 'None',
|
||||||
|
clearButton: true,
|
||||||
placeholder: 'Placeholder',
|
placeholder: 'Placeholder',
|
||||||
defaultValue: 'default value',
|
defaultValue: 'default value',
|
||||||
onChange: undefined,
|
onChange: undefined,
|
||||||
|
|
|
@ -6,11 +6,11 @@ export const TextFieldStyles = css`
|
||||||
width: auto;
|
width: auto;
|
||||||
border-bottom: 1px solid rgb(var(--lsd-border-primary));
|
border-bottom: 1px solid rgb(var(--lsd-border-primary));
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.${textFieldClasses.root} > div {
|
.${textFieldClasses.inputContainer} {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ export const TextFieldStyles = css`
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.${textFieldClasses.error} {
|
.${textFieldClasses.error} .${textFieldClasses.input} {
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,12 +57,19 @@ export const TextFieldStyles = css`
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.${textFieldClasses.withIcon} {
|
.${textFieldClasses.clearButton} {
|
||||||
|
padding: 0;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.${textFieldClasses.icon} {
|
.${textFieldClasses.icon} {
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import React, { useRef } from 'react'
|
import React, { useRef } from 'react'
|
||||||
import { useInput } from '../../utils/useInput'
|
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 { Typography } from '../Typography'
|
||||||
import { textFieldClasses } from './TextField.classes'
|
import { textFieldClasses } from './TextField.classes'
|
||||||
|
|
||||||
|
@ -11,8 +12,10 @@ export type TextFieldProps = Omit<
|
||||||
> &
|
> &
|
||||||
Pick<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> & {
|
Pick<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> & {
|
||||||
size?: 'large' | 'medium'
|
size?: 'large' | 'medium'
|
||||||
withIcon?: boolean
|
icon?: React.ReactNode
|
||||||
error?: boolean
|
error?: boolean
|
||||||
|
errorIcon?: boolean
|
||||||
|
clearButton?: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
supportingText?: string
|
supportingText?: string
|
||||||
value?: string
|
value?: string
|
||||||
|
@ -25,13 +28,16 @@ export const TextField: React.FC<TextFieldProps> & {
|
||||||
classes: typeof textFieldClasses
|
classes: typeof textFieldClasses
|
||||||
} = ({
|
} = ({
|
||||||
size = 'large',
|
size = 'large',
|
||||||
withIcon = false,
|
icon,
|
||||||
supportingText,
|
|
||||||
error = false,
|
error = false,
|
||||||
|
errorIcon = false,
|
||||||
|
clearButton,
|
||||||
|
supportingText,
|
||||||
children,
|
children,
|
||||||
value,
|
value,
|
||||||
placeholder,
|
placeholder,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
|
disabled,
|
||||||
onChange,
|
onChange,
|
||||||
inputProps = {},
|
inputProps = {},
|
||||||
...props
|
...props
|
||||||
|
@ -43,41 +49,39 @@ export const TextField: React.FC<TextFieldProps> & {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
aria-disabled={disabled ? 'true' : 'false'}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
props.className,
|
props.className,
|
||||||
textFieldClasses.root,
|
textFieldClasses.root,
|
||||||
textFieldClasses[size],
|
textFieldClasses[size],
|
||||||
props.disabled && textFieldClasses.disabled,
|
disabled && textFieldClasses.disabled,
|
||||||
withIcon && textFieldClasses.withIcon,
|
error && textFieldClasses.error,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<div>
|
<div className={textFieldClasses.inputContainer}>
|
||||||
<input
|
<input
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
{...inputProps}
|
{...inputProps}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
value={input.value}
|
value={input.value}
|
||||||
onChange={input.onChange}
|
onChange={input.onChange}
|
||||||
className={clsx(
|
className={clsx(inputProps.className, textFieldClasses.input)}
|
||||||
inputProps.className,
|
|
||||||
textFieldClasses.input,
|
|
||||||
error && textFieldClasses.error,
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
{withIcon && error ? (
|
{error && errorIcon ? (
|
||||||
<span className={textFieldClasses.icon} onClick={onCancel}>
|
<ErrorIcon color="primary" className={textFieldClasses.icon} />
|
||||||
<ErrorIcon color="primary" className={textFieldClasses.icon} />
|
) : clearButton && input.filled ? (
|
||||||
</span>
|
<IconButton
|
||||||
) : withIcon && !input.filled ? (
|
disabled={disabled}
|
||||||
<span className={textFieldClasses.icon}>
|
onClick={() => !disabled && onCancel()}
|
||||||
<CheckIcon color="primary" />
|
aria-label="clear"
|
||||||
</span>
|
className={textFieldClasses.clearButton}
|
||||||
) : withIcon && input.filled ? (
|
>
|
||||||
<span className={textFieldClasses.icon} onClick={onCancel}>
|
<CloseIcon color="primary" className={textFieldClasses.icon} />
|
||||||
<CloseIcon color="primary" />
|
</IconButton>
|
||||||
</span>
|
) : (
|
||||||
) : null}
|
icon
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{supportingText && (
|
{supportingText && (
|
||||||
<div className={clsx(textFieldClasses.supportingText)}>
|
<div className={clsx(textFieldClasses.supportingText)}>
|
||||||
|
|
Loading…
Reference in New Issue