Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] TextField 컴포넌트 구현 #40

Merged
merged 29 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
046f039
feat: TextField 컴포넌트 구현
ghdtjgus76 Jun 5, 2024
769b00e
chore: 텍스트 필드 자잘한 수정 사항 반영
ghdtjgus76 Jun 5, 2024
6651877
feat: 텍스트 필드 컴포넌트 스토리 코드 작성
ghdtjgus76 Jun 5, 2024
e1af0ed
fix: max length 관련 onChange 로직 수정
ghdtjgus76 Jun 5, 2024
cc5d84e
test: 텍스트필드 컴포넌트 테스트 코드 작성
ghdtjgus76 Jun 5, 2024
fe9e362
chore: 토큰 변경
ghdtjgus76 Jun 7, 2024
bcacf72
feat: TextField 빌드 세팅
ghdtjgus76 Jun 7, 2024
212a2b8
fix: a11y violation, incomplete 사항 해결
ghdtjgus76 Jun 7, 2024
0adf388
feat: 반응형 관련 breakpoint 추가
ghdtjgus76 Jun 7, 2024
07d5ae2
chore: token에서 breakpoint 가져오도록 변경
ghdtjgus76 Jun 7, 2024
46cf565
chore: label2 자간 수정사항 반영
ghdtjgus76 Jun 7, 2024
7b70ad2
chore: breakpoint 네이밍 변경
ghdtjgus76 Jun 7, 2024
9f0a341
refactor: 텍스트필드 반응형 토큰 사용
ghdtjgus76 Jun 7, 2024
8a172b6
chore: 불필요한 useEffect 삭제
ghdtjgus76 Jun 7, 2024
643006c
chore: panda codegen 실행
ghdtjgus76 Jun 7, 2024
972c22b
design: 글자 색 변경
ghdtjgus76 Jun 7, 2024
e8fa0fa
chore: useTextareaAutosize 훅에 useEffect 추가
ghdtjgus76 Jun 7, 2024
0c6a97a
fix: 텍스트필드 색상 대조 관련 웹 접근성 테스트 끄도록 설정 변경
ghdtjgus76 Jun 7, 2024
8318eb5
Merge branch 'main' into feature/text-field-component
ghdtjgus76 Jun 7, 2024
fef6914
chore: 포커스된 경우도 typing으로 처리하도록 변경
ghdtjgus76 Jun 7, 2024
08b135d
chore: 스토리북 테스트 러너 a11y rule 관련 설정 추가
ghdtjgus76 Jun 7, 2024
31663cd
chore: 변경된 빌드 설정 반영
ghdtjgus76 Jun 7, 2024
c2f411e
chore: placeholder 여러 줄인 경우도 수용하도록 수정
ghdtjgus76 Jun 9, 2024
0ed8a40
Merge branch 'main' into feature/text-field-component
ghdtjgus76 Jun 9, 2024
d07dc24
fix: 머지 에러 해결
ghdtjgus76 Jun 9, 2024
393dc42
refactor: 상수값 따로 분리
ghdtjgus76 Jun 9, 2024
4594a07
chore: props style로 네이밍 변경
ghdtjgus76 Jun 10, 2024
0655222
Merge branch 'main' into feature/text-field-component
ghdtjgus76 Jun 10, 2024
e69b6a7
chore: codegen 반영
ghdtjgus76 Jun 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions apps/wow-docs/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { css } from "@styled-system/css/css";
import Switch from "wowds-ui/Switch";

import Checkbox from "../../../packages/wow-ui/src/components/Checkbox";

const Home = () => {
return (
<>
Expand All @@ -16,7 +14,6 @@ const Home = () => {
<p>docs</p>
</main>
<Switch />
<Checkbox />
</>
);
};
Expand Down
8 changes: 8 additions & 0 deletions packages/theme/src/tokens/breakpoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { breakpoint } from "wowds-tokens";

export const breakpoints = {
xs: breakpoint.xs,
sm: breakpoint.sm,
md: breakpoint.md,
lg: breakpoint.lg,
};
2 changes: 2 additions & 0 deletions packages/theme/src/tokens/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export * from "./breakpoint.ts";
export * from "./color.ts";
export * from "./typography.ts";

import { defineTokens } from "@pandacss/dev";

import { colors, gradients } from "./color.ts";
Expand Down
4 changes: 4 additions & 0 deletions packages/wow-tokens/src/breakpoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const xs = "360px";
export const sm = "600px";
export const md = "900px";
export const lg = "1280px";
6 changes: 3 additions & 3 deletions packages/wow-tokens/src/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,14 @@ export const blackOpacity80 = "rgba(0, 0, 0, 0.8)";

// 시맨틱 토큰
export const primary = blue500;
export const success = green500;
export const error = red500;
export const success = green600;
export const error = red600;

export const backgroundNormal = white;
export const backgroundAlternative = mono50;
export const backgroundDimmer = blackOpacity80;

export const sub = mono600;
export const sub = mono700;
export const outline = mono400;
export const textBlack = black;
export const textWhite = white;
Expand Down
1 change: 1 addition & 0 deletions packages/wow-tokens/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * as breakpoint from "./breakpoint.ts";
export * as color from "./color.ts";
export * as radius from "./radius.ts";
export * as space from "./space.ts";
Expand Down
1 change: 1 addition & 0 deletions packages/wow-tokens/src/typography.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const label2 = {
fontSize: "0.875rem",
lineHeight: "100%",
fontWeight: 600,
letterSpacing: "-0.01rem",
};

export const label3 = {
Expand Down
5 changes: 5 additions & 0 deletions packages/wow-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
"require": "./dist/Switch.cjs",
"import": "./dist/Switch.js"
},
"./TextField": {
"types": "./dist/components/TextField/index.d.ts",
"require": "./dist/TextField.cjs",
"import": "./dist/TextField.js"
},
"./Chip": {
"types": "./dist/components/Chip/index.d.ts",
"require": "./dist/Chip.cjs",
Expand Down
3 changes: 2 additions & 1 deletion packages/wow-ui/panda.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { defineConfig, defineGlobalStyles } from "@pandacss/dev";
import { semanticTokens, textStyles, tokens } from "theme";
import { semanticTokens, textStyles, tokens, breakpoints } from "theme";
import { removeUnusedCssVars, removeUnusedKeyframes } from "theme/utils";

const globalCss = defineGlobalStyles({
Expand Down Expand Up @@ -32,5 +32,6 @@ export default defineConfig({
tokens,
textStyles,
semanticTokens,
breakpoints,
},
});
1 change: 1 addition & 0 deletions packages/wow-ui/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default {
Button: "./src/components/Button",
Checkbox: "./src/components/Checkbox",
Switch: "./src/components/Switch",
TextField: "./src/components/TextField",
},
output: [
{
Expand Down
246 changes: 246 additions & 0 deletions packages/wow-ui/src/components/TextField/TextField.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
import type { Meta, StoryObj } from "@storybook/react";
import { useState } from "react";

import TextField from "@/components/TextField";

const meta = {
title: "UI/TextField",
component: TextField,
tags: ["autodocs"],
parameters: {
componentSubtitle: "텍스트필드 컴포넌트",
a11y: {
config: {
rules: [{ id: "color-contrast", enabled: false }],
},
},
},
argTypes: {
label: {
description: "텍스트필드의 라벨입니다.",
table: {
type: { summary: "string" },
defaultValue: { summary: null },
},
control: {
type: "text",
},
type: {
name: "string",
required: true,
},
},
placeholder: {
description: "텍스트필드의 플레이스홀더 텍스트입니다.",
table: {
type: { summary: "string" },
defaultValue: { summary: null },
},
control: {
type: "text",
},
},
defaultValue: {
description: "텍스트필드의 기본 값입니다.",
table: {
type: { summary: "string" },
defaultValue: { summary: null },
},
control: {
type: "text",
},
},
value: {
description: "외부에서 제어할 활성 상태입니다.",
table: {
type: { summary: "string" },
defaultValue: { summary: null },
},
control: {
type: "text",
},
},
maxLength: {
description: "텍스트필드의 최대 입력 길이입니다.",
table: {
type: { summary: "number" },
defaultValue: { summary: null },
},
control: {
type: "number",
},
},
error: {
description: "텍스트필드의 오류 상태 여부입니다.",
table: {
type: { summary: "boolean" },
defaultValue: { summary: false },
},
control: {
type: "boolean",
},
},
success: {
description: "텍스트필드의 성공 상태 여부입니다.",
table: {
type: { summary: "boolean" },
defaultValue: { summary: false },
},
control: {
type: "boolean",
},
},
helperText: {
description: "텍스트필드 아래 추가적인 텍스트입니다.",
table: {
type: { summary: "ReactNode" },
defaultValue: { summary: null },
},
control: {
type: "text",
},
},
onChange: {
description: "외부 활성 상태가 변경될 때 호출될 콜백 함수입니다.",
table: {
type: { summary: "(value: string) => void" },
defaultValue: { summary: null },
control: {
type: "function",
},
},
},
onBlur: {
description: "텍스트필드가 포커스를 잃을 때 호출될 콜백 함수입니다.",
table: {
type: { summary: "() => void" },
defaultValue: { summary: null },
control: {
type: "function",
},
},
},
onFocus: {
description: "텍스트필드가 포커스됐을 때 호출될 콜백 함수입니다.",
table: {
type: { summary: "() => void" },
defaultValue: { summary: null },
control: {
type: "function",
},
},
},
textareaProps: {
description: "텍스트필드에 전달할 추가 textarea 속성입니다.",
table: {
type: { summary: "TextareaHTMLAttributes<HTMLTextAreaElement>" },
defaultValue: { summary: null },
control: {
type: "object",
},
},
},
style: {
description: "텍스트필드의 커스텀 스타일 속성입니다.",
table: {
type: { summary: "CSSProperties" },
defaultValue: { summary: null },
control: {
type: "object",
},
},
},
className: {
description: "텍스트필드에 전달하는 커스텀 클래스명입니다.",
table: {
type: { summary: "string" },
defaultValue: { summary: null },
control: {
type: "text",
},
},
},
},
} satisfies Meta<typeof TextField>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Primary: Story = {
args: {
label: "Label",
},
};

export const WithMaxLength: Story = {
args: {
label: "Label",
maxLength: 10,
},
};

export const WithPlaceholder: Story = {
args: {
label: "Label",
placeholder:
"PlaceholderPlaceholderPlaceholderPlaceholderPlaceholderPlaceholderPlaceholder",
},
};

export const WithDefaultValue: Story = {
args: {
label: "Label",
defaultValue: "Text",
},
};

export const WithHelperText: Story = {
args: {
label: "Label",
helperText: "*Caption",
},
};

export const WithMaxLengthAndHelperText: Story = {
args: {
label: "Label",
maxLength: 100,
helperText: "*Caption",
},
};

export const Success: Story = {
args: {
label: "Label",
maxLength: 100,
helperText: "*Caption",
success: true,
},
};

export const Error: Story = {
args: {
label: "Label",
maxLength: 100,
helperText: "*Caption",
error: true,
},
};

const ControlledTextField = () => {
const [value, setValue] = useState("");

const handleChange = (value: string) => {
setValue(value);
};

return <TextField label="Label" value={value} onChange={handleChange} />;
};

export const ControlledState: Story = {
render: () => <ControlledTextField />,
args: {
label: "Label",
},
};
Loading
Loading