From 3c00dbf3abb8a21b78fa71ea50cab57114482e29 Mon Sep 17 00:00:00 2001 From: kimgho Date: Tue, 16 Dec 2025 16:46:32 +0900 Subject: [PATCH 1/7] =?UTF-8?q?chore:=20nvmrc=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - node 20 버전에서 storybook 오류가 있어 20보다 높은 버전을 요구함 --- .nvmrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 .nvmrc diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..a45fd52 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24 From b321726e592bac101ba62d1633ba9c3f20755e11 Mon Sep 17 00:00:00 2001 From: kimgho Date: Tue, 16 Dec 2025 21:33:43 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat(storybook):=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94=EB=A5=BC=20=EC=9C=84=ED=95=B4=20mdx=20=ED=98=95?= =?UTF-8?q?=EC=8B=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .storybook/main.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.storybook/main.ts b/.storybook/main.ts index 098d7f8..d5d11ee 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -6,11 +6,11 @@ import type { StorybookConfig } from "@storybook/nextjs-vite"; const require = createRequire(import.meta.url); const config: StorybookConfig = { - stories: ["../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], - addons: [ - "@chromatic-com/storybook", - "@storybook/addon-docs", + stories: [ + "../src/**/*.mdx", + "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)", ], + addons: ["@chromatic-com/storybook", "@storybook/addon-docs"], framework: "@storybook/nextjs-vite", staticDirs: ["../public"], From 8c8a9e2d7ab9642b392ca07666721ce964eb20f3 Mon Sep 17 00:00:00 2001 From: kimgho Date: Tue, 16 Dec 2025 21:34:04 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat(Badge):=20badge=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=8A=A4=ED=86=A0=EB=A6=AC=EB=B6=81=20?= =?UTF-8?q?=EB=B0=8F=20=EB=AC=B8=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/ui/badge/Badge.mdx | 70 +++++++++++++++++++++++++++ src/shared/ui/badge/Badge.stories.tsx | 38 +++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/shared/ui/badge/Badge.mdx create mode 100644 src/shared/ui/badge/Badge.stories.tsx diff --git a/src/shared/ui/badge/Badge.mdx b/src/shared/ui/badge/Badge.mdx new file mode 100644 index 0000000..bacc144 --- /dev/null +++ b/src/shared/ui/badge/Badge.mdx @@ -0,0 +1,70 @@ +import * as BadgeStories from "./Badge.stories"; +import { + Meta, + Canvas, + Controls, + Story, + Description, + ArgTypes, + Source, +} from "@storybook/addon-docs/blocks"; + + + +# Badge + +상태나 카테고리를 나타내는 작은 라벨 컴포넌트입니다. + + + +## Props + + + +## Examples + +### Variants + +`Badge` 컴포넌트는 5가지 스타일(`primary`, `secondary`, `success`, `danger`,`warning`)을 지원합니다. + + + +primary + secondary + success + danger + warning + `} +/> + +
+ +### Sizes + +`Badge` 컴포넌트는 3가지 크기(`sm`, `md`, `lg`)를 지원합니다. + + + +Small + Medium + Large + `} +/> + +
+ +## 사용 가이드 (Usage) + +`children` prop을 통해 뱃지 텍스트를 전달합니다. + +```tsx + + 뱃지 텍스트 + +``` diff --git a/src/shared/ui/badge/Badge.stories.tsx b/src/shared/ui/badge/Badge.stories.tsx new file mode 100644 index 0000000..a116bc5 --- /dev/null +++ b/src/shared/ui/badge/Badge.stories.tsx @@ -0,0 +1,38 @@ +import { Badge } from "./Badge"; +import type { Meta, StoryObj } from "@storybook/nextjs-vite"; + +const meta: Meta = { + title: "design-system/Badge", + component: Badge, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { children: "뱃지입니다." }, +}; + +export const Variants: Story = { + args: { children: "variants" }, + render: () => ( +
+ primary + secondary + success + danger + warning +
+ ), +}; + +export const Sizes: Story = { + args: { children: "size" }, + render: () => ( +
+ Large + Medium + Small +
+ ), +}; From 47051107262adf1a9e697cab931bb4e46e8cd8ea Mon Sep 17 00:00:00 2001 From: kimgho Date: Tue, 16 Dec 2025 22:24:21 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat(storybook):=20viewport=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .storybook/preview.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 557ab73..633622c 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,7 +1,11 @@ import type { Preview } from "@storybook/nextjs-vite"; +import { INITIAL_VIEWPORTS } from "storybook/viewport"; const preview: Preview = { parameters: { + viewport: { + options: INITIAL_VIEWPORTS, + }, controls: { matchers: { color: /(background|color)$/i, From 18adbdaf584b40d71eb6f2b77a34260bda9a1746 Mon Sep 17 00:00:00 2001 From: kimgho Date: Tue, 16 Dec 2025 22:24:36 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat(shared):=20header=20=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shared/ui/header/Header.stories.tsx | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/shared/ui/header/Header.stories.tsx diff --git a/src/shared/ui/header/Header.stories.tsx b/src/shared/ui/header/Header.stories.tsx new file mode 100644 index 0000000..0f6f47d --- /dev/null +++ b/src/shared/ui/header/Header.stories.tsx @@ -0,0 +1,48 @@ +import { Header } from "./Header"; +import type { Meta, StoryObj } from "@storybook/nextjs-vite"; +import { expect, userEvent, within } from "storybook/test"; + +const meta: Meta = { + title: "shared/Header", + component: Header, + parameters: { + layout: "fullscreen", + nextjs: { + appDirectory: true, + navigation: { + pathname: "/", + }, + }, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Desktop: Story = {}; + +export const Mobile: Story = { + globals: { + viewport: { + value: "iphone12", + isRotated: false, + }, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const menuButton = canvas.getByRole("button", { name: "메뉴 열기" }); + + await expect(menuButton).toBeInTheDocument(); + + await userEvent.click(menuButton); + + const closeButton = canvas.getByRole("button", { name: "닫기" }); + + await expect(closeButton).toBeVisible(); + + await userEvent.click(closeButton); + + await expect(menuButton).toBeInTheDocument(); + }, +}; From 10f116c6b55ed35a7198fdbed25ca0e8de43ab54 Mon Sep 17 00:00:00 2001 From: kimgho Date: Tue, 16 Dec 2025 22:38:02 +0900 Subject: [PATCH 6/7] =?UTF-8?q?fix(workspace):=20storybook=20import=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/workspace.code-snippets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/workspace.code-snippets b/.vscode/workspace.code-snippets index 3794ad9..a62cea1 100644 --- a/.vscode/workspace.code-snippets +++ b/.vscode/workspace.code-snippets @@ -2,7 +2,7 @@ "StoryBook": { "prefix": ["!sb", "!storybook"], "body": [ - "import type { Meta, StoryObj } from '@storybook/react-vite';\n", + "import type { Meta, StoryObj } from '@storybook/nextjs-vite';\n", "const meta: Meta = {", " component: ${1:Component},", From 7339bc32278dd5047d8db583121f0d19ed85b81c Mon Sep 17 00:00:00 2001 From: kimgho Date: Tue, 16 Dec 2025 22:38:21 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat(FeedCard):=20feed=20card=20=EC=8A=A4?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/feed/ui/FeedCard.stories.tsx | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/entities/feed/ui/FeedCard.stories.tsx diff --git a/src/entities/feed/ui/FeedCard.stories.tsx b/src/entities/feed/ui/FeedCard.stories.tsx new file mode 100644 index 0000000..d241a77 --- /dev/null +++ b/src/entities/feed/ui/FeedCard.stories.tsx @@ -0,0 +1,29 @@ +import { FeedCard } from "./FeedCard"; +import type { Meta, StoryObj } from "@storybook/nextjs-vite"; +import { expect, userEvent, within } from "storybook/test"; + +const meta: Meta = { + component: FeedCard, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: {}, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const likeButton = canvas.getByRole("button", { name: "좋아요" }); + + const heartIcon = likeButton.querySelector("svg") as SVGSVGElement; + await userEvent.click(heartIcon); + + const unlikeButton = canvas.getByRole("button", { name: "좋아요 취소" }); + await expect(unlikeButton).toBeInTheDocument(); + + await userEvent.click(heartIcon); + + const likeButtonAgain = canvas.getByRole("button", { name: "좋아요" }); + await expect(likeButtonAgain).toBeInTheDocument(); + }, +};