ui-polish
Skill2 starsChanged 41 days agoMITView on GitHub
Visual and interaction craft for Vue 3 / Vuetify and Flutter UI — typography, color and contrast, spacing and hierarchy, interaction states, responsive behaviour, UX copy, and the invisible details that make interfaces feel considered. Use on your own, without being asked, BEFORE writing markup whenever you build a new screen or change the layout of an existing one (web or mobile) — it makes you match the app's sibling screens and kit first. Also use when reviewing UI that looks generic, unbalanced, or unfinished, or when choosing type scales, palettes, spacing systems, focus/hover/disabled states, or button and error copy. NOT for motion — all animation, transitions, springs, gestures, and scroll/pointer-driven effects belong to the `animate` skill. Adapted from Emil Kowalski's design engineering philosophy.
We split this skill into the rules it gives an agent
8 rules. 0 are common, 8 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 11 edited versions we read keep these.
8
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 10
If you invoked this yourself while building or changing a screen, skip the greeting below and go straight to Build mode.
- Distinctive: line 12
When the user invokes this skill without a specific question, respond only with:
- Distinctive: line 16
Do not provide any other information until the user asks a question.
- Distinctive: line 44
Parity across variants: When a composer, form or action has modes (customer reply vs internal note, create vs edit, roles), a capability …
- Distinctive: line 68
When building UI, don't just make it work.
- Distinctive: line 76
Every decision below exists because the aggregate of invisible correctness creates interfaces people love without knowing why.
- Distinctive: line 84
When reviewing UI code, you MUST use a markdown table with Before/After columns:
- Distinctive: line 95
Write the Before/After in the target platform's own syntax — a CSS diff shown to someone working in Dart is noise.
“Common” is measured: kept by at least 6 in 10 of the 11 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Design Engineering
Initial Response
If you invoked this yourself while building or changing a screen, skip the greeting below and go straight to Build mode.
When the user invokes this skill without a specific question, respond only with:
I'm ready to help you polish your interfaces — type, color, spacing, interaction states, and the invisible details that make software feel right. Works on Vue 3 / Vuetify and Flutter. This knowledge is adapted from Emil Kowalski's design engineering philosophy. For deeper learning, check out animations.dev.
Do not provide any other information until the user asks a question.
You are a design engineer with craft sensibility. You build interfaces where every detail compounds into something that feels right. You understand that in a world where everyone's software is good enough, taste is the differentiator.
Scope — and the one thing this skill does NOT do
This skill owns the still frame: what the interface looks like and how it responds, at rest.
It does not own motion. Animation, transitions, easing curves, durations, springs, stagger, gestures and drag physics, scroll- and pointer-driven effects, and the decision of whether something should animate at all belong entirely to the animate skill. That skill carries the decision map, the combo library, the platform recipes, and a verification harness. If a question is about how something moves, hand it over rather than answering here — two skills answering the same question is how they drift into contradicting each other.
The boundary is simple: if it changes over time, it's animate. If it's true in a screenshot, it's here.
Build mode — match the app before you write a widget
A screen in an existing app is judged against its neighbours first, not against taste. Most ugly agent-built screens are not badly styled; they are foreign: a layout the rest of the app never uses, hand-rolled widgets beside a kit that already has them. Before writing markup:
- Open the closest sibling screen (same kind: detail, list, form, thread) and note its structure — section order, cards, how secondary content (history, remarks, logs) is reached (inline, tab, sheet), where actions sit. Reuse that structure unless the user asked for a new one.
- Use the kit and tokens. Find the shared component folder and theme tokens; every row, badge, card, spacing and colour comes from there. A hand-rolled widget needs a reason the kit can't meet.
- Keep different kinds of content apart. Conversation (messages), an activity/audit log, and facts are different things to a user. Don't interleave them in one feed with only a section label between; separate them the way the sibling screen does (tab, sheet, or clearly distinct region with its own title), and label each so a first-time user can tell which is which.
- Parity across variants. When a composer, form or action has modes (customer reply vs internal note, create vs edit, roles), a capability added to one mode exists in the others unless there is a stated reason. Check the backend accepts it before gating it in the UI.
- Then apply the rest of this skill and the checklist below.
Reference Documents
Consult these for deep guidance on specific topics. The principles are stack-agnostic; the code examples show Vue 3 / Vuetify and Flutter side by side, so read the pair that matches the target.
- Typography — scales, pairing, loading, OpenType features
- Color & Contrast — OKLCH, palettes, WCAG, dark mode
- Spatial Design — spacing systems, grids, hierarchy, depth
- Interaction Design — 8 states, focus rings, forms, overlays, keyboard nav
- Responsive Design — mobile-first, breakpoints, input detection, safe areas
- UX Writing — button labels, error messages, empty states, terminology
- Anti-Patterns — AI slop detection, generic patterns to avoid, missing elements checklist
- Motion → the
animateskill, not a reference here.
Core Philosophy
Taste is trained, not innate
Good taste is not personal preference. It is a trained instinct: the ability to see beyond the obvious and recognize what elevates. You develop it by surrounding yourself with great work, thinking deeply about why something feels good, and practicing relentlessly.
When building UI, don't just make it work. Study why the best interfaces feel the way they do. Reverse engineer what you admire. Inspect it. Be curious.
Unseen details compound
Most details users never consciously notice. That is the point. When a feature functions exactly as someone assumes it should, they proceed without giving it a second thought. That is the goal.
"All those unseen details combine to produce something that's just stunning, like a thousand barely audible voices all singing in tune." — Paul Graham
Every decision below exists because the aggregate of invisible correctness creates interfaces people love without knowing why.
Beauty is leverage
People select tools based on the overall experience, not just functionality. Good defaults and considered detail are real differentiators. Beauty is underutilized in software. Use it as leverage to stand out.
Review Format (Required)
When reviewing UI code, you MUST use a markdown table with Before/After columns:
| Before | After | Why |
color: #6b7280 on white | color: #4b5563 | 4.6:1 clears WCAG AA for body text; the original is 4.0:1 and fails |
font-size: 13px; line-height: 1.2 | line-height: 1.5 | Body copy under ~1.4 line-height is measurably harder to scan |
padding: 11px 13px | padding: 12px / 16px | Arbitrary values; snap to the spacing scale or it reads as unsystematic |
| Icon button 28×28 | 44×44 hit area (visual size can stay) | Below 44px fails touch-target guidance regardless of how it looks |
:hover styling with no :focus-visible | Add :focus-visible with a visible ring | Keyboard users get no affordance at all otherwise |
| Button labelled "Submit" | "Create order" | Label the outcome, not the mechanism |
Write the Before/After in the target platform's own syntax — a CSS diff shown to someone working in Dart is noise. The Flutter equivalents of the rows above:
| Before | After | Why |
TextStyle(fontSize: 13, height: 1.2) | height: 1.5 | height is a multiplier in Flutter, not px — 1.2 is as tight as web's 1.2 |
EdgeInsets.symmetric(horizontal: 11, vertical: 13) | EdgeInsets.all(Tokens.space3) | Arbitrary values; snap to the scale or it reads as unsystematic |
IconButton at 28×28 | minimumSize: Size(48, 48) (visual size can stay) | Material guidance is 48dp; below that fails touch-target regardless of looks |
InkWell with no focus affordance | add focusColor / a Focus ring | Flutter draws no focus ring by default on custom widgets — keyboard users get nothing |
EdgeInsets.only(left: 16) | EdgeInsetsDirectional.only(start: 16) | Plain EdgeInsets does not flip under RTL |
onPressed: () {} on a busy button | onPressed: null while busy | The null callback is the disabled state; an empty closure looks enabled and does nothing |
Pick the rows that fit what you actually found — don't pad the table to look thorough. If the UI is genuinely fine, say so.
Checklist before you call it done
- Text meets contrast minimums (4.5:1 body, 3:1 large/UI) in every theme the app ships, not just the default one.
- Every interactive element has hover, focus, active, and disabled states — not just hover.
Web:
:focus-visible. Flutter:WidgetStateProperty/ an explicitFocusring, since nothing is drawn for you. On touch targets hover never fires — don't hide meaning in it. - Touch targets are ≥44px (web/iOS) or ≥48dp (Material), even where the visual affordance is smaller.
- Spacing and type sizes come from the scale, not from eyeballed one-off values.
- Empty, loading, and error states exist and say something useful.
- Copy names outcomes, not mechanisms; errors say what to do next.
- Layout survives OS text scaling — on mobile this is far more aggressive than browser zoom, and hardcoded heights are where it breaks.
- Directional padding is direction-safe if the app ships an RTL locale.
- Nothing here is a motion decision — if it moves, it went to
animate.
Other versions15 projects use a version of this.
Word for word · 1
- AhmedMerza/claude-skills★ 2100% same
Edited · 0
None found.
Wrote their own version · 14
- felvieira/claude-skills-fv★ 27same name
- icons8/agent-skills★ 12same name
- The-Utopia-Studio/skills★ 6same name
- aictrl-dev/skills★ 2same name
- cindyeme/ui-polish★ 2same name
- jukrap/ai-agent-playbook★ 2same name
- indubitably-ai/indubitably-skills★ 1same name
- manastalukdar/ai-devstudio★ 1same name
- Mheaus/claude-skills★ 1same name
- napnap11/claude-skills★ 1same name
4 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository53 other files it gives its agents.
- animateSkill
- api-docs-completeSkill
- best-optionSkill
- browseSkill
- changelog-generateSkill
- checkpointSkill
- claimSkill
- commitSkill
- courtSkill
- design-driftSkill
- designSkill
- expandSkill
- explainSkill
- fix-reviewSkill
- grill-meSkill
- handover-listSkill
- handover-resumeSkill
- handover-saveSkill
- i18n-syncSkill
- issueSkill
- leadSkill
- mr-approveSkill
- mr-assignSkill
- mr-createSkill
- mr-guideSkill
- mr-listSkill
- mr-mergeSkill
- mr-review-requestSkill
- mr-reviewSkill
- mr-statusSkill
- persona-walkthroughSkill
- ponytailSkill
- prove-the-testSkill
- qa-crawlSkill
- qa-sweepSkill
- reflectSkill
- reviewSkill
- root-causeSkill
- scoutSkill
- second-opinionSkill
- ship-checkSkill
- skill-auditSkill
- skill-compareSkill
- spinoffSkill
- story-siteSkill
- tool-compareSkill
- ui-auditSkill
- usage-weekSkill
- ux-auditSkill
- validate-planSkill
- video-teardownSkill
- wait-whatSkill
- where-were-weSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

