Extract and capture screenshots of specific UI elements mentioned in QA test procedures. Use when creating visual references for test steps to show exactly what buttons, fields, and components look like.
Extracts screenshots of specific UI elements mentioned in QA test steps (like buttons, fields, and links) and saves them to a structured directory. Use when creating visual references for test procedures to show exactly what elements look like.
/plugin marketplace add jpoutrin/product-forge/plugin install product-design@product-forge-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Capture targeted screenshots of UI elements referenced in test procedures to create visual documentation.
When a test step says "Click the Login button", capture a screenshot of that specific button so testers know exactly what to look for. This creates a visual glossary alongside full-page screenshots.
qa-tests/
├── active/
│ └── QA-20250105-001-login.md # QA test document
└── screenshots/
└── QA-20250105-001/ # Matches test-id
├── 01-initial-state.png # Full page screenshots
├── 02-form-filled.png
├── 03-success-state.png
└── elements/ # Extracted UI elements
├── login-button.png
├── email-field.png
└── password-field.png
Note: The {test-id} folder name (e.g., QA-20250105-001) matches the QA test document filename.
Identify actionable elements from test steps:
| Test Step Text | Element to Extract |
|---|---|
| "Click the Login button" | Login button |
| "Enter email in the Email field" | Email input field |
| "Select Settings from dropdown" | Settings menu item |
| "Check the Remember me checkbox" | Remember me checkbox |
| "Click the hamburger menu icon" | Hamburger menu icon |
Look for these patterns in test steps:
Action + "the" + [Element Name] + element type
Action verbs to scan:
Element type keywords:
Using Playwright MCP:
// Find element by accessible name or text
const element = page.getByRole('button', { name: 'Login' });
// Capture just this element
await element.screenshot({
path: 'qa-tests/screenshots/QA-20250105-001/elements/login-button.png'
});
| Attribute | Specification |
|---|---|
| Format | PNG (transparency support) |
| Padding | 8-16px around element |
| Background | Capture with page background |
| State | Default state unless specified |
| Max width | 400px (scale down if larger) |
For interactive elements, capture multiple states:
elements/
├── login-button.png # Default state
├── login-button-hover.png # Hover state
├── login-button-focus.png # Focus state
├── login-button-disabled.png # Disabled state (if applicable)
Generate a reference table in the test procedure:
## Element Visual Reference
| Element | Screenshot | Selector | Notes |
|---------|------------|----------|-------|
| Login button |  | `button[name="login"]` | Blue primary button |
| Email field |  | `input#email` | With placeholder |
| Remember me |  | `input#remember` | Unchecked by default |
// Button
const loginBtn = page.getByRole('button', { name: 'Login' });
await loginBtn.screenshot({ path: 'elements/login-button.png' });
// Link
const helpLink = page.getByRole('link', { name: 'Help' });
await helpLink.screenshot({ path: 'elements/help-link.png' });
// Input field
const emailInput = page.getByLabel('Email');
await emailInput.screenshot({ path: 'elements/email-field.png' });
// Element containing specific text
const submitBtn = page.getByText('Submit', { exact: true });
await submitBtn.screenshot({ path: 'elements/submit-button.png' });
// Using data-testid attribute
const navMenu = page.getByTestId('main-navigation');
await navMenu.screenshot({ path: 'elements/main-nav.png' });
// Capture parent for context
const field = page.locator('.form-group:has(#email)');
await field.screenshot({ path: 'elements/email-field-with-label.png' });
{element-name}[-{state}][-{variant}].png
| Element | Filename |
|---|---|
| Login button | login-button.png |
| Login button hovered | login-button-hover.png |
| Submit button disabled | submit-button-disabled.png |
| Email field with error | email-field-error.png |
| Primary nav expanded | primary-nav-expanded.png |
### TC-001: User Login
| Step | Action | Expected Result |
|------|--------|-----------------|
| 1 | Navigate to login page | Login form displays |
| 2 | Enter "test@example.com" in **Email field** | Email accepted |
| 3 | Enter "password123" in **Password field** | Password masked |
| 4 | Click **Login button** | Redirects to dashboard |
## Elements to Capture
From TC-001:
- [ ] Email field (`input[type="email"]`)
- [ ] Password field (`input[type="password"]`)
- [ ] Login button (`button[type="submit"]`)
Capture command:
1. Navigate to login page
2. Take element screenshots before any interaction
Create a reusable element glossary for the application:
elements-glossary/
├── buttons/
│ ├── primary-button.png
│ ├── secondary-button.png
│ ├── danger-button.png
│ └── icon-button.png
├── forms/
│ ├── text-input.png
│ ├── text-input-error.png
│ ├── select-dropdown.png
│ ├── checkbox.png
│ └── radio-button.png
├── navigation/
│ ├── main-nav.png
│ ├── breadcrumb.png
│ └── sidebar-menu.png
└── feedback/
├── success-toast.png
├── error-alert.png
└── loading-spinner.png
#### Step 2: Enter credentials
Enter your email in the Email field:

Then enter your password in the Password field:

When extracting, note identifying characteristics:
| Element | Visual | Identification Tips |
|---------|--------|---------------------|
| Login button |  | Blue button, right side of form, text "Log In" |
| Forgot password |  | Gray link below password field |
When creating a new QA test:
⚠️ Element "Submit button" not visible on initial load.
Trigger: Appears after form validation passes.
Action: Capture after filling required fields.
⚠️ Element "Loading spinner" is transient.
Capture: Use video or multiple timed captures.
⚠️ Multiple "Delete" buttons found (3 instances).
Resolution: Capture each with context or specify row/position.
Files: delete-button-row-1.png, delete-button-row-2.png
Before finalizing element screenshots:
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.