/arc:polish
Visual refinement
—What it does
Polish performs a systematic visual quality audit on a component or page. It screenshots current state, checks spacing against your scale, verifies all interactive states exist (default, hover, focus, active, disabled, loading, error, success), validates contrast ratios, audits typography hierarchy, and reviews motion. All fixes use Tailwind classes.
—Why it exists
The gap between "it works" and "it's polished" is where most AI-generated UI falls short. Polish catches the things you stop noticing after staring at code—inconsistent spacing, missing focus states, cramped padding, contrast failures. It's the last step before shipping, not the first.
—Design decisions
- —User-interactive, not agent-delegated. You see every finding and approve every fix.
- —Uses browser screenshots for visual verification, with Chrome MCP preferred in Claude Code.
- —All fixes expressed in Tailwind classes.
Source document
Polish Workflow
Pre-ship visual refinement. The last step before shipping, not the first.
Announce at start: "I'm using the polish skill for a final visual quality pass."
This skill is user-interactive. Do NOT spawn agents. Polish requires visual inspection and judgment — it's collaborative, not delegated. Polish is the last step, not the first. Don't begin until functionality is complete.
Phase 0: Load References (MANDATORY)
Phase 1: Visual Capture
Screenshot current state. Prefer Chrome MCP in Claude Code. Outside Claude, prefer agent-browser, then Playwright if needed:
1. mcp__claude-in-chrome__tabs_context_mcp
2. mcp__claude-in-chrome__navigate to the feature URL
3. mcp__claude-in-chrome__computer action=screenshot (desktop)
4. mcp__claude-in-chrome__resize_window width=375 height=812
5. mcp__claude-in-chrome__computer action=screenshot (mobile)
6. mcp__claude-in-chrome__resize_window width=1440 height=900
If no browser tool is available, ask the user to provide the component/page path or screenshots and review code directly.
Phase 2: Systematic Audit
Work through each dimension. Report findings as you go.
2.1 Spacing Verification
Check all spacing against the 4px scale (Tailwind's built-in: 1=4px, 2=8px, 3=12px, 4=16px, 6=24px, 8=32px):
- Section padding consistent (
p-4 md:p-6 lg:p-8or similar) - Card/container padding not cramped (minimum
p-4for compact,p-6standard) - Gap between elements uses
gap-*not margin hacks - Button padding not cramped (
px-4 py-2minimum standard) - Heading
margin-bottomcreates hierarchy (heading closer to its body than to content above) - Consistent rhythm top to bottom
- No arbitrary spacing values (
p-[13px]) - Content width constrained (
max-w-prosefor body text)
2.2 Interactive State Completeness
For every interactive element, verify all 8 states:
| State | Check | Common Tailwind |
|---|---|---|
| Default | Base styling present | — |
| Hover | Subtle feedback (gated to hover:hover) | hover:bg-gray-100 |
| Focus | Visible ring for keyboard | focus-visible:ring-2 |
| Active | Press feedback | active:scale-[0.97] |
| Disabled | Reduced opacity, no pointer | disabled:opacity-50 disabled:pointer-events-none |
| Loading | Spinner or skeleton | aria-busy="true" |
| Error | Red border, message | aria-invalid:border-red-500 |
| Success | Confirmation feedback | — |
- No hover-only interactions (touch users excluded)
- Focus rings visible and consistent
- Disabled states prevent interaction
2.3 Contrast & Color
- Body text passes 4.5:1 against background
- Large text (≥18px bold, ≥24px) passes 3:1
- UI components (borders, icons) pass 3:1
- Placeholder text passes 4.5:1 (commonly fails)
- No grey text on colored backgrounds
- No pure black (#000) on pure white (#fff)
- Color not used as sole indicator
2.4 Typography
-
antialiasedon body - Heading hierarchy clear (size + weight + color, not size alone)
- Body text minimum 16px (
text-base) - Line length constrained (45-75 characters)
-
text-balanceon headings,text-prettyon body -
tabular-numson data tables, prices, timers - No weight change on hover (causes layout shift)
2.5 Motion
- Entering elements use
ease-out(notease-in) - Durations appropriate (100-150ms feedback, 200-300ms state changes)
-
prefers-reduced-motionrespected - Only
transformandopacityanimated (nowidth,height,top) - Exit animations faster than entrances (~75% duration)
2.6 Responsive
- No horizontal scroll on mobile
- Touch targets minimum 44px
- Text readable without zooming
- Images don't overflow container
Phase 3: Report & Fix
Present findings grouped by severity:
Critical (must fix)
- Contrast failures
- Missing focus states
- Broken mobile layout
- Touch targets too small
High (should fix)
- Inconsistent spacing
- Missing interactive states
- Typography hierarchy unclear
Medium (nice to fix)
- Motion refinements
- Spacing fine-tuning
- Dark mode adjustments
For each finding: state what's wrong, show the current Tailwind classes, show the fix (new Tailwind classes), then ask for approval before applying:
AskUserQuestion:
question: "Apply this fix?"
header: "Polish Fix"
options:
- label: "Apply"
description: "Apply this fix now"
- label: "Skip"
description: "Skip this fix and move to the next finding"
- label: "Apply all"
description: "Apply this and all remaining fixes without asking"
If the user selects "Apply all", apply all remaining fixes without further prompts.
Phase 4: Verify
After all fixes, screenshot again:
1. mcp__claude-in-chrome__computer action=screenshot (desktop)
2. mcp__claude-in-chrome__resize_window width=375 height=812
3. mcp__claude-in-chrome__computer action=screenshot (mobile)
Compare before/after. Confirm improvements with user.
Phase 5: Final Checklist
Run the Design Review Checklist from frontend-design.md:
- Zero red flags
- Spacing consistent and generous
- All interactive states designed
- Contrast compliant
- Typography intentional
- Motion purposeful
- Mobile responsive
"Zoom in. Squint at it. Use it yourself."