Initial commit
This commit is contained in:
107
skills/visual-regression/examples/design-system-vr.md
Normal file
107
skills/visual-regression/examples/design-system-vr.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Example: Visual Regression for Full Design System
|
||||
|
||||
Setup visual regression for entire design system with token validation.
|
||||
|
||||
---
|
||||
|
||||
## Scenario
|
||||
|
||||
You have a design system with multiple components:
|
||||
- Button, Input, Card, Avatar, Badge, Modal, etc.
|
||||
- Design tokens extracted from Figma (via product-design skill)
|
||||
- Want to ensure pixel-perfect implementation
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
"Set up visual regression for entire design system in src/components"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What Skill Does
|
||||
|
||||
1. **Discovers components**: Scans `src/components/` directory
|
||||
2. **Generates stories**: Creates `.stories.tsx` for each component
|
||||
3. **Token validation**: Compares CSS values to design tokens
|
||||
4. **Bulk setup**: Single Chromatic config for all components
|
||||
|
||||
---
|
||||
|
||||
## Generated Files
|
||||
|
||||
```
|
||||
src/components/
|
||||
├── Button/
|
||||
│ ├── Button.tsx
|
||||
│ └── Button.stories.tsx # ← Generated
|
||||
├── Input/
|
||||
│ ├── Input.tsx
|
||||
│ └── Input.stories.tsx # ← Generated
|
||||
├── Card/
|
||||
│ ├── Card.tsx
|
||||
│ └── Card.stories.tsx # ← Generated
|
||||
...
|
||||
|
||||
chromatic.config.json # ← Generated
|
||||
.github/workflows/chromatic.yml # ← Generated
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integration with product-design Skill
|
||||
|
||||
If you used `product-design` skill to extract Figma tokens:
|
||||
|
||||
```
|
||||
1. "Review this design from Figma"
|
||||
→ Extracts tokens to tokens.json
|
||||
|
||||
2. "Set up visual regression for design system"
|
||||
→ Generates stories with token values
|
||||
→ Validates implementation matches tokens
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Token Validation Example
|
||||
|
||||
**Design token** (from Figma):
|
||||
```json
|
||||
{
|
||||
"color": {
|
||||
"primary": {
|
||||
"value": "#3B82F6"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Story validation**:
|
||||
```typescript
|
||||
export const Primary: Story = {
|
||||
args: { variant: 'primary' },
|
||||
play: async ({ canvasElement }) => {
|
||||
const button = within(canvasElement).getByRole('button');
|
||||
const computedStyle = window.getComputedStyle(button);
|
||||
expect(computedStyle.backgroundColor).toBe('rgb(59, 130, 246)'); // #3B82F6
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Prevent drift**: Catch when code diverges from designs
|
||||
- **Scale testing**: Test 50+ components in one workflow
|
||||
- **Token enforcement**: Ensure design tokens are used correctly
|
||||
- **Design review**: Designers see visual diffs in Chromatic
|
||||
|
||||
---
|
||||
|
||||
**Time saved**: 6-10 hours → 15 minutes (95% reduction)
|
||||
**Components**: All in design system
|
||||
**Tokens validated**: Automatically
|
||||
109
skills/visual-regression/examples/existing-storybook-vr.md
Normal file
109
skills/visual-regression/examples/existing-storybook-vr.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Example: Add Chromatic to Existing Storybook
|
||||
|
||||
Add visual regression to project that already has Storybook configured.
|
||||
|
||||
---
|
||||
|
||||
## Scenario
|
||||
|
||||
- Storybook 7.x already installed and configured
|
||||
- Existing `.stories.tsx` files for components
|
||||
- Want to add Chromatic without breaking existing setup
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
"Add Chromatic to existing Storybook"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What Skill Does
|
||||
|
||||
1. **Detects existing setup**: Reads `.storybook/main.js`, existing stories
|
||||
2. **Non-destructive update**: Only adds Chromatic addon
|
||||
3. **Preserves config**: Keeps existing addons, framework, settings
|
||||
4. **CI integration**: Generates workflow
|
||||
|
||||
---
|
||||
|
||||
## Changes Made
|
||||
|
||||
### Before
|
||||
|
||||
**.storybook/main.js**:
|
||||
```javascript
|
||||
module.exports = {
|
||||
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@storybook/addon-interactions',
|
||||
],
|
||||
framework: {
|
||||
name: '@storybook/react-vite',
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### After
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@chromatic-com/storybook', // ← Added
|
||||
'@storybook/addon-interactions',
|
||||
],
|
||||
framework: {
|
||||
name: '@storybook/react-vite',
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Additional Files
|
||||
|
||||
- `chromatic.config.json` (new)
|
||||
- `.github/workflows/chromatic.yml` (new)
|
||||
- `package.json` scripts updated
|
||||
|
||||
---
|
||||
|
||||
## No Stories Generated
|
||||
|
||||
Skill detects existing stories and **skips generation**:
|
||||
|
||||
```
|
||||
✅ Existing Storybook detected
|
||||
✅ Found 23 existing story files
|
||||
✅ Skipping story generation
|
||||
✅ Adding Chromatic configuration only
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
```bash
|
||||
# Install Chromatic
|
||||
npm install --save-dev chromatic @chromatic-com/storybook
|
||||
|
||||
# Run on existing stories
|
||||
npm run chromatic
|
||||
```
|
||||
|
||||
All existing stories are captured as baseline automatically.
|
||||
|
||||
---
|
||||
|
||||
**Time saved**: 1-2 hours → 3 minutes
|
||||
**Stories affected**: 0 (uses existing)
|
||||
**Breaking changes**: None
|
||||
297
skills/visual-regression/examples/simple-component-vr.md
Normal file
297
skills/visual-regression/examples/simple-component-vr.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# Example: Visual Regression for Simple Component
|
||||
|
||||
This example shows how to set up visual regression testing for a single React component.
|
||||
|
||||
---
|
||||
|
||||
## Scenario
|
||||
|
||||
You have a `ProfileCard` component that you want to test for visual regressions.
|
||||
|
||||
**Component**: `src/components/ProfileCard.tsx`
|
||||
|
||||
```typescript
|
||||
interface ProfileCardProps {
|
||||
name: string;
|
||||
avatar: string;
|
||||
bio: string;
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
variant?: 'default' | 'compact';
|
||||
}
|
||||
|
||||
export function ProfileCard({ name, avatar, bio, size = 'md', variant = 'default' }: ProfileCardProps) {
|
||||
// Component implementation
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
### Step 1: Invoke Skill
|
||||
|
||||
```
|
||||
"Set up visual regression for ProfileCard component"
|
||||
```
|
||||
|
||||
### Step 2: Skill Auto-Invokes
|
||||
|
||||
Navigator detects the command and invokes `visual-regression` skill.
|
||||
|
||||
### Step 3: Validation
|
||||
|
||||
Skill executes `vr_setup_validator.py`:
|
||||
|
||||
```json
|
||||
{
|
||||
"framework": "react",
|
||||
"storybook": {
|
||||
"installed": true,
|
||||
"version": "7.6.0"
|
||||
},
|
||||
"vr_tool": null,
|
||||
"ci_platform": "github",
|
||||
"component": {
|
||||
"valid": true,
|
||||
"path": "src/components/ProfileCard.tsx",
|
||||
"name": "ProfileCard"
|
||||
},
|
||||
"dependencies": {
|
||||
"installed": ["@storybook/react", "@storybook/addon-essentials"],
|
||||
"missing": ["chromatic", "@chromatic-com/storybook"]
|
||||
},
|
||||
"ready": true
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Generate Story
|
||||
|
||||
Skill executes `story_generator.py`:
|
||||
|
||||
**Created**: `src/components/ProfileCard.stories.tsx`
|
||||
|
||||
```typescript
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { ProfileCard } from './ProfileCard';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/ProfileCard',
|
||||
component: ProfileCard,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
argTypes: {
|
||||
size: { control: 'select', options: ['sm', 'md', 'lg'] },
|
||||
variant: { control: 'select', options: ['default', 'compact'] },
|
||||
},
|
||||
} satisfies Meta<typeof ProfileCard>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
name: 'John Doe',
|
||||
avatar: 'https://via.placeholder.com/150',
|
||||
bio: 'Software Engineer',
|
||||
size: 'md',
|
||||
variant: 'default',
|
||||
},
|
||||
};
|
||||
|
||||
export const Small: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
size: 'sm',
|
||||
},
|
||||
};
|
||||
|
||||
export const Large: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
size: 'lg',
|
||||
},
|
||||
};
|
||||
|
||||
export const Compact: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'compact',
|
||||
},
|
||||
};
|
||||
|
||||
// Accessibility tests
|
||||
Default.parameters = {
|
||||
a11y: {
|
||||
config: {
|
||||
rules: [
|
||||
{ id: 'color-contrast', enabled: true },
|
||||
{ id: 'label', enabled: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Step 5: Generate Chromatic Config
|
||||
|
||||
Skill executes `chromatic_config_generator.py`:
|
||||
|
||||
**Created**: `chromatic.config.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"projectId": "<PROJECT_ID_PLACEHOLDER>",
|
||||
"buildScriptName": "build-storybook",
|
||||
"exitZeroOnChanges": true,
|
||||
"exitOnceUploaded": true,
|
||||
"onlyChanged": true,
|
||||
"externals": ["public/**"],
|
||||
"skip": "dependabot/**",
|
||||
"ignoreLastBuildOnBranch": "main"
|
||||
}
|
||||
```
|
||||
|
||||
**Updated**: `.storybook/main.js`
|
||||
|
||||
```diff
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
+ '@chromatic-com/storybook',
|
||||
'@storybook/addon-interactions',
|
||||
],
|
||||
```
|
||||
|
||||
**Updated**: `package.json`
|
||||
|
||||
```diff
|
||||
"scripts": {
|
||||
+ "chromatic": "npx chromatic",
|
||||
+ "chromatic:ci": "npx chromatic --exit-zero-on-changes",
|
||||
"build-storybook": "storybook build"
|
||||
}
|
||||
```
|
||||
|
||||
### Step 6: Generate CI Workflow
|
||||
|
||||
Skill executes `ci_workflow_generator.py`:
|
||||
|
||||
**Created**: `.github/workflows/chromatic.yml`
|
||||
|
||||
```yaml
|
||||
name: Visual Regression Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ['main', 'develop']
|
||||
pull_request:
|
||||
branches: ['main']
|
||||
|
||||
jobs:
|
||||
chromatic:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run Chromatic
|
||||
uses: chromaui/action@latest
|
||||
with:
|
||||
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||
exitZeroOnChanges: true
|
||||
onlyChanged: true
|
||||
autoAcceptChanges: 'main'
|
||||
```
|
||||
|
||||
### Step 7: Setup Instructions
|
||||
|
||||
Skill outputs:
|
||||
|
||||
```markdown
|
||||
✅ Visual regression testing setup complete!
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
✅ ProfileCard.stories.tsx (Storybook story with 4 variants)
|
||||
✅ chromatic.config.json (Chromatic configuration)
|
||||
✅ .storybook/main.js (Added @chromatic-com/storybook addon)
|
||||
✅ package.json (Added chromatic scripts)
|
||||
✅ .github/workflows/chromatic.yml (CI workflow)
|
||||
|
||||
## Next Steps
|
||||
|
||||
### 1. Install Dependencies
|
||||
|
||||
```bash
|
||||
npm install --save-dev chromatic @chromatic-com/storybook
|
||||
```
|
||||
|
||||
### 2. Create Chromatic Project
|
||||
|
||||
1. Go to https://www.chromatic.com/start
|
||||
2. Sign in with GitHub
|
||||
3. Create new project
|
||||
4. Copy project token
|
||||
|
||||
### 3. Add Secret to GitHub
|
||||
|
||||
1. Go to repository Settings → Secrets and variables → Actions
|
||||
2. Create secret: `CHROMATIC_PROJECT_TOKEN`
|
||||
3. Paste your project token
|
||||
|
||||
### 4. Update chromatic.config.json
|
||||
|
||||
Replace `<PROJECT_ID_PLACEHOLDER>` with your actual project ID.
|
||||
|
||||
### 5. Create Baseline
|
||||
|
||||
```bash
|
||||
npm run chromatic
|
||||
```
|
||||
|
||||
### 6. Test Visual Regression
|
||||
|
||||
1. Make a visual change to ProfileCard
|
||||
2. Commit and push
|
||||
3. CI will run Chromatic automatically
|
||||
4. Review changes in Chromatic dashboard
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Result
|
||||
|
||||
**Time saved**: 2-3 hours → 5 minutes (96% reduction)
|
||||
|
||||
**Files created**: 4
|
||||
**Lines of code generated**: ~150
|
||||
**Token usage**: 3k tokens (vs 50k manual)
|
||||
|
||||
---
|
||||
|
||||
## Follow-up Tasks
|
||||
|
||||
After setup, you can:
|
||||
|
||||
1. **Add more variants**: Edit `ProfileCard.stories.tsx` to add edge cases
|
||||
2. **Customize Chromatic**: Adjust `chromatic.config.json` settings
|
||||
3. **Add interaction tests**: Use `@storybook/test` for click/focus states
|
||||
4. **Review visual diffs**: Monitor Chromatic dashboard for changes
|
||||
|
||||
---
|
||||
|
||||
**Skill used**: visual-regression
|
||||
**Time to complete**: ~5 minutes
|
||||
**Automated**: Story generation, config creation, CI setup
|
||||
Reference in New Issue
Block a user