Refina detalhes visuais e interacoes de interfaces existentes. Trigger em: "polish", "deixar mais refinado", "parece meio off", "acabamento", "border radius", "alinhamento optico", "font smoothing", "tabular numbers", "shadow em vez de border", "sombra pra dar profundidade", "stagger na animacao de entrada", "animacao de saida", "scale on press", "stagger animation", "hit area", "image outline", "revisar detalhes visuais".
87%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Grandes interfaces raramente vêm de uma coisa só. É uma coleção de pequenos detalhes que se acumulam. Esta skill entra depois que Frontend (04) e/ou Motion Design (12) já produziram o componente — ela revisa e ajusta acabamento, não substitui a estrutura.
Para projetos sem Framer Motion (ou quando a transição é puramente CSS), copiar direto de templates/transitions.css em vez de reescrever a regra em prosa — o arquivo tem snippets nomeados (t-fade, t-scale-press, t-icon-swap, etc.) já com guard de prefers-reduced-motion embutido. Os valores no CSS espelham os princípios abaixo; se um valor mudar aqui, replicar no arquivo.
Esta skill segue GLOBAL.md, policies/execution.md, policies/handoffs.md, policies/token-efficiency.md e policies/evals.md.
Para exemplos extensos de CSS/Tailwind/Motion por categoria, consultar docs/skill-guides/ui-polish.md apenas quando necessario.
Raio externo = raio interno + padding. Raios diferentes em elementos aninhados e a coisa mais comum que faz uma interface parecer errada.
outerRadius = innerRadius + paddingSe o padding for maior que 24px, tratar as camadas como superficies separadas — nao forcar concentricidade.
Quando a centralizacao geometrica parece errada, alinhar oticamente. Botoes com icone, triangulos de play e icones assimetricos (estrela, seta, caret) precisam de ajuste manual.
padding do lado do icone = padding do lado do texto - 2pxmargin-left: 2px)Para cards, containers e botoes com proposito de profundidade/elevacao, usar box-shadow em camadas transparentes em vez de border solida. Sombra se adapta a qualquer fundo; borda solida nao.
Nao aplicar em dividers (border-b, border-t, separadores de layout) — esses continuam borda.
--shadow-border:
0px 0px 0px 1px rgba(0, 0, 0, 0.06),
0px 1px 2px -1px rgba(0, 0, 0, 0.06),
0px 2px 4px 0px rgba(0, 0, 0, 0.04);Dark mode: simplificar pra um unico ring branco (0 0 0 1px rgba(255, 255, 255, 0.08)).
CSS transitions para mudancas de estado interativas (hover, toggle, abrir/fechar) — retomam de onde pararam se o usuario mudar de intencao no meio. Keyframes ficam reservados para sequencias que rodam uma vez (loading, entrada de pagina) — reiniciam do zero se interrompidas, o que parece quebrado em elemento interativo.
Nao animar um container unico. Quebrar em blocos semanticos (titulo, descricao, botoes) e escalonar com ~100ms de delay entre eles. Para titulos, considerar quebrar em palavras individuais com ~80ms de stagger. Combinar opacity + blur + translateY.
Saida deve ser mais discreta que entrada — o foco do usuario ja foi pro proximo lugar. Usar translateY pequeno e fixo (ex: -12px), nao a altura total do elemento. Duracao de saida menor que entrada (ex: 150ms vs 300ms). Nunca remover a animacao de saida completamente (display: none direto) — motion sutil preserva contexto.
Ao trocar icone (hover, mudanca de estado), animar com opacity + scale + blur em vez de so alternar visibilidade. Valores exatos, sem desvio:
scale: 0.25 → 1 (nunca 0.5 ou 0.6)opacity: 0 → 1filter: blur(4px) → blur(0px)motion/framer-motion no package.json: transition: { type: "spring", duration: 0.3, bounce: 0 } — bounce sempre 0cubic-bezier(0.2, 0, 0, 1) — da entrada e saida sem dependencia nova-webkit-font-smoothing: antialiased + -moz-osx-font-smoothing: grayscale no root do layout (afeta so macOS, seguro aplicar universal).
font-variant-numeric: tabular-nums (Tailwind: tabular-nums) em qualquer numero que atualiza dinamicamente (contador, preco, timer, coluna de tabela) — evita layout shift. Nao usar em numeros estaticos (versao, CEP, telefone).
text-wrap: balance (Tailwind: text-balance) em headings — so funciona ate 6 linhas (Chromium) / 10 (Firefox), nao usar em paragrafo longotext-wrap: pretty (Tailwind: text-pretty) em paragrafo curto/medio, descricao, caption, item de lista — evita palavra orfa na ultima linhaOutline sutil de 1px em imagens para profundidade consistente. Regra de cor nao-negociavel: preto puro rgba(0, 0, 0, 0.1) no light mode, branco puro rgba(255, 255, 255, 0.1) no dark mode. Nunca usar near-black/near-white da paleta do projeto (slate-900, zinc-900, etc) — outline com tinta pega a cor da superficie ao redor e parece sujeira na borda da imagem.
<img className="outline outline-1 -outline-offset-1 outline-black/10 dark:outline-white/10" />scale(0.96) sutil no click para feedback tatil. Sempre 0.96 — nunca menor que 0.95 (fica exagerado). Usar CSS transition (interrompivel). Adicionar prop static no componente de botao pra desabilitar quando o movimento for indesejado.
initial={false} em AnimatePresence evita animacao de entrada no primeiro render — funciona bem pra icon swap, toggle, tabs. Nao usar quando o componente depende do initial pra configurar a entrada da pagina (hero com stagger, loading state) — verificar sempre com refresh completo da pagina.
transition: allSempre especificar propriedades exatas: transition-property: scale, opacity. Tailwind transition-transform cobre transform, translate, scale, rotate — usar quando so anima transform; para multiplas propriedades nao-transform, usar transition-[scale,opacity,filter].
will-change com ModeracaoSo para transform, opacity, filter, clip-path — propriedades que a GPU compoe. Nunca will-change: all. Adicionar so quando notar stutter no primeiro frame (Safari se beneficia mais); nao adicionar preventivamente — cada layer de composicao custa memoria.
Elementos interativos precisam de pelo menos 40x40px (WCAG pede 44x44px) de area clicavel. Estender com pseudo-elemento se o elemento visivel for menor (ex: checkbox 20x20). Duas areas de hit nunca podem sobrepor — se colidir, encolher o pseudo-elemento até nao colidir.
| Erro | Correcao |
|---|---|
| Mesmo border radius em pai e filho | Calcular outerRadius = innerRadius + padding |
| Icone parece descentralizado | Ajustar oticamente com padding ou corrigir SVG direto |
| Borda dura entre secoes | Usar box-shadow em camadas com transparencia |
| Animacao de entrada/saida abrupta | Split, stagger, e manter saida sutil |
| Numero causa layout shift | Aplicar tabular-nums |
| Texto pesado no macOS | Aplicar antialiased no root |
| Animacao toca no page load | Adicionar initial={false} no AnimatePresence |
transition: all em elementos | Especificar propriedades exatas |
| Stutter no primeiro frame | Adicionar will-change: transform (com moderacao) |
| Hit area minuscula em controle pequeno | Estender com pseudo-elemento ate 40x40px |
Sempre apresentar mudancas como tabela markdown com colunas Before e After, agrupadas por principio (um heading por principio, uma tabela por heading). Incluir toda mudanca feita, nao um subconjunto. Se um principio foi revisado mas nada precisou mudar, omitir a tabela inteira — tabela vazia so gera ruido.
#### Border radius concentrico
| Before | After |
| --- | --- |
| `rounded-xl` no card + `rounded-xl` no botao interno (`p-2`) | `rounded-2xl` no card (`12+8`), `rounded-lg` no botao interno |
#### Scale on press
| Before | After |
| --- | --- |
| `scale(0.9)` no press | Ajustado para `scale(0.96)` — abaixo de `0.95` fica exagerado |tabular-numstext-wrap: balance; paragrafos curtos usam text-wrap: prettyAnimatePresence usa initial={false} quando o estado default nao deve animar no loadtransition: all — sempre propriedades especificaswill-change so em transform/opacity/filter/clip-path, nunca allCheckpoint: marcar um item nesta checklist exige ter visto o resultado no browser (não no código-fonte) — "usei tabular-nums" não é evidência de que o número não pula mais durante contagem, é evidência de que a classe existe. Item que não foi visualmente confirmado fica desmarcado, não vira aposta otimista.
Esta skill NAO cria componentes novos — ajusta acabamento no MESMO codebase do Frontend/Motion. Se Motion Design ainda nao rodou e a tarefa envolve sistema de animacao amplo (nao so detalhe pontual), delegar a 12-motion-design primeiro.
ZERO comentarios explicando o que o codigo faz. Nomes de classes/variaveis autoexplicativos. Comentario so quando existe uma restricao nao-obvia (ex: por que um valor exato como bounce: 0 ou scale(0.96) foi escolhido, se nao for evidente do contexto).
templates/transitions.css) inspirado em Jakubantalik/transitions.dev.felvieira/claude-skills-fv
449fb53
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.