From ux-harness
Verify migrated or newly built components match Storybook's established style and organizational structure. Checks against all four Storybook sections — Foundations (colors, typography, icons, spacing, borders), Components (buttons, inputs, cards, tabs, badges), Widget Garage (composed widgets), and Page Examples (layout conventions) — not just individual token matches. Primary goal is reuse from Storybook; secondary is style consistency for genuinely new code. Run after any migration, refactor, or build to catch drift before it ships. Triggers on: "ux-polish", "does this match storybook", "style check", "polish this", "does this look right", "visual check", or after any ux-migrate/ux-refactor/ ux-component-builder completes.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ux-harness:ux-polishThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Verify that code reuses Storybook components wherever possible and visually matches Storybook's established style where it doesn't. The primary goal is **reuse from Storybook** — don't reinvent what already exists. The secondary goal is style consistency for genuinely new code.
Verify that code reuses Storybook components wherever possible and visually matches Storybook's established style where it doesn't. The primary goal is reuse from Storybook — don't reinvent what already exists. The secondary goal is style consistency for genuinely new code.
Announce at start: "Running Storybook polish check — looking for reuse opportunities and style drift..."
Run ux-prime to load:
If ux-prime reports no Storybook detected, stop: "No Storybook found — can't verify style without a reference. Run ux-audit to assess gaps."
What files to check:
--staged → check git diff --name-only --cached--diff → check git diff main...HEAD --name-only.tsx and .jsx files in src/Before checking style, check if Storybook already has what this code is building.
For each file in scope:
REUSE OPPORTUNITIES:
[filename.tsx] line 24-45: Renders a metric card with gauge
→ MetricCard exists in Storybook (Widget Garage/Metric Card)
→ Import: @components/common/MetricCard
→ Props: { name, type, passRate, coverage }
→ Stories: Healthy, Warning, NoData, Loading
→ Recommendation: REPLACE 22 lines of JSX with <MetricCard ... />
[filename.tsx] line 52-68: Renders a nav sidebar
→ SideNav exists in Storybook (Widget Garage/SideNav)
→ Import: @components/layout/SideNav
→ Recommendation: REPLACE with <SideNav items={...} />
[filename.tsx] line 80-95: Renders a card container — no Storybook match
→ Proceed to style check (Step 4) for this block
Every pattern that has a Storybook component should use that component, not reinvent it. This is the most important check ux-polish does.
Check the code against each high-level Storybook section — not just individual components, but the conventions each section establishes.
Use the Storybook Section Map from ux-prime to verify compliance at every layer:
Does the code follow the design primitives established in the Foundations section?
bg-*, text-*, border-* classes from the Foundations/Colors palette? Flag any class not in the palette.text-[17px])?Does the code use existing Components where applicable?
Does the code use existing Widgets for composed patterns?
Does the code follow the page layout conventions from Page Examples?
SECTION COMPLIANCE:
Foundations:
✓ Colors — all classes in palette
⚠ Typography — text-[15px] not in type scale (line 42) → use text-sm
✓ Icons — all Lucide, correctly sized
✓ Spacing — all values in scale
✓ Borders & Shadows — matches
Components:
⚠ 3 buttons rendered — 2 use Storybook Button, 1 is custom (line 67)
→ Custom button could be <Button variant="ghost" size="sm" />
✓ Cards use Storybook Card component
✓ Badges use Storybook Badge component
Widget Garage:
✗ Lines 24-45 render a metric display → MetricCard exists
→ REPLACE with <MetricCard name={...} passRate={...} />
✓ SideNav is imported from Storybook
Page Examples:
✓ Layout follows Card Grid pattern (grid-cols-3, gap-6, p-8)
For code that has no Storybook component match (Step 3 found nothing) and no section-level issue (Step 4 passed), fall back to the Storybook Style Reference for fine-grained visual consistency.
Compare every class in genuinely new code against the Storybook Style Reference. Check all 10 element categories:
bg-* classes does this file use?bg-bg-page. Containers should be bg-bg-default or bg-bg-elevated. Are they?text-tx-header / text-tx-strong like Storybook?text-tx-primary?text-tx-weak?text-status-critical-text, text-status-success-text?border-bd-default?border-bd-weak?hover:border-bd-primary?p-3 and p-5 on the same type of element)rounded-xl like Storybook?rounded-lg or rounded-md?rounded-full?text-sm? text-base?text-xs text-tx-weak?font-semibold for headings, font-medium for labels?lucide-react?w-4 h-4 (small) or w-5 h-5 (medium) like Storybook?aria-label or aria-hidden?transition-colors or transition-all?duration-200 like Storybook?hover:bg-bg-elevated, not ad-hoc)flex items-center justify-center)?UX Polish Report
════════════════
Files checked: [count]
═══ REUSE OPPORTUNITIES (replace, don't reinvent) ═══
[filename.tsx] lines 24-45: metric card pattern → USE <MetricCard />
[filename.tsx] lines 52-68: sidebar pattern → USE <SideNav />
Total: [N] patterns could be replaced with Storybook imports
Estimated lines removed: [N]
═══ SECTION COMPLIANCE ═══
Foundations:
✓ Colors — all classes in palette
⚠ Typography — text-[15px] not in type scale (line 42) → use text-sm
✓ Icons — all Lucide, correctly sized
✓ Spacing — all values in scale
✓ Borders & Shadows — matches
Components:
⚠ 3 buttons rendered — 2 use Storybook Button, 1 is custom (line 67)
✓ Cards use Storybook Card component
Widget Garage:
✗ Lines 24-45 render metric display → MetricCard exists → REPLACE
✓ SideNav imported from Storybook
Page Examples:
✓ Layout follows Card Grid pattern
═══ STYLE DRIFT (genuinely new code that doesn't match Storybook) ═══
[filename.tsx] — Reference: Style Reference (aggregate)
⚠ Spacing: p-3 — Storybook widgets use p-5 → FIX
⚠ Radius: rounded-md — Storybook cards use rounded-xl → FIX
⚠ Icons: w-6 h-6 — Storybook uses w-5 h-5 → FIX
✗ Hover: no hover state — Storybook uses hover:border-bd-primary → ADD
✓ Backgrounds, Text, Borders, Typography, Transitions, Layout: match
[filename2.tsx] — Reference: Style Reference (aggregate)
✓ All 10 categories match established patterns
Summary:
🔄 Reuse: [N] patterns should be Storybook imports (not custom code)
📐 Sections: [N/4] Storybook sections fully compliant
⚠ Drift: [N] style differences on genuinely new code
✓ Match: [N] files fully match Storybook style
Polish score: [N]% (reuse + section compliance + style match combined)
After presenting the report:
Found [N] reuse opportunities and [M] style drift issues.
Reuse fixes (replace custom code with Storybook imports):
1. [filename.tsx] lines 24-45 → <MetricCard />
2. [filename.tsx] lines 52-68 → <SideNav />
Style fixes (align new code with Storybook patterns):
3. [filename.tsx] line 15: p-3 → p-5
4. [filename.tsx] line 22: rounded-md → rounded-xl
Apply fixes? (yes / no / pick)
- "yes" → Apply all reuse replacements and style fixes
- "no" → Leave as-is
- "pick" → Choose by number
Wait for user decision. Do NOT auto-fix.
rounded-xl on cards, every card should use rounded-xl. Period.ux-guard catches rule violations. ux-polish catches "it works but doesn't reuse what's already there" and "it works but doesn't look right."Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub jakecjones/ux-harness --plugin ux-harness