Skip to content

Commit

Permalink
feat: TextField 컴포넌트 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
bytrustu committed Mar 1, 2024
1 parent 9c204c7 commit fc62f8c
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/shared/components/Box/Box.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const WithPadding: Story = {

export const WithBorder: Story = {
args: {
border: `2px solid ${styleToken.color.gray500}`,
border: `2px solid ${styleToken.color.gray600}`,
},
};

Expand All @@ -65,7 +65,7 @@ export const WithChildren: Story = {
display="flex"
alignItems="center"
justifyContent="center"
backgroundColor={styleToken.color.teal}
backgroundColor={styleToken.color.teal100}
width="100px"
height="100px"
>
Expand Down
4 changes: 2 additions & 2 deletions src/shared/components/HStack/HStack.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const WithPadding: Story = {

export const WithBorder: Story = {
args: {
border: `2px solid ${styleToken.color.gray500}`,
border: `2px solid ${styleToken.color.gray600}`,
},
};

Expand All @@ -61,7 +61,7 @@ export const WithChildren: Story = {
<HStack
alignItems="center"
justifyContent="center"
backgroundColor={styleToken.color.teal}
backgroundColor={styleToken.color.teal100}
width="100px"
height="100px"
>
Expand Down
93 changes: 93 additions & 0 deletions src/shared/components/TextField/TextField.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import type { Meta, StoryObj } from '@storybook/react';
import { AppLayout } from '@/components';
import { TextField } from '@/shared/components';
import { letterSpacingValue, storybookControls, styleToken } from '@/shared/styles';

const FONT_SIZE = 18;
const LETTER_SPACING = letterSpacingValue(FONT_SIZE, -8.5);

const meta: Meta = {
title: 'Primitive/TextField',
component: TextField,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
...storybookControls.argTypes,
type: {
options: ['text', 'password', 'email', 'number', 'tel', 'url'],
},
},
args: {
as: 'input',
type: 'text',
variant: 'outline',
width: styleToken.width.w100,
height: '45px',
padding: '13px 12px 13px 11px',
borderRadius: '6px',
fontSize: `${FONT_SIZE}px`,
placeholder: '카드에 표시된 이름과 동일하게 입력하세요.',
_placeholder: {
letterSpacing: LETTER_SPACING,
},
autoFocus: true,
},
decorators: [
(Story) => (
<AppLayout>
<Story />
</AppLayout>
),
],
} satisfies Meta<typeof TextField>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Primary: Story = {};

export const Password: Story = {
args: {
type: 'password',
},
};

export const WithFocusOutlineStyle: Story = {
args: {
_focus: {
outline: `2px solid ${styleToken.color.teal200}`,
},
},
};

export const WithFocusPlaceholderStyle: Story = {
args: {
placeholder: '중앙 정렬',
_placeholder: {
color: styleToken.color.teal200,
textAlign: 'center',
letterSpacing: '2px',
},
},
};

export const WithVariantFilled: Story = {
args: {
variant: 'filled',
},
};

export const WithVariantFlushed: Story = {
args: {
variant: 'flushed',
},
};

export const WithVariantUnstyled: Story = {
args: {
variant: 'unstyled',
},
};
63 changes: 63 additions & 0 deletions src/shared/components/TextField/TextField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { forwardRef, HTMLProps } from 'react';
import styled from '@emotion/styled';
import type { FocusProps, PlaceholderProps, TextFieldVariant } from './TextField.type';
import { DefaultStyled, styleToken } from '@/shared/styles';
import { AsProps, StyleProps } from '@/shared/types';

type TextFieldProps = StyleProps &
AsProps &
HTMLProps<HTMLInputElement> & {
variant?: TextFieldVariant;
_placeholder?: PlaceholderProps;
_focus?: FocusProps;
};

export const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
const { type, variant, ...restProps } = props;
return <Root as="input" type={type || 'text'} variant={variant || 'outline'} ref={ref} {...restProps} />;
});

const Root = styled(DefaultStyled)<TextFieldProps>`
width: ${styleToken.width.w100};
height: 45px;
padding: 13px 12px 13px 11px;
border-radius: 6px;
font-size: 18px;
${({ variant }) => variantStyles[variant || 'outline']};
&::placeholder {
letter-spacing: ${({ _placeholder }) => _placeholder?.letterSpacing};
color: ${({ _placeholder }) => _placeholder?.color};
text-align: ${({ _placeholder }) => _placeholder?.textAlign};
}
&:focus-visible {
${({ variant }) => variant && isValidVariantNoneOutline(variant) && `outline: none;`};
outline: ${({ _focus }) => _focus?.outline};
}
`;

const variantStyles = {
outline: {
border: `1px solid ${styleToken.color.gray400}`,
borderRadius: '7px',
},
filled: {
backgroundColor: styleToken.color.gray200,
border: 'none',
borderRadius: '7px',
},
flushed: {
border: 'none',
borderBottom: `2px solid ${styleToken.color.gray600}`,
borderRadius: '0',
},
unstyled: {
border: 'none',
borderRadius: '0',
padding: '0',
},
};

const isValidVariantNoneOutline = (variant: TextFieldVariant): variant is 'filled' | 'flushed' | 'unstyled' =>
['filled', 'flushed', 'unstyled'].includes(variant);
13 changes: 13 additions & 0 deletions src/shared/components/TextField/TextField.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { StyleProps } from '@/shared/types';

export type PlaceholderProps = {
color?: StyleProps['color'];
letterSpacing?: StyleProps['letterSpacing'];
textAlign?: StyleProps['textAlign'];
};

export type FocusProps = {
outline?: StyleProps['outline'];
};

export type TextFieldVariant = 'outline' | 'filled' | 'flushed' | 'unstyled';
1 change: 1 addition & 0 deletions src/shared/components/TextField/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './TextField';
4 changes: 2 additions & 2 deletions src/shared/components/VStack/VStack.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const WithPadding: Story = {

export const WithBorder: Story = {
args: {
border: `2px solid ${styleToken.color.gray500}`,
border: `2px solid ${styleToken.color.gray600}`,
},
};

Expand All @@ -61,7 +61,7 @@ export const WithChildren: Story = {
<VStack
alignItems="center"
justifyContent="center"
backgroundColor={styleToken.color.teal}
backgroundColor={styleToken.color.teal100}
width="100px"
height="100px"
>
Expand Down
1 change: 1 addition & 0 deletions src/shared/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './Box';
export * from './HStack';
export * from './VStack';
export * from './TextField';
1 change: 1 addition & 0 deletions src/shared/styles/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './DefaultStyled';
export * from './GlobalStyles';
export * from './storybookControls';
export * from './styledUtils';
export * from './styleToken';
29 changes: 25 additions & 4 deletions src/shared/styles/styleToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ const colors = {
gray200: '#ecebf1',
gray300: '#d3d3d3',
gray400: '#9ca3af',
gray500: '#575757',
gray600: '#525252',
gray700: '#383838',
teal: '#94dacd',
gray500: '#737373',
gray600: '#575757',
gray700: '#525252',
gray800: '#383838',
teal100: '#94dacd',
teal200: '#04C09E',
mustard: '#cbba64',
shadow: 'rgba(0, 0, 0, 0.25)',
body: '#e5e5e5',
Expand All @@ -27,8 +29,27 @@ const fontWeight = {
medium: 500,
} as const;

const spacing = {
mt10: '2.5rem',
mt20: '5rem',
mt30: '7.5rem',
mt40: '10rem',
mt50: '12.5rem',
mb10: '2.5rem',
} as const;

const width = {
w100: '100%',
w75: '75%',
w50: '50%',
w25: '25%',
w15: '15%',
} as const;

export const styleToken = {
color: colors,
fontSize,
fontWeight,
spacing,
width,
} as const;
4 changes: 4 additions & 0 deletions src/shared/styles/styledUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const letterSpacingValue = (fontSize: number, letterSpacingPercentage: number) =>
(fontSize * letterSpacingPercentage) / 100;

export { letterSpacingValue };
2 changes: 2 additions & 0 deletions src/shared/types/props/StyleProps.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export type TypographyProps = {
fontWeight?: CSSProperties['fontWeight'];
lineHeight?: CSSProperties['lineHeight'];
textAlign?: CSSProperties['textAlign'];
letterSpacing?: CSSProperties['letterSpacing'];
};

export type BackgroundProps = {
Expand Down Expand Up @@ -85,4 +86,5 @@ export type OtherProps = {
opacity?: CSSProperties['opacity'];
overflow?: CSSProperties['overflow'];
transition?: CSSProperties['transition'];
outline?: CSSProperties['outline'];
};

0 comments on commit fc62f8c

Please sign in to comment.