From fc0cc0aa5a8b6e9faf77aff956169a59f22b98a1 Mon Sep 17 00:00:00 2001 From: HyeongKyeom Kim <97586683+Brokyeom@users.noreply.github.com> Date: Thu, 16 Jan 2025 17:27:53 +0900 Subject: [PATCH] =?UTF-8?q?feat(ui):=20TextField=20rigntAddon=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80.=20(#238)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add rightAddon option. * feat: Enhance TextField component with additional props and rightAddon support * cs * refactor: Change TextFieldProps to interface for consistency --- .changeset/tough-mails-camp.md | 5 ++++ apps/docs/src/stories/TextField.stories.tsx | 28 +++++++++++++++++++-- packages/ui/Input/TextField.tsx | 7 +++++- packages/ui/Input/style.css.ts | 18 ++++++++++--- 4 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 .changeset/tough-mails-camp.md diff --git a/.changeset/tough-mails-camp.md b/.changeset/tough-mails-camp.md new file mode 100644 index 00000000..ffde4cd6 --- /dev/null +++ b/.changeset/tough-mails-camp.md @@ -0,0 +1,5 @@ +--- +'@sopt-makers/ui': patch +--- + +Add rightAddon prop in TextField. diff --git a/apps/docs/src/stories/TextField.stories.tsx b/apps/docs/src/stories/TextField.stories.tsx index 1b315fb9..070cd7a1 100644 --- a/apps/docs/src/stories/TextField.stories.tsx +++ b/apps/docs/src/stories/TextField.stories.tsx @@ -1,13 +1,21 @@ -import { ChangeEvent, useState, type InputHTMLAttributes } from 'react'; +import { ChangeEvent, ReactNode, useState, type InputHTMLAttributes } from 'react'; import { StoryObj } from '@storybook/react'; import { TextField } from '@sopt-makers/ui'; +import { IconSend } from '@sopt-makers/icons'; interface TextFieldProps extends Omit, 'value'> { + className?: string; + topAddon?: ReactNode; + bottomAddon?: ReactNode; + rightAddon?: ReactNode; labelText?: string; descriptionText?: string; - value: string; + required?: boolean; errorMessage?: string; + value?: string; + // isError -> validationFn 순서로 적용 isError?: boolean; + validationFn?: (input: string) => boolean; } const useTextField = (props: TextFieldProps) => { @@ -20,6 +28,10 @@ const useTextField = (props: TextFieldProps) => { return ; }; +/** + * `TextField` 컴포넌트는 **[FieldBox](https://main--6571c88390d085ed7efcce84.chromatic.com/?path=/docs/components-fieldbox--docs)**를 부모 컴포넌트로 삼는 Input 컴포넌트입니다. + */ + export default { title: 'Components/Input/TextField', component: useTextField, @@ -137,3 +149,15 @@ export const Error: StoryObj = { disabled: false, }, }; + +export const HasRightAddon: StoryObj = { + args: { + labelText: 'Label', + descriptionText: 'Description', + placeholder: 'Placeholder...', + rightAddon: , + required: true, + readOnly: false, + disabled: false, + }, +}; diff --git a/packages/ui/Input/TextField.tsx b/packages/ui/Input/TextField.tsx index a274db4e..77a6294f 100644 --- a/packages/ui/Input/TextField.tsx +++ b/packages/ui/Input/TextField.tsx @@ -6,6 +6,7 @@ interface TextFieldProps extends Omit, 'va className?: string; topAddon?: ReactNode; bottomAddon?: ReactNode; + rightAddon?: ReactNode; labelText?: string; descriptionText?: string; required?: boolean; @@ -21,6 +22,7 @@ const TextField = forwardRef((props, ref) => { className, topAddon, bottomAddon, + rightAddon, labelText, descriptionText, required, @@ -60,7 +62,10 @@ const TextField = forwardRef((props, ref) => { ) } > - +
+ + {rightAddon} +
); }); diff --git a/packages/ui/Input/style.css.ts b/packages/ui/Input/style.css.ts index cf38cb04..f903e229 100644 --- a/packages/ui/Input/style.css.ts +++ b/packages/ui/Input/style.css.ts @@ -23,8 +23,8 @@ export const label = style({ color: theme.colors.white, }); -export const input = style({ - ...theme.fontsObject.BODY_2_16_M, +export const inputWrapper = style({ + 'display': 'flex', 'background': theme.colors.gray800, 'border': '1px solid transparent', 'borderRadius': '10px', @@ -34,11 +34,23 @@ export const input = style({ 'color': theme.colors.white, 'boxSizing': 'border-box', + ':focus-within': { + border: `1px solid ${theme.colors.gray200}`, + }, +}); + +export const input = style({ + ...theme.fontsObject.BODY_2_16_M, + 'flex': 1, + 'border': 0, + 'background': 'transparent', + 'color': theme.colors.white, + 'boxSizing': 'border-box', + '::placeholder': { color: theme.colors.gray300, }, ':focus': { - border: `1px solid ${theme.colors.gray200}`, outline: 'none', }, ':disabled': {