@the-bearded-bear/claude-craft 8.8.1 → 8.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dev/i18n/de/Angular/commands/check-compliance.md +218 -168
- package/Dev/i18n/de/Common/agents/refactoring-specialist.md +146 -69
- package/Dev/i18n/de/Common/commands/add-technology.md +166 -68
- package/Dev/i18n/de/Common/commands/setup-ci.md +216 -33
- package/Dev/i18n/de/Laravel/commands/check-compliance.md +223 -115
- package/Dev/i18n/de/Python/checklists/new-feature.md +319 -44
- package/Dev/i18n/de/React/rules/02-architecture.md +483 -322
- package/Dev/i18n/de/React/rules/03-coding-standards.md +584 -368
- package/Dev/i18n/de/Symfony/commands/check-compliance.md +186 -114
- package/Dev/i18n/de/Symfony/rules/07-testing-symfony.md +679 -10
- package/Dev/i18n/de/UIUX/commands/a11y-component.md +284 -26
- package/Dev/i18n/de/UIUX/commands/design-tokens.md +199 -35
- package/Dev/i18n/de/UIUX/commands/user-flow.md +179 -16
- package/Dev/i18n/de/VueJS/commands/check-compliance.md +227 -102
- package/Dev/i18n/es/Angular/commands/check-compliance.md +217 -167
- package/Dev/i18n/es/Common/commands/add-technology.md +158 -60
- package/Dev/i18n/es/Laravel/commands/check-compliance.md +223 -115
- package/Dev/i18n/es/React/commands/check-testing.md +263 -169
- package/Dev/i18n/es/ReactNative/commands/check-testing.md +256 -198
- package/Dev/i18n/es/Symfony/commands/check-compliance.md +189 -117
- package/Dev/i18n/es/Symfony/commands/check-testing.md +301 -102
- package/Dev/i18n/es/Symfony/commands/migration-plan.md +267 -34
- package/Dev/i18n/es/UIUX/commands/a11y-component.md +274 -16
- package/Dev/i18n/es/UIUX/commands/design-tokens.md +186 -22
- package/Dev/i18n/es/UIUX/commands/user-flow.md +173 -10
- package/Dev/i18n/es/VueJS/commands/check-compliance.md +227 -102
- package/Dev/i18n/fr/Angular/commands/check-compliance.md +217 -167
- package/Dev/i18n/fr/Common/commands/ralph-run.md +138 -60
- package/Dev/i18n/fr/Laravel/commands/check-compliance.md +223 -115
- package/Dev/i18n/fr/React/commands/check-architecture.md +370 -53
- package/Dev/i18n/fr/React/commands/check-code-quality.md +454 -64
- package/Dev/i18n/fr/React/commands/check-testing.md +476 -102
- package/Dev/i18n/fr/Symfony/commands/check-compliance.md +188 -116
- package/Dev/i18n/fr/VueJS/commands/check-compliance.md +227 -102
- package/Dev/i18n/pt/Angular/commands/check-compliance.md +225 -175
- package/Dev/i18n/pt/Common/agents/ralph-conductor.md +211 -30
- package/Dev/i18n/pt/Common/commands/add-technology.md +149 -51
- package/Dev/i18n/pt/Common/commands/ralph-run.md +239 -35
- package/Dev/i18n/pt/Flutter/commands/analyze-performance.md +331 -46
- package/Dev/i18n/pt/Flutter/commands/check-compliance.md +234 -29
- package/Dev/i18n/pt/Flutter/commands/generate-feature.md +526 -51
- package/Dev/i18n/pt/Flutter/commands/generate-widget.md +515 -27
- package/Dev/i18n/pt/Flutter/commands/golden-update.md +322 -46
- package/Dev/i18n/pt/Flutter/commands/localization-check.md +278 -37
- package/Dev/i18n/pt/Laravel/commands/check-compliance.md +212 -104
- package/Dev/i18n/pt/React/commands/accessibility-check.md +151 -42
- package/Dev/i18n/pt/React/commands/bundle-analyze.md +300 -25
- package/Dev/i18n/pt/React/commands/check-architecture.md +369 -34
- package/Dev/i18n/pt/React/commands/check-code-quality.md +440 -34
- package/Dev/i18n/pt/React/commands/check-compliance.md +232 -62
- package/Dev/i18n/pt/React/commands/check-security.md +370 -31
- package/Dev/i18n/pt/React/commands/check-testing.md +473 -43
- package/Dev/i18n/pt/React/commands/generate-component.md +454 -19
- package/Dev/i18n/pt/React/commands/generate-hook.md +425 -24
- package/Dev/i18n/pt/React/commands/storybook-story.md +520 -35
- package/Dev/i18n/pt/ReactNative/commands/app-size.md +358 -387
- package/Dev/i18n/pt/ReactNative/commands/check-code-quality.md +246 -75
- package/Dev/i18n/pt/ReactNative/commands/check-compliance.md +191 -85
- package/Dev/i18n/pt/ReactNative/commands/check-security.md +363 -115
- package/Dev/i18n/pt/ReactNative/commands/check-testing.md +269 -79
- package/Dev/i18n/pt/ReactNative/commands/generate-screen.md +491 -324
- package/Dev/i18n/pt/ReactNative/commands/native-module.md +539 -82
- package/Dev/i18n/pt/ReactNative/commands/store-prepare.md +429 -185
- package/Dev/i18n/pt/ReactNative/rules/02-architecture.md +1084 -31
- package/Dev/i18n/pt/Symfony/commands/check-compliance.md +195 -123
- package/Dev/i18n/pt/UIUX/commands/a11y-audit.md +208 -24
- package/Dev/i18n/pt/UIUX/commands/a11y-component.md +281 -23
- package/Dev/i18n/pt/UIUX/commands/design-tokens.md +197 -33
- package/Dev/i18n/pt/UIUX/commands/user-flow.md +183 -20
- package/Dev/i18n/pt/VueJS/commands/check-compliance.md +228 -103
- package/Dev/i18n/pt/Workflow/commands/analyze.md +147 -146
- package/Dev/i18n/pt/Workflow/commands/design.md +205 -204
- package/Dev/i18n/pt/Workflow/commands/implement.md +184 -184
- package/Project/i18n/de/Sprint/commands/dev.md +339 -86
- package/Project/i18n/es/Sprint/commands/dev.md +342 -91
- package/Project/i18n/pt/Sprint/commands/dev.md +343 -92
- package/bundles/cursor/.cursorrules +1 -1
- package/bundles/windsurf/.windsurfrules +1 -1
- package/package.json +1 -1
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Gerar Story Storybook
|
|
2
|
+
description: Gerar Story do Storybook
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
# Gerar Story Storybook
|
|
5
|
+
# Gerar Story do Storybook
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Gere uma story do Storybook para um componente React existente.
|
|
8
8
|
|
|
9
9
|
## O Que Este Comando Faz
|
|
10
10
|
|
|
11
|
-
1. **
|
|
12
|
-
- Criar arquivo de story para componente
|
|
11
|
+
1. **Geração de Story**
|
|
12
|
+
- Criar arquivo de story para o componente
|
|
13
13
|
- Gerar todas as variantes do componente
|
|
14
14
|
- Adicionar controles interativos (args)
|
|
15
|
-
- Configurar
|
|
16
|
-
- Adicionar
|
|
15
|
+
- Configurar parâmetros da story
|
|
16
|
+
- Adicionar documentação
|
|
17
17
|
|
|
18
|
-
2. **Templates
|
|
18
|
+
2. **Templates Utilizados**
|
|
19
19
|
- Formato CSF 3.0 (Component Story Format)
|
|
20
20
|
- Tipos TypeScript
|
|
21
21
|
- Args e argTypes
|
|
@@ -30,18 +30,20 @@ Gerar uma story Storybook para um componente React existente.
|
|
|
30
30
|
## Como Usar
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
# Gerar story para componente existente
|
|
33
|
+
# Gerar story para um componente existente
|
|
34
34
|
npm run generate:story ComponentName
|
|
35
35
|
|
|
36
36
|
# Com caminho personalizado
|
|
37
37
|
npm run generate:story features/users/components/UserCard
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
## Modo
|
|
40
|
+
## Modo de Planejamento
|
|
41
41
|
|
|
42
|
-
> **O modo
|
|
42
|
+
> **O modo de planejamento é obrigatório.** Antes de executar, o Claude ativa o modo de planejamento para analisar o código impactado, propor um plano de implementação e aguardar sua validação antes de realizar qualquer alteração.
|
|
43
43
|
|
|
44
|
-
##
|
|
44
|
+
## Templates de Story
|
|
45
|
+
|
|
46
|
+
### 1. Story Básica
|
|
45
47
|
|
|
46
48
|
```typescript
|
|
47
49
|
// Button.stories.tsx
|
|
@@ -59,16 +61,16 @@ const meta: Meta<typeof Button> = {
|
|
|
59
61
|
variant: {
|
|
60
62
|
control: 'select',
|
|
61
63
|
options: ['primary', 'secondary', 'danger'],
|
|
62
|
-
description: 'Estilo da variante do
|
|
64
|
+
description: 'Estilo da variante do botão',
|
|
63
65
|
},
|
|
64
66
|
size: {
|
|
65
67
|
control: 'select',
|
|
66
68
|
options: ['sm', 'md', 'lg'],
|
|
67
|
-
description: 'Tamanho do
|
|
69
|
+
description: 'Tamanho do botão',
|
|
68
70
|
},
|
|
69
71
|
disabled: {
|
|
70
72
|
control: 'boolean',
|
|
71
|
-
description: 'Desabilitar o
|
|
73
|
+
description: 'Desabilitar o botão',
|
|
72
74
|
},
|
|
73
75
|
},
|
|
74
76
|
};
|
|
@@ -76,10 +78,10 @@ const meta: Meta<typeof Button> = {
|
|
|
76
78
|
export default meta;
|
|
77
79
|
type Story = StoryObj<typeof Button>;
|
|
78
80
|
|
|
79
|
-
// Story
|
|
81
|
+
// Story padrão
|
|
80
82
|
export const Default: Story = {
|
|
81
83
|
args: {
|
|
82
|
-
children: '
|
|
84
|
+
children: 'Button',
|
|
83
85
|
variant: 'primary',
|
|
84
86
|
size: 'md',
|
|
85
87
|
},
|
|
@@ -88,50 +90,533 @@ export const Default: Story = {
|
|
|
88
90
|
// Todas as variantes
|
|
89
91
|
export const Primary: Story = {
|
|
90
92
|
args: {
|
|
91
|
-
children: '
|
|
93
|
+
children: 'Primary Button',
|
|
92
94
|
variant: 'primary',
|
|
93
95
|
},
|
|
94
96
|
};
|
|
95
97
|
|
|
96
98
|
export const Secondary: Story = {
|
|
97
99
|
args: {
|
|
98
|
-
children: '
|
|
100
|
+
children: 'Secondary Button',
|
|
99
101
|
variant: 'secondary',
|
|
100
102
|
},
|
|
101
103
|
};
|
|
102
104
|
|
|
103
105
|
export const Danger: Story = {
|
|
104
106
|
args: {
|
|
105
|
-
children: '
|
|
107
|
+
children: 'Danger Button',
|
|
106
108
|
variant: 'danger',
|
|
107
109
|
},
|
|
108
110
|
};
|
|
109
111
|
|
|
112
|
+
// Variantes de tamanho
|
|
113
|
+
export const Small: Story = {
|
|
114
|
+
args: {
|
|
115
|
+
children: 'Small Button',
|
|
116
|
+
size: 'sm',
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export const Large: Story = {
|
|
121
|
+
args: {
|
|
122
|
+
children: 'Large Button',
|
|
123
|
+
size: 'lg',
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
|
|
110
127
|
// Variantes de estado
|
|
111
128
|
export const Disabled: Story = {
|
|
112
129
|
args: {
|
|
113
|
-
children: '
|
|
130
|
+
children: 'Disabled Button',
|
|
114
131
|
disabled: true,
|
|
115
132
|
},
|
|
116
133
|
};
|
|
134
|
+
|
|
135
|
+
export const Loading: Story = {
|
|
136
|
+
args: {
|
|
137
|
+
children: 'Loading Button',
|
|
138
|
+
isLoading: true,
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 2. Story de Componente de Formulário
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
// Input.stories.tsx
|
|
147
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
148
|
+
import { Input } from './Input';
|
|
149
|
+
|
|
150
|
+
const meta: Meta<typeof Input> = {
|
|
151
|
+
title: 'Forms/Input',
|
|
152
|
+
component: Input,
|
|
153
|
+
parameters: {
|
|
154
|
+
layout: 'padded',
|
|
155
|
+
},
|
|
156
|
+
tags: ['autodocs'],
|
|
157
|
+
argTypes: {
|
|
158
|
+
type: {
|
|
159
|
+
control: 'select',
|
|
160
|
+
options: ['text', 'email', 'password', 'number'],
|
|
161
|
+
},
|
|
162
|
+
error: {
|
|
163
|
+
control: 'text',
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export default meta;
|
|
169
|
+
type Story = StoryObj<typeof Input>;
|
|
170
|
+
|
|
171
|
+
export const Default: Story = {
|
|
172
|
+
args: {
|
|
173
|
+
label: 'Email',
|
|
174
|
+
placeholder: 'Digite seu e-mail',
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
export const WithError: Story = {
|
|
179
|
+
args: {
|
|
180
|
+
label: 'Email',
|
|
181
|
+
value: 'invalid-email',
|
|
182
|
+
error: 'Formato de e-mail inválido',
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export const Password: Story = {
|
|
187
|
+
args: {
|
|
188
|
+
label: 'Senha',
|
|
189
|
+
type: 'password',
|
|
190
|
+
placeholder: 'Digite a senha',
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export const Disabled: Story = {
|
|
195
|
+
args: {
|
|
196
|
+
label: 'Email',
|
|
197
|
+
disabled: true,
|
|
198
|
+
value: 'disabled@example.com',
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### 3. Componente Complexo com Actions
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// UserCard.stories.tsx
|
|
207
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
208
|
+
import { action } from '@storybook/addon-actions';
|
|
209
|
+
import { UserCard } from './UserCard';
|
|
210
|
+
|
|
211
|
+
const meta: Meta<typeof UserCard> = {
|
|
212
|
+
title: 'Features/UserCard',
|
|
213
|
+
component: UserCard,
|
|
214
|
+
parameters: {
|
|
215
|
+
layout: 'centered',
|
|
216
|
+
},
|
|
217
|
+
tags: ['autodocs'],
|
|
218
|
+
decorators: [
|
|
219
|
+
(Story) => (
|
|
220
|
+
<div style={{ maxWidth: '400px' }}>
|
|
221
|
+
<Story />
|
|
222
|
+
</div>
|
|
223
|
+
),
|
|
224
|
+
],
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export default meta;
|
|
228
|
+
type Story = StoryObj<typeof UserCard>;
|
|
229
|
+
|
|
230
|
+
const mockUser = {
|
|
231
|
+
id: '1',
|
|
232
|
+
name: 'John Doe',
|
|
233
|
+
email: 'john@example.com',
|
|
234
|
+
avatar: 'https://i.pravatar.cc/150?img=1',
|
|
235
|
+
role: 'admin' as const,
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export const Default: Story = {
|
|
239
|
+
args: {
|
|
240
|
+
user: mockUser,
|
|
241
|
+
onEdit: action('onEdit'),
|
|
242
|
+
onDelete: action('onDelete'),
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
export const WithoutAvatar: Story = {
|
|
247
|
+
args: {
|
|
248
|
+
user: { ...mockUser, avatar: undefined },
|
|
249
|
+
onEdit: action('onEdit'),
|
|
250
|
+
onDelete: action('onDelete'),
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export const Loading: Story = {
|
|
255
|
+
args: {
|
|
256
|
+
isLoading: true,
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### 4. Story com Múltiplas Composições
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
// Card.stories.tsx
|
|
265
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
266
|
+
import { Card } from './Card';
|
|
267
|
+
|
|
268
|
+
const meta: Meta<typeof Card> = {
|
|
269
|
+
title: 'Components/Card',
|
|
270
|
+
component: Card,
|
|
271
|
+
parameters: {
|
|
272
|
+
layout: 'centered',
|
|
273
|
+
},
|
|
274
|
+
tags: ['autodocs'],
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
export default meta;
|
|
278
|
+
type Story = StoryObj<typeof Card>;
|
|
279
|
+
|
|
280
|
+
export const Default: Story = {
|
|
281
|
+
args: {
|
|
282
|
+
children: 'Conteúdo do card',
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
export const WithHeader: Story = {
|
|
287
|
+
render: () => (
|
|
288
|
+
<Card>
|
|
289
|
+
<Card.Header>Título do Card</Card.Header>
|
|
290
|
+
<Card.Body>Conteúdo do card aqui</Card.Body>
|
|
291
|
+
</Card>
|
|
292
|
+
),
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
export const Complete: Story = {
|
|
296
|
+
render: () => (
|
|
297
|
+
<Card>
|
|
298
|
+
<Card.Header>
|
|
299
|
+
<h3>Perfil do Usuário</h3>
|
|
300
|
+
</Card.Header>
|
|
301
|
+
<Card.Body>
|
|
302
|
+
<p>Nome: John Doe</p>
|
|
303
|
+
<p>Email: john@example.com</p>
|
|
304
|
+
</Card.Body>
|
|
305
|
+
<Card.Footer>
|
|
306
|
+
<button>Editar</button>
|
|
307
|
+
<button>Excluir</button>
|
|
308
|
+
</Card.Footer>
|
|
309
|
+
</Card>
|
|
310
|
+
),
|
|
311
|
+
};
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### 5. Story com MSW (Mock de API)
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
// UserList.stories.tsx
|
|
318
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
319
|
+
import { http, HttpResponse } from 'msw';
|
|
320
|
+
import { UserList } from './UserList';
|
|
321
|
+
|
|
322
|
+
const meta: Meta<typeof UserList> = {
|
|
323
|
+
title: 'Features/UserList',
|
|
324
|
+
component: UserList,
|
|
325
|
+
parameters: {
|
|
326
|
+
layout: 'fullscreen',
|
|
327
|
+
},
|
|
328
|
+
tags: ['autodocs'],
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
export default meta;
|
|
332
|
+
type Story = StoryObj<typeof UserList>;
|
|
333
|
+
|
|
334
|
+
export const Default: Story = {
|
|
335
|
+
parameters: {
|
|
336
|
+
msw: {
|
|
337
|
+
handlers: [
|
|
338
|
+
http.get('/api/users', () => {
|
|
339
|
+
return HttpResponse.json([
|
|
340
|
+
{ id: '1', name: 'John Doe', email: 'john@example.com' },
|
|
341
|
+
{ id: '2', name: 'Jane Smith', email: 'jane@example.com' },
|
|
342
|
+
]);
|
|
343
|
+
}),
|
|
344
|
+
],
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
export const Empty: Story = {
|
|
350
|
+
parameters: {
|
|
351
|
+
msw: {
|
|
352
|
+
handlers: [
|
|
353
|
+
http.get('/api/users', () => {
|
|
354
|
+
return HttpResponse.json([]);
|
|
355
|
+
}),
|
|
356
|
+
],
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
export const Error: Story = {
|
|
362
|
+
parameters: {
|
|
363
|
+
msw: {
|
|
364
|
+
handlers: [
|
|
365
|
+
http.get('/api/users', () => {
|
|
366
|
+
return new HttpResponse(null, { status: 500 });
|
|
367
|
+
}),
|
|
368
|
+
],
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
};
|
|
117
372
|
```
|
|
118
373
|
|
|
119
|
-
##
|
|
374
|
+
## Configuração de Story
|
|
375
|
+
|
|
376
|
+
### Parâmetros Globais
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
// .storybook/preview.ts
|
|
380
|
+
import type { Preview } from '@storybook/react';
|
|
381
|
+
import '../src/index.css';
|
|
382
|
+
|
|
383
|
+
const preview: Preview = {
|
|
384
|
+
parameters: {
|
|
385
|
+
actions: { argTypesRegex: '^on[A-Z].*' },
|
|
386
|
+
controls: {
|
|
387
|
+
matchers: {
|
|
388
|
+
color: /(background|color)$/i,
|
|
389
|
+
date: /Date$/,
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
backgrounds: {
|
|
393
|
+
default: 'light',
|
|
394
|
+
values: [
|
|
395
|
+
{ name: 'light', value: '#ffffff' },
|
|
396
|
+
{ name: 'dark', value: '#1a1a1a' },
|
|
397
|
+
],
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
export default preview;
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Decorators
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
// Decorator global
|
|
409
|
+
export const decorators = [
|
|
410
|
+
(Story) => (
|
|
411
|
+
<div style={{ padding: '3rem' }}>
|
|
412
|
+
<Story />
|
|
413
|
+
</div>
|
|
414
|
+
),
|
|
415
|
+
];
|
|
416
|
+
|
|
417
|
+
// Decorator específico de story
|
|
418
|
+
export const WithPadding: Story = {
|
|
419
|
+
decorators: [
|
|
420
|
+
(Story) => (
|
|
421
|
+
<div style={{ padding: '2rem', backgroundColor: '#f0f0f0' }}>
|
|
422
|
+
<Story />
|
|
423
|
+
</div>
|
|
424
|
+
),
|
|
425
|
+
],
|
|
426
|
+
args: {
|
|
427
|
+
children: 'Conteúdo com padding',
|
|
428
|
+
},
|
|
429
|
+
};
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
## Controles Interativos
|
|
433
|
+
|
|
434
|
+
### Configuração de ArgTypes
|
|
435
|
+
|
|
436
|
+
```typescript
|
|
437
|
+
const meta: Meta<typeof Component> = {
|
|
438
|
+
argTypes: {
|
|
439
|
+
// Select
|
|
440
|
+
variant: {
|
|
441
|
+
control: 'select',
|
|
442
|
+
options: ['primary', 'secondary'],
|
|
443
|
+
description: 'Variante do componente',
|
|
444
|
+
table: {
|
|
445
|
+
defaultValue: { summary: 'primary' },
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
|
|
449
|
+
// Radio
|
|
450
|
+
size: {
|
|
451
|
+
control: 'radio',
|
|
452
|
+
options: ['sm', 'md', 'lg'],
|
|
453
|
+
},
|
|
454
|
+
|
|
455
|
+
// Boolean
|
|
456
|
+
disabled: {
|
|
457
|
+
control: 'boolean',
|
|
458
|
+
},
|
|
459
|
+
|
|
460
|
+
// Number
|
|
461
|
+
count: {
|
|
462
|
+
control: { type: 'number', min: 0, max: 100, step: 1 },
|
|
463
|
+
},
|
|
464
|
+
|
|
465
|
+
// Range
|
|
466
|
+
opacity: {
|
|
467
|
+
control: { type: 'range', min: 0, max: 1, step: 0.1 },
|
|
468
|
+
},
|
|
469
|
+
|
|
470
|
+
// Color
|
|
471
|
+
color: {
|
|
472
|
+
control: 'color',
|
|
473
|
+
},
|
|
474
|
+
|
|
475
|
+
// Date
|
|
476
|
+
date: {
|
|
477
|
+
control: 'date',
|
|
478
|
+
},
|
|
120
479
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
480
|
+
// Text
|
|
481
|
+
label: {
|
|
482
|
+
control: 'text',
|
|
483
|
+
},
|
|
484
|
+
|
|
485
|
+
// Object
|
|
486
|
+
user: {
|
|
487
|
+
control: 'object',
|
|
488
|
+
},
|
|
489
|
+
|
|
490
|
+
// Function (desabilitar controle)
|
|
491
|
+
onClick: {
|
|
492
|
+
action: 'clicked',
|
|
493
|
+
table: {
|
|
494
|
+
category: 'Events',
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
};
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
## Documentação
|
|
502
|
+
|
|
503
|
+
### Documentação MDX
|
|
504
|
+
|
|
505
|
+
```mdx
|
|
506
|
+
<!-- Button.stories.mdx -->
|
|
507
|
+
import { Canvas, Meta, Story } from '@storybook/blocks';
|
|
508
|
+
import * as ButtonStories from './Button.stories';
|
|
509
|
+
|
|
510
|
+
<Meta of={ButtonStories} />
|
|
511
|
+
|
|
512
|
+
# Button
|
|
513
|
+
|
|
514
|
+
Componente de botão com múltiplas variantes e tamanhos.
|
|
515
|
+
|
|
516
|
+
## Uso
|
|
517
|
+
|
|
518
|
+
```tsx
|
|
519
|
+
import { Button } from '@/components/Button';
|
|
520
|
+
|
|
521
|
+
<Button variant="primary" onClick={handleClick}>
|
|
522
|
+
Clique aqui
|
|
523
|
+
</Button>
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
## Variantes
|
|
527
|
+
|
|
528
|
+
<Canvas of={ButtonStories.Primary} />
|
|
529
|
+
<Canvas of={ButtonStories.Secondary} />
|
|
530
|
+
<Canvas of={ButtonStories.Danger} />
|
|
531
|
+
|
|
532
|
+
## Tamanhos
|
|
533
|
+
|
|
534
|
+
<Canvas of={ButtonStories.Small} />
|
|
535
|
+
<Canvas of={ButtonStories.Large} />
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
## Boas Práticas
|
|
539
|
+
|
|
540
|
+
1. **Nomenclatura de Story**: Use nomes descritivos (Default, Primary, WithError)
|
|
541
|
+
2. **Args**: Forneça valores padrão sensatos
|
|
542
|
+
3. **ArgTypes**: Documente todas as props
|
|
543
|
+
4. **Actions**: Use para manipuladores de eventos
|
|
544
|
+
5. **Decorators**: Adicione contexto quando necessário
|
|
545
|
+
6. **MSW**: Simule chamadas de API
|
|
546
|
+
7. **Acessibilidade**: Teste com o addon a11y
|
|
547
|
+
8. **Documentação**: Adicione MDX para componentes complexos
|
|
548
|
+
9. **Variantes**: Cubra todos os estados visuais
|
|
549
|
+
10. **Casos Extremos**: Inclua estados de erro, carregamento e vazio
|
|
550
|
+
|
|
551
|
+
## Testes com Storybook
|
|
552
|
+
|
|
553
|
+
### Teste de Interação
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
// Button.stories.tsx
|
|
557
|
+
import { expect } from '@storybook/jest';
|
|
558
|
+
import { userEvent, within } from '@storybook/testing-library';
|
|
559
|
+
|
|
560
|
+
export const ClickTest: Story = {
|
|
561
|
+
args: {
|
|
562
|
+
children: 'Clique aqui',
|
|
563
|
+
},
|
|
564
|
+
play: async ({ canvasElement }) => {
|
|
565
|
+
const canvas = within(canvasElement);
|
|
566
|
+
const button = canvas.getByRole('button');
|
|
567
|
+
|
|
568
|
+
await userEvent.click(button);
|
|
569
|
+
await expect(button).toHaveAttribute('aria-pressed', 'true');
|
|
570
|
+
},
|
|
571
|
+
};
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### Teste Visual
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
// Configurar Chromatic
|
|
578
|
+
export const parameters = {
|
|
579
|
+
chromatic: {
|
|
580
|
+
viewports: [320, 768, 1200],
|
|
581
|
+
delay: 300,
|
|
582
|
+
},
|
|
583
|
+
};
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
## Script de Geração
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
// scripts/generate-story.ts
|
|
590
|
+
import fs from 'fs/promises';
|
|
591
|
+
import path from 'path';
|
|
592
|
+
|
|
593
|
+
async function generateStory(componentName: string, componentPath: string) {
|
|
594
|
+
const storyPath = path.join(componentPath, `${componentName}.stories.tsx`);
|
|
595
|
+
|
|
596
|
+
await fs.writeFile(storyPath, getStoryTemplate(componentName));
|
|
597
|
+
|
|
598
|
+
console.log(`✅ Story criada: ${storyPath}`);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// Executar
|
|
602
|
+
const [,, name, pathArg] = process.argv;
|
|
603
|
+
generateStory(name, pathArg || `src/components/${name}`);
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
## Addons do Storybook
|
|
607
|
+
|
|
608
|
+
Addons essenciais para instalar:
|
|
609
|
+
|
|
610
|
+
```bash
|
|
611
|
+
npm install -D @storybook/addon-essentials
|
|
612
|
+
npm install -D @storybook/addon-interactions
|
|
613
|
+
npm install -D @storybook/addon-a11y
|
|
614
|
+
npm install -D msw-storybook-addon
|
|
615
|
+
```
|
|
131
616
|
|
|
132
617
|
## Recursos
|
|
133
618
|
|
|
134
|
-
- [
|
|
619
|
+
- [Documentação do Storybook](https://storybook.js.org/docs/react/get-started/introduction)
|
|
135
620
|
- [CSF 3.0](https://storybook.js.org/docs/react/api/csf)
|
|
136
|
-
- [
|
|
137
|
-
- [Addon
|
|
621
|
+
- [Teste de Interação](https://storybook.js.org/docs/react/writing-tests/interaction-testing)
|
|
622
|
+
- [MSW Addon](https://storybook.js.org/addons/msw-storybook-addon)
|