Skip to content

Commit

Permalink
[Feature] TextField 컴포넌트 구현 (#40)
Browse files Browse the repository at this point in the history
* feat: TextField 컴포넌트 구현

* chore: 텍스트 필드 자잘한 수정 사항 반영

* feat: 텍스트 필드 컴포넌트 스토리 코드 작성

* fix: max length 관련 onChange 로직 수정

* test: 텍스트필드 컴포넌트 테스트 코드 작성

* chore: 토큰 변경

* feat: TextField 빌드 세팅

* fix: a11y violation, incomplete 사항 해결

* feat: 반응형 관련 breakpoint 추가

* chore: token에서 breakpoint 가져오도록 변경

* chore: label2 자간 수정사항 반영

* chore: breakpoint 네이밍 변경

* refactor: 텍스트필드 반응형 토큰 사용

* chore: 불필요한 useEffect 삭제

* chore: panda codegen 실행

* design: 글자 색 변경

* chore: useTextareaAutosize 훅에 useEffect 추가

* fix: 텍스트필드 색상 대조 관련 웹 접근성 테스트 끄도록 설정 변경

* chore: 포커스된 경우도 typing으로 처리하도록 변경

* chore: 스토리북 테스트 러너 a11y rule 관련 설정 추가

* chore: 변경된 빌드 설정 반영

* chore: placeholder 여러 줄인 경우도 수용하도록 수정

* fix: 머지 에러 해결

* refactor: 상수값 따로 분리

* chore: props style로 네이밍 변경

* chore: codegen 반영
  • Loading branch information
ghdtjgus76 authored Jun 10, 2024
1 parent d7c1274 commit fd0be3d
Show file tree
Hide file tree
Showing 21 changed files with 864 additions and 81 deletions.
6 changes: 3 additions & 3 deletions apps/wow-docs/styled-system/tokens/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,11 +384,11 @@ const tokens = {
variable: "var(--colors-primary)",
},
"colors.success": {
value: "#34A853",
value: "#2A8642",
variable: "var(--colors-success)",
},
"colors.error": {
value: "#EA4335",
value: "#BB362A",
variable: "var(--colors-error)",
},
"colors.backgroundNormal": {
Expand All @@ -404,7 +404,7 @@ const tokens = {
variable: "var(--colors-background-dimmer)",
},
"colors.sub": {
value: "#8F8F8F",
value: "#6B6B6B",
variable: "var(--colors-sub)",
},
"colors.outline": {
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 @@ -24,6 +24,7 @@ export default {
Checkbox: "./src/components/Checkbox",
Chip: "./src/components/Chip",
Switch: "./src/components/Switch",
TextField: "./src/components/TextField",
},
output: [
{
Expand Down
3 changes: 2 additions & 1 deletion packages/wow-ui/src/components/Chip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const Chip: ChipComponent & { displayName?: string } = forwardRef(
isChecked: checkedProp = false,
defaultChecked = false,
disabled = false,
style,
...rest
}: ChipProps<T>,
ref: any
Expand Down Expand Up @@ -110,7 +111,7 @@ const Chip: ChipComponent & { displayName?: string } = forwardRef(
aria-label={`chip ${isChecked ? "activated" : "inactivated"}`}
data-selected={isChecked}
ref={ref}
style={rest.customStyle}
style={style}
className={chip({
clickable: disabled ? false : clickable,
disabled: disabled,
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

0 comments on commit fd0be3d

Please sign in to comment.