150 lines
3.5 KiB
Markdown
150 lines
3.5 KiB
Markdown
---
|
|
name: dev-storybook
|
|
description: |
|
|
Vue 3 컴포넌트를 받아 Storybook Story 파일과 Props/Emits/슬롯 사용 가이드를 자동 생성합니다.
|
|
팀 컴포넌트 카탈로그와 재사용 진입 장벽을 낮추는 데 사용합니다.
|
|
|
|
다음 상황에서 반드시 사용하세요:
|
|
- "이 컴포넌트 Story 만들어줘", "Storybook 파일 생성해줘"
|
|
- "컴포넌트 사용 가이드 문서 만들어줘", "Props 문서 작성해줘"
|
|
- 컴포넌트 카탈로그에 새 컴포넌트를 등록해야 할 때
|
|
---
|
|
|
|
# Storybook Story 생성 (dev-storybook)
|
|
|
|
`.vue` 컴포넌트 → `.stories.ts` 파일 + 사용 가이드 자동 생성.
|
|
|
|
## 언제 사용하는가
|
|
|
|
- 컴포넌트 완성 후 Storybook에 등록할 때
|
|
- 다른 팀원이 컴포넌트를 찾고 재사용할 수 있도록 문서화할 때
|
|
- Props 변형(variant)을 시각적으로 확인해야 할 때
|
|
|
|
## 입력
|
|
|
|
- 대상 `.vue` 파일 경로
|
|
- Storybook 버전 (없으면 Storybook 8 + CSF 3 포맷 기본 적용)
|
|
|
|
---
|
|
|
|
## 작업 순서
|
|
|
|
### Phase 1: 컴포넌트 인터페이스 파악
|
|
|
|
1. `.vue` 파일을 읽어 아래 항목을 추출한다.
|
|
- Props 목록 (타입, 기본값, 설명)
|
|
- Emits 목록
|
|
- 슬롯 목록 (default, named)
|
|
- 주요 상태 변형 (size, variant, disabled, loading 등)
|
|
|
|
### Phase 2: Story 파일 생성 (CSF 3 포맷)
|
|
|
|
파일 위치: 컴포넌트와 동일 디렉토리 또는 `stories/`
|
|
파일명: `<ComponentName>.stories.ts`
|
|
|
|
#### 기본 구조
|
|
```ts
|
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
import ComponentName from './ComponentName.vue'
|
|
|
|
const meta: Meta<typeof ComponentName> = {
|
|
title: '<Category>/<ComponentName>',
|
|
component: ComponentName,
|
|
tags: ['autodocs'],
|
|
argTypes: {
|
|
// Props 컨트롤 정의
|
|
variant: {
|
|
control: 'select',
|
|
options: ['primary', 'secondary', 'ghost'],
|
|
description: '버튼 스타일 변형',
|
|
},
|
|
onClick: { action: 'clicked' },
|
|
},
|
|
}
|
|
|
|
export default meta
|
|
type Story = StoryObj<typeof ComponentName>
|
|
```
|
|
|
|
#### 필수 Story 목록
|
|
```ts
|
|
// 1. 기본 상태
|
|
export const Default: Story = {
|
|
args: {
|
|
// 기본값으로 렌더링
|
|
},
|
|
}
|
|
|
|
// 2. 각 변형(variant)별 Story
|
|
export const Primary: Story = {
|
|
args: { variant: 'primary', label: '확인' },
|
|
}
|
|
|
|
// 3. 비활성 상태
|
|
export const Disabled: Story = {
|
|
args: { disabled: true },
|
|
}
|
|
|
|
// 4. 로딩 상태 (해당 시)
|
|
export const Loading: Story = {
|
|
args: { isLoading: true },
|
|
}
|
|
|
|
// 5. 슬롯 사용 예시 (슬롯 있을 때)
|
|
export const WithSlot: Story = {
|
|
render: (args) => ({
|
|
components: { ComponentName },
|
|
setup() { return { args } },
|
|
template: `<ComponentName v-bind="args">슬롯 내용</ComponentName>`,
|
|
}),
|
|
}
|
|
```
|
|
|
|
### Phase 3: 사용 가이드 주석
|
|
|
|
각 Story에 JSDoc 주석으로 사용 목적을 설명한다:
|
|
|
|
```ts
|
|
/**
|
|
* 기본 상태. 가장 일반적인 사용 패턴.
|
|
* @example
|
|
* <ComponentName label="클릭" @click="handleClick" />
|
|
*/
|
|
export const Default: Story = { ... }
|
|
```
|
|
|
|
### Phase 4: argTypes 컨트롤 매핑
|
|
|
|
| Props 타입 | Storybook 컨트롤 |
|
|
|---|---|
|
|
| `string` | `text` |
|
|
| `number` | `number` |
|
|
| `boolean` | `boolean` |
|
|
| Union 타입 (`'a' \| 'b'`) | `select` |
|
|
| Array | `object` |
|
|
| Function (emit) | `action` |
|
|
|
|
---
|
|
|
|
## 출력 형식
|
|
|
|
```
|
|
## Story: <ComponentName>.stories.ts
|
|
|
|
### Story 목록
|
|
1. Default — 기본 상태
|
|
2. Primary — 주요 variant
|
|
3. Disabled — 비활성
|
|
4. Loading — 로딩 (해당 시)
|
|
|
|
### 코드
|
|
\`\`\`ts
|
|
[전체 stories 파일]
|
|
\`\`\`
|
|
|
|
### Storybook 실행
|
|
\`\`\`bash
|
|
npx storybook dev
|
|
\`\`\`
|
|
```
|