From 2b53c8660816e34e34e619904e66ff96d12f9d2d Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Sat, 18 Feb 2023 05:15:49 +0900 Subject: [PATCH] feat: implement textField component --- .../components/CSSBaseline/CSSBaseline.tsx | 2 + .../components/Icons/CheckIcon/CheckIcon.tsx | 35 ++++---- .../components/TextField/TextField.classes.ts | 16 ++++ .../TextField/TextField.stories.tsx | 28 ++++++ .../components/TextField/TextField.styles.ts | 76 ++++++++++++++++ .../src/components/TextField/TextField.tsx | 87 +++++++++++++++++++ .../src/components/TextField/index.ts | 1 + 7 files changed, 230 insertions(+), 15 deletions(-) create mode 100644 packages/lsd-react/src/components/TextField/TextField.classes.ts create mode 100644 packages/lsd-react/src/components/TextField/TextField.stories.tsx create mode 100644 packages/lsd-react/src/components/TextField/TextField.styles.ts create mode 100644 packages/lsd-react/src/components/TextField/TextField.tsx create mode 100644 packages/lsd-react/src/components/TextField/index.ts diff --git a/packages/lsd-react/src/components/CSSBaseline/CSSBaseline.tsx b/packages/lsd-react/src/components/CSSBaseline/CSSBaseline.tsx index bdc53fa..1f2d353 100644 --- a/packages/lsd-react/src/components/CSSBaseline/CSSBaseline.tsx +++ b/packages/lsd-react/src/components/CSSBaseline/CSSBaseline.tsx @@ -12,6 +12,7 @@ import { BreadcrumbStyles } from '../Breadcrumb/Breadcrumb.styles' import { BreadcrumbItemStyles } from '../BreadcrumbItem/BreadcrumbItem.styles' import { defaultThemes, Theme, withTheme } from '../Theme' import { TypographyStyles } from '../Typography/Typography.styles' +import { TextFieldStyles } from '../TextField/TextField.styles' const componentStyles: Array | SerializedStyles> = [ @@ -26,6 +27,7 @@ const componentStyles: Array | SerializedStyles> = IconTagStyles, BreadcrumbStyles, BreadcrumbItemStyles, + TextFieldStyles, ] export const CSSBaseline: React.FC<{ theme?: Theme }> = ({ diff --git a/packages/lsd-react/src/components/Icons/CheckIcon/CheckIcon.tsx b/packages/lsd-react/src/components/Icons/CheckIcon/CheckIcon.tsx index d1a56a0..fd8da9d 100644 --- a/packages/lsd-react/src/components/Icons/CheckIcon/CheckIcon.tsx +++ b/packages/lsd-react/src/components/Icons/CheckIcon/CheckIcon.tsx @@ -1,17 +1,22 @@ import { LsdIcon } from '../LsdIcon' -export const CheckIcon = LsdIcon((props) => ( - - - -)) +export const CheckIcon = LsdIcon( + (props) => ( + + + + ), + { + filled: true, + }, +) diff --git a/packages/lsd-react/src/components/TextField/TextField.classes.ts b/packages/lsd-react/src/components/TextField/TextField.classes.ts new file mode 100644 index 0000000..ab3c2bd --- /dev/null +++ b/packages/lsd-react/src/components/TextField/TextField.classes.ts @@ -0,0 +1,16 @@ +export const textFieldClasses = { + root: `lsd-textField`, + + input: `lsd-textField__input`, + filled: `lsd-textField__icon`, + + supportingText: 'lsd-textField__supporting-text', + supportingTextLarge: 'lsd-textField__supporting-text--large', + supportingTextMedium: 'lsd-textField__supporting-text--medium', + + disabled: `lsd-textField--disabled`, + error: 'lsd-textField--error', + large: `lsd-textField--large`, + medium: `lsd-textField--medium`, + withIcon: `lsd-textField--with-icon`, +} diff --git a/packages/lsd-react/src/components/TextField/TextField.stories.tsx b/packages/lsd-react/src/components/TextField/TextField.stories.tsx new file mode 100644 index 0000000..ac489a7 --- /dev/null +++ b/packages/lsd-react/src/components/TextField/TextField.stories.tsx @@ -0,0 +1,28 @@ +import { Meta, Story } from '@storybook/react' +import { TextField, TextFieldProps } from './TextField' + +export default { + title: 'TextField', + component: TextField, + argTypes: { + size: { + type: { + name: 'enum', + value: ['medium', 'large'], + }, + defaultValue: 'large', + }, + }, +} as Meta + +export const Root: Story = (args) => ( + TextField +) +Root.args = { + size: 'large', + supportingText: 'Supporting text', + disabled: false, + withIcon: false, + error: false, + placeholder: 'Placeholder', +} diff --git a/packages/lsd-react/src/components/TextField/TextField.styles.ts b/packages/lsd-react/src/components/TextField/TextField.styles.ts new file mode 100644 index 0000000..c7bceeb --- /dev/null +++ b/packages/lsd-react/src/components/TextField/TextField.styles.ts @@ -0,0 +1,76 @@ +import { css } from '@emotion/react' +import { textFieldClasses } from './TextField.classes' + +export const TextFieldStyles = css` + .${textFieldClasses.root} { + width: auto; + border-bottom: 1px solid rgb(var(--lsd-border-primary)); + box-sizing: border-box; + display: flex; + align-items: center; + } + + .${textFieldClasses.input} { + border: none; + outline: none; + font-size: 14px; + color: rgb(var(--lsd-text-primary)); + background: none; + width: inherit; + } + + .${textFieldClasses.input}:hover { + outline: none; + } + + .${textFieldClasses.input}::placeholder { + color: rgb(var(--lsd-text-primary)); + opacity: 0.3; + } + + .${textFieldClasses.disabled} { + cursor: default; + opacity: 0.34; + } + + .${textFieldClasses.error} { + text-decoration: line-through; + } + + .${textFieldClasses.supportingText} { + width: fit-content; + font-size: 12px; + line-height: 16px; + } + + .${textFieldClasses.large} { + width: 208px; + height: 40px; + padding: 10px 14px; + } + + .${textFieldClasses.medium} { + width: 188px; + height: 32px; + padding: 6px 12px; + } + + .${textFieldClasses.supportingTextLarge} { + margin: 8px 14px; + } + + .${textFieldClasses.supportingTextMedium} { + margin: 8px 12px; + } + + .${textFieldClasses.withIcon} { + } + + .${textFieldClasses.filled} { + cursor: pointer; + display: flex; + svg path { + --lsd-icon-primary: var(--lsd-icon-primary); + } + } +` diff --git a/packages/lsd-react/src/components/TextField/TextField.tsx b/packages/lsd-react/src/components/TextField/TextField.tsx new file mode 100644 index 0000000..ce4ebd9 --- /dev/null +++ b/packages/lsd-react/src/components/TextField/TextField.tsx @@ -0,0 +1,87 @@ +import clsx from 'clsx' +import React, { useState } from 'react' +import { CheckIcon, CloseIcon, ErrorIcon } from '../Icons' +import { Typography } from '../Typography' +import { textFieldClasses } from './TextField.classes' + +export type TextFieldProps = React.InputHTMLAttributes & { + size?: 'large' | 'medium' + withIcon?: boolean + error?: boolean + supportingText?: string +} + +export const TextField: React.FC & { + classes: typeof textFieldClasses +} = ({ + size = 'large', + withIcon = 'false', + supportingText = 'Supporting text', + error = false, + children, + ...props +}) => { + const [inputValue, setInputValue] = useState('') + + const onChange = (e: React.FormEvent) => { + const newValue = e.currentTarget.value + setInputValue(newValue) + } + + const onCancel = () => { + setInputValue('') + } + + return ( + <> +
+ + {withIcon && error ? ( + + + + ) : withIcon && !inputValue.length ? ( + + + + ) : withIcon && inputValue.length ? ( + + + + ) : null} +
+ {supportingText && ( + + {supportingText} + + )} + + ) +} + +TextField.classes = textFieldClasses diff --git a/packages/lsd-react/src/components/TextField/index.ts b/packages/lsd-react/src/components/TextField/index.ts new file mode 100644 index 0000000..dd7d2ac --- /dev/null +++ b/packages/lsd-react/src/components/TextField/index.ts @@ -0,0 +1 @@ +export * from './TextField'