npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill screenshot用于用户界面变更的可视化验证工作流,以加速代码审查并及早发现响应式设计问题。
在以下情况使用此技能:
对于任何更改用户界面的拉取请求,请捕获所有三种视口尺寸:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
Chrome/Edge DevTools:
Firefox DevTools:
使用 Playwright(推荐用于 CI):
// screenshot.js
const { chromium } = require('playwright');
async function captureScreenshots(url) {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(url);
// Desktop
await page.setViewportSize({ width: 1920, height: 1080 });
await page.screenshot({
path: 'screenshots/desktop.png',
fullPage: true
});
// Tablet
await page.setViewportSize({ width: 768, height: 1024 });
await page.screenshot({
path: 'screenshots/tablet.png',
fullPage: true
});
// Mobile
await page.setViewportSize({ width: 375, height: 667 });
await page.screenshot({
path: 'screenshots/mobile.png',
fullPage: true
});
await browser.close();
}
captureScreenshots('http://localhost:3000');
运行:node screenshot.js
使用 Puppeteer:
// screenshot.js
const puppeteer = require('puppeteer');
async function captureScreenshots(url) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
// Desktop
await page.setViewport({ width: 1920, height: 1080 });
await page.screenshot({
path: 'screenshots/desktop.png',
fullPage: true
});
// Tablet
await page.setViewport({ width: 768, height: 1024 });
await page.screenshot({
path: 'screenshots/tablet.png',
fullPage: true
});
// Mobile
await page.setViewport({ width: 375, height: 667 });
await page.screenshot({
path: 'screenshots/mobile.png',
fullPage: true
});
await browser.close();
}
captureScreenshots('http://localhost:3000');
使用此模板记录视觉变更:
## 视觉变更
### 桌面 (1920x1080)

**关键变更**:
- 更新了头部导航布局
- 改进了各区域之间的间距
- 为按钮添加了悬停状态
### 平板 (768x1024)

**关键变更**:
- 侧边栏采用堆叠布局
- 适合触摸的按钮尺寸 (48x48px)
- 调整了排版以提高可读性
### 移动 (375x667)

**关键变更**:
- 汉堡菜单取代水平导航
- 单列布局
- 底部粘性 CTA 按钮
### 前后对比
#### 修复前(错误)

**问题**:移动端文本溢出容器
#### 修复后

**修复**:应用了 word-wrap 和 max-width 约束
### 交互状态
#### 默认状态

#### 悬停状态

#### 激活/选中状态

#### 错误状态

#### 加载状态

## 响应式设计说明
- 断点:768px(平板)、375px(移动)
- 所有触摸目标 > 44x44px
- 所有尺寸下文本均保持可读性(最小 16px 正文)
- 在任何视口下均无水平滚动
- 图像按比例缩放
## 无障碍性检查
- [ ] 键盘导航正常工作
- [ ] 焦点状态可见
- [ ] 颜色对比度满足 WCAG AA (4.5:1)
- [ ] 图像有替代文本
- [ ] 需要时使用 ARIA 标签
// tests/visual.spec.js
const { test, expect } = require('@playwright/test');
test.describe('Visual Regression', () => {
test('homepage looks correct on desktop', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.setViewportSize({ width: 1920, height: 1080 });
await expect(page).toHaveScreenshot('homepage-desktop.png');
});
test('homepage looks correct on mobile', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.setViewportSize({ width: 375, height: 667 });
await expect(page).toHaveScreenshot('homepage-mobile.png');
});
});
运行:npx playwright test --update-snapshots(首次运行以生成基线)
用于组件级视觉测试:
// Button.stories.jsx
export default {
title: 'Components/Button',
component: Button,
};
export const Primary = () => <Button variant="primary">Click me</Button>;
export const Secondary = () => <Button variant="secondary">Click me</Button>;
npm install --save-dev chromatic
npx chromatic --project-token=<token>
# .github/workflows/chromatic.yml
name: Chromatic
on: push
jobs:
chromatic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx chromatic --project-token=${{ secrets.CHROMATIC_TOKEN }}
在提交包含用户界面变更的拉取请求前:
desktop-homepage.png)问题:截图超过 5MB+,在拉取请求中加载缓慢 解决方案:上传前压缩图像
# 使用 ImageMagick
convert input.png -quality 85 output.png
# 使用 pngquant
pngquant input.png --output output.png
问题:时间戳、随机数据导致截图不一致 解决方案:在测试中使用模拟数据或冻结时间
// Mock Date
const mockDate = new Date('2025-01-01T00:00:00Z');
jest.useFakeTimers();
jest.setSystemTime(mockDate);
// Or in Playwright
await page.addInitScript(() => {
Date.now = () => 1704067200000; // Fixed timestamp
});
问题:相同代码在不同操作系统上渲染不同 解决方案:使用 Docker 确保环境一致
FROM mcr.microsoft.com/playwright:v1.40.0-jammy
WORKDIR /app
COPY . .
RUN npm ci
CMD ["npm", "run", "screenshot"]
screenshots/
├── desktop/
│ ├── homepage.png
│ ├── product-list.png
│ └── checkout.png
├── tablet/
│ ├── homepage.png
│ ├── product-list.png
│ └── checkout.png
└── mobile/
├── homepage.png
├── product-list.png
└── checkout.png
desktop-homepage-logged-in.pngmobile-form-error-state.pngbefore-header-fix.png、after-header-fix.pngname: Visual Testing
on: pull_request
jobs:
screenshots:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build app
run: npm run build
- name: Start app
run: npm start &
- name: Wait for app
run: npx wait-on http://localhost:3000
- name: Capture screenshots
run: node scripts/screenshot.js
- name: Upload screenshots
uses: actions/upload-artifact@v4
with:
name: screenshots
path: screenshots/
universal-verification-pre-merge - 合并前验证检查清单universal-testing-webapp-testing - Web 应用程序测试模式toolchains-javascript-testing-playwright - Playwright 测试框架universal-debugging-verification-before-completion - 验证工作流每周安装次数
88
代码仓库
GitHub 星标数
18
首次出现
2026年1月23日
安全审计
安装于
opencode71
claude-code71
gemini-cli66
codex65
cursor63
github-copilot60
Visual verification workflow for UI changes to accelerate code review and catch responsive design issues early.
Use this skill when:
For any PR that changes UI, capture all three viewport sizes:
Chrome/Edge DevTools :
Firefox DevTools :
Using Playwright (recommended for CI):
// screenshot.js
const { chromium } = require('playwright');
async function captureScreenshots(url) {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(url);
// Desktop
await page.setViewportSize({ width: 1920, height: 1080 });
await page.screenshot({
path: 'screenshots/desktop.png',
fullPage: true
});
// Tablet
await page.setViewportSize({ width: 768, height: 1024 });
await page.screenshot({
path: 'screenshots/tablet.png',
fullPage: true
});
// Mobile
await page.setViewportSize({ width: 375, height: 667 });
await page.screenshot({
path: 'screenshots/mobile.png',
fullPage: true
});
await browser.close();
}
captureScreenshots('http://localhost:3000');
Run: node screenshot.js
Using Puppeteer :
// screenshot.js
const puppeteer = require('puppeteer');
async function captureScreenshots(url) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle2' });
// Desktop
await page.setViewport({ width: 1920, height: 1080 });
await page.screenshot({
path: 'screenshots/desktop.png',
fullPage: true
});
// Tablet
await page.setViewport({ width: 768, height: 1024 });
await page.screenshot({
path: 'screenshots/tablet.png',
fullPage: true
});
// Mobile
await page.setViewport({ width: 375, height: 667 });
await page.screenshot({
path: 'screenshots/mobile.png',
fullPage: true
});
await browser.close();
}
captureScreenshots('http://localhost:3000');
Use this template to document visual changes:
## Visual Changes
### Desktop (1920x1080)

**Key changes**:
- Updated header navigation layout
- Improved spacing between sections
- Added hover states to buttons
### Tablet (768x1024)

**Key changes**:
- Stacked layout for sidebar
- Touch-friendly button sizes (48x48px)
- Adjusted typography for readability
### Mobile (375x667)

**Key changes**:
- Hamburger menu replaces horizontal nav
- Single column layout
- Bottom sticky CTA button
### Before/After Comparison
#### Before (Bug)

**Issue**: Text overflowing container on mobile
#### After (Fixed)

**Fix**: Applied word-wrap and max-width constraints
### Interaction States
#### Default State

#### Hover State

#### Active/Selected State

#### Error State

#### Loading State

## Responsive Design Notes
- Breakpoints: 768px (tablet), 375px (mobile)
- All touch targets > 44x44px
- Text remains readable at all sizes (min 16px body)
- No horizontal scrolling on any viewport
- Images scale proportionally
## Accessibility Checks
- [ ] Keyboard navigation works
- [ ] Focus states visible
- [ ] Color contrast meets WCAG AA (4.5:1)
- [ ] Alt text on images
- [ ] ARIA labels where needed
// tests/visual.spec.js
const { test, expect } = require('@playwright/test');
test.describe('Visual Regression', () => {
test('homepage looks correct on desktop', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.setViewportSize({ width: 1920, height: 1080 });
await expect(page).toHaveScreenshot('homepage-desktop.png');
});
test('homepage looks correct on mobile', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.setViewportSize({ width: 375, height: 667 });
await expect(page).toHaveScreenshot('homepage-mobile.png');
});
});
Run: npx playwright test --update-snapshots (first time to generate baselines)
For component-level visual testing:
// Button.stories.jsx
export default {
title: 'Components/Button',
component: Button,
};
export const Primary = () => <Button variant="primary">Click me</Button>;
export const Secondary = () => <Button variant="secondary">Click me</Button>;
2. Integrate Chromatic :
npm install --save-dev chromatic
npx chromatic --project-token=<token>
3. CI Integration (GitHub Actions):
# .github/workflows/chromatic.yml
name: Chromatic
on: push
jobs:
chromatic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx chromatic --project-token=${{ secrets.CHROMATIC_TOKEN }}
Before submitting PR with UI changes:
desktop-homepage.png)Problem : Screenshots are 5MB+ and slow to load in PR Solution : Compress images before uploading
# Using ImageMagick
convert input.png -quality 85 output.png
# Using pngquant
pngquant input.png --output output.png
Problem : Timestamps, random data make screenshots inconsistent Solution : Mock data or freeze time in tests
// Mock Date
const mockDate = new Date('2025-01-01T00:00:00Z');
jest.useFakeTimers();
jest.setSystemTime(mockDate);
// Or in Playwright
await page.addInitScript(() => {
Date.now = () => 1704067200000; // Fixed timestamp
});
Problem : Same code renders differently on different OS Solution : Use Docker for consistent environment
FROM mcr.microsoft.com/playwright:v1.40.0-jammy
WORKDIR /app
COPY . .
RUN npm ci
CMD ["npm", "run", "screenshot"]
screenshots/
├── desktop/
│ ├── homepage.png
│ ├── product-list.png
│ └── checkout.png
├── tablet/
│ ├── homepage.png
│ ├── product-list.png
│ └── checkout.png
└── mobile/
├── homepage.png
├── product-list.png
└── checkout.png
desktop-homepage-logged-in.pngmobile-form-error-state.pngbefore-header-fix.png, after-header-fix.pngname: Visual Testing
on: pull_request
jobs:
screenshots:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build app
run: npm run build
- name: Start app
run: npm start &
- name: Wait for app
run: npx wait-on http://localhost:3000
- name: Capture screenshots
run: node scripts/screenshot.js
- name: Upload screenshots
uses: actions/upload-artifact@v4
with:
name: screenshots
path: screenshots/
universal-verification-pre-merge - Pre-merge verification checklistuniversal-testing-webapp-testing - Web application testing patternstoolchains-javascript-testing-playwright - Playwright testing frameworkuniversal-debugging-verification-before-completion - Verification workflowsWeekly Installs
88
Repository
GitHub Stars
18
First Seen
Jan 23, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode71
claude-code71
gemini-cli66
codex65
cursor63
github-copilot60
Skills CLI 使用指南:AI Agent 技能包管理器安装与管理教程
44,900 周安装
Kalshi 预测市场 API 与 Python SDK 使用指南 - 体育赛事数据分析与交易
213 周安装
Airflow部署指南:Astro托管与开源Docker/K8s方案详解
220 周安装
AI画布设计工具:原创视觉艺术、海报、徽标、信息图表设计,支持PNG/PDF输出
218 周安装
项目文档协调器 - 自动化文档生成与上下文管理工具
217 周安装
自然语言处理(NLP)开发指南:Transformers、spaCy、NLTK实战与最佳实践
218 周安装
图书翻译助手translate-book:多语言PDF/EPUB/DOCX文档AI翻译工具
218 周安装