Communitygithub.com

figma-lens

Implemente interfaces de usuário a partir de designs do Figma com precisão de pixels usando exportações do figma-lens (design/<frame>/spec.md, tokens.json, screenshots, ícones SVG) — sem necessidade de Figma MCP ou Modo Dev. Use sempre que o usuário pedir para construir, implementar, igualar ou corrigir uma tela/componente "do Figma", mencionar uma pasta design/ ou exportação figma-lens, ou quiser código Flutter ou web (HTML/CSS/React/Tailwind) que corresponda a um frame do Figma.

O que é figma-lens?

figma-lens é uma habilidade para agentes de IA que permite construir interfaces de usuário a partir de designs do Figma com precisão de pixels, sem depender de plugins MCP ou do Modo Dev do Figma. A habilidade utiliza exportações geradas pelo plugin figma-lens, que incluem um arquivo `spec.md` com a árvore de camadas e valores exatos, `tokens.json` com variáveis e estilos, screenshots, ícones SVG e imagens. O fluxo de trabalho envolve ler o `spec.md`, inspecionar as imagens exportadas, mapear componentes e tokens do Figma para o código existente do projeto (seja Flutter ou Web com CSS/Tailwind/React), construir a UI seguindo a árvore de layout, e verificar a precisão através de um loop de comparação e correção usando o comando `figma-lens check`. A habilidade suporta tanto Flutter quanto desenvolvimento web, fornecendo tabelas de mapeamento detalhadas para cada plataforma. A saída final é um JSON contendo nome, descrição, resumo e o conteúdo completo da SKILL.md traduzido para o português.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MohamedRamadanSalah/figma-lens/tree/HEAD/skill/figma-lens

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

figma-lens: construa UI que corresponda ao Figma

figma-lens é um plugin do Figma mais uma ponte local. O usuário seleciona frames no Figma desktop e clica em Exportar para Claude. A ponte escreve uma pasta por frame:

design/
  INDEX.md                  ← lista de todos os frames exportados (comece aqui)
  <frame>/
    spec.md                 ← LEIA PRIMEIRO: árvore de camadas compacta com valores exatos
    spec.json               ← dados completos (+ CSS por camada do Figma) quando spec.md não é suficiente
    tokens.json             ← variáveis (todos os modos), estilos, contagens de uso de valores brutos
    [email protected]           ← renderização completa (2x por padrão)
    sections/NN-nome.png    ← recortes dos blocos de nível superior em resolução total
    assets/*.svg            ← ícones/arte vetorial, prontos para uso
    images/*                ← bitmaps originais usados como preenchimentos de imagem
    compare/                ← escrito por `figma-lens check` (report.md, side-by-side.png, diff.png)
figma-lens.map.json         ← (raiz do projeto) componente/token do Figma → código real neste projeto

O comando figma-lens é a CLI do repositório figma-lens (npm link lá o torna global; caso contrário, execute node <figma-lens>/bin/figma-lens.js …). Execute figma-lens help para todos os comandos.

Se ainda não houver exportação

  1. Inicie a ponte para o projeto do usuário e mantenha-a em execução (em segundo plano): figma-lens bridge --out <projeto>/design.
  2. Peça ao usuário para selecionar o(s) frame(s) no Figma desktop → Plugins → Desenvolvimento → Figma Lens → Exportar para Claude.
  3. Leia design/INDEX.md para confirmar que chegou.

Nunca adivinhe um design a partir de uma descrição quando uma exportação for possível. Peça a exportação.

Fluxo de Trabalho

  1. Leia spec.md completamente (é pequeno). Observe o tamanho do frame, a árvore de layout, as variáveis e estilos, e os ativos.
  2. Veja as imagens. Leia sections/*.png uma a uma para obter detalhes. Use [email protected] apenas para a visão geral, porque imagens grandes são redimensionadas quando você as visualiza. Os valores sempre vêm do spec, nunca medindo pixels.
  3. Use o mapa de componentes (veja "Mapa de componentes" abaixo). Cada ⇒ USE … em spec.md é obrigatório: use esse widget/componente e seu mapeamento de props, e use tokens mapeados ((color/primary ⇒ AppColors.primary)) em vez de valores brutos. Para itens marcados como (não no mapa), pesquise no código-fonte o tema e widgets existentes (Flutter ThemeData, AppColors, TextTheme, constantes de espaçamento, lib/widgets; web variáveis CSS, configuração Tailwind, src/components). Use valores brutos apenas quando nenhum token existir, e informe ao usuário quais você adicionou.
  4. Reutilize componentes. Uma camada marcada como component Button {Tipo=Primário} deve usar o widget ou componente Button existente do projeto com props correspondentes. Construa um novo apenas se nenhum existir, torne-o reutilizável e adicione-o ao mapa.
  5. Construa de cima para baixo, seguindo a árvore. Layout automático mapeia para Row/Column/flex (tabelas abaixo). Apenas camadas @x,y (sem layout automático, ou absolute) precisam de Stack/Positioned ou posicionamento absoluto.
  6. Use os arquivos exportados. Coloque assets/*.svg e images/* na pasta de ativos do projeto e faça referência a eles. Nunca redesenhe ícones e nunca substitua por um conjunto de ícones diferente.
  7. Copie o texto exatamente de "…" em spec.md, incluindo maiúsculas/minúsculas, pontuação e strings em árabe/RTL. Texto com várias linhas run precisa de rich text (TextSpan / spans aninhados).
  8. Verifique com o loop de comparação e correção (abaixo). Não declare uma tela como concluída apenas lendo o código; prove com um diff de screenshot.

Loop de comparação e correção

Depois de construir uma tela, compare o resultado real com o Figma e corrija as diferenças:

  1. Execute o build mostrando aquela tela:
    • Web: inicie o servidor de desenvolvimento e abra a rota.
    • Flutter web: flutter run -d web-server --web-port 8080, depois use essa URL.
    • Flutter Android: execute o aplicativo em um emulador/dispositivo e navegue até a tela.
  2. Verifique:
    • Web / Flutter web: figma-lens check --design design/<frame> --url http://localhost:<porta>/<rota> (o viewport é definido para o tamanho do frame e escala automaticamente).
    • Android: figma-lens check --design design/<frame> --adb --crop-top <px barra de status> [--crop-bottom <px barra de navegação>] (barra de status ≈ 24–48 dp × densidade do dispositivo; corte-a para que apenas o conteúdo do aplicativo seja comparado).
  3. Leia design/<frame>/compare/report.md (% de incompatibilidade, as maiores áreas de diferença e os ids das camadas do Figma em cada uma) e veja compare/side-by-side.png (Figma | build | diff, vermelho = diferente).
  4. Corrija de cima para baixo: primeiro diferenças de altura ou espaçamento (elas deslocam tudo abaixo), depois tamanhos, cores, tipografia, raios, sombras. Procure cada id de camada listado em spec.md para os valores exatos.
  5. Execute a verificação novamente. O relatório mostra a pontuação anterior, para que você veja o progresso.
  6. Pare quando a incompatibilidade for ≤ 3% (o anti-aliasing de texto nunca chega a 0) ou quando duas execuções consecutivas pararem de melhorar. Em seguida, relate a pontuação final e tudo o que não pôde ser correspondido, e o porquê (fonte ausente, renderização da plataforma, dados dinâmicos).

Regras: corrija o código real, nunca manipule o diff (sem screenshots ou imagens do design dentro do aplicativo). Use os mesmos dados/texto do design ao verificar (dados simulados, se necessário), caso contrário, diferenças de texto dominam a pontuação.

Mapa de componentes

figma-lens.map.json (raiz do projeto) mapeia componentes e tokens do Figma para o código deste projeto:

{
  "components": {
    "Button": { "flutter": "lib/widgets/app_button.dart#AppButton", "web": "src/components/Button.tsx#Button", "props": { "Label": "label", "Type": "variant" } },
    "Icon/*": "SvgPicture.asset('assets/icons/<nome>.svg')"
  },
  "tokens": { "color/primary": { "flutter": "AppColors.primary", "web": "var(--color-primary)" } }
}
  • Nenhum mapa ainda → execute figma-lens map --design design. Ele adiciona todos os componentes e tokens das exportações com valores vazios ("").
  • Preencha você mesmo: pesquise no código-fonte cada componente (por nome, por aparência, por props) e cada valor de token; escreva caminho#Símbolo (ou uma expressão). Deixe "" apenas quando nada existir ainda. "Prefix/*" corresponde a uma família inteira (ícones).
  • Após editar o mapa, execute figma-lens render design/<frame> para que spec.md mostre as setas ⇒ USE. A ponte também aplica o mapa em cada nova exportação.
  • Quando você criar um novo widget reutilizável para um componente não mapeado, adicione-o ao mapa.

Lendo spec.md

  • As unidades são px de design, que equivalem a px CSS e px lógicos do Flutter. Nunca multiplique pela escala do screenshot.
  • row|column gap G pad t,r,b,l main:X cross:Y é layout automático. pad 16 significa que todos os quatro lados são 16. gap auto significa space-between.
  • w:FILL h:HUG fornece dimensionamento em cada eixo: FIXED (tamanho exato mostrado), HUG (envolver conteúdo) ou FILL (ocupar espaço disponível).
  • @x,y é a posição dentro do pai. absolute significa um filho posicionado absolutamente dentro de um layout automático. pin H/V fornece restrições (MIN = esquerda/topo, MAX = direita/inferior, STRETCH = ambos, CENTER, SCALE).
  • bg A + B lista pinturas de baixo para cima. (nome) é uma variável do Figma e [nome do estilo] é um estilo do Figma.
  • As cores são #RRGGBB ou #RRGGBBAA (alfa por último).
  • O texto usa o formato "caracteres" · Família Estilo (peso) tamanho/alturaLinha cor. alturaLinha é px, % ou auto. ls é espaçamento entre letras em px, ou em % do tamanho da fonte.
  • radius 12 define todos os cantos. radius tl,tr,br,bl define cada canto. smoothing é suavização de cantos estilo iOS; aproxime ou ignore no Flutter, a menos que um pacote squircle esteja em uso.
  • drop-shadow x,y blur B spread S cor, inner-shadow, layer-blur R, background-blur R.
  • → assets/x.svg significa que a camada é um ícone. Use o SVG no tamanho listado.
  • vars{itemSpacing=space/md} significa que a propriedade da camada está vinculada a essa variável. Use o token.

Mapeamento Flutter

FigmaFlutter
column / rowColumn / Row (use spacing: G no Flutter ≥ 3.27, caso contrário SizedBox gaps)
wrap, rowGap RWrap(spacing: G, runSpacing: R)
pad t,r,b,lPadding(padding: EdgeInsets.fromLTRB(l, t, r, b)). Cuidado com a ordem.
main MIN / CENTER / MAX / SPACE_BETWEENMainAxisAlignment.start / center / end / spaceBetween
cross MIN / CENTER / MAX / BASELINECrossAxisAlignment.start / center / end / baseline (baseline precisa de textBaseline)
HUG no eixo principalmainAxisSize: MainAxisSize.min
FILL no eixo principal do paiExpanded (ou Flexible); grow N define flex: N
FILL no eixo transversal do paiCrossAxisAlignment.stretch no pai, ou SizedBox(width: double.infinity)
FIXED w×hSizedBox(width: w, height: h)
@x,y / absoluteStack + Positioned(left: x, top: y); use pin para right/bottom
bg sólidoBoxDecoration(color: Color(0xAARRGGBB)). Mova alfa para a frente: #11223380 → 0x80112233.
gradient-linear de/paraLinearGradient(begin: Alignment(fx*2-1, fy*2-1), end: Alignment(tx*2-1, ty*2-1), colors, stops) usando from/to em spec.json
radiusBorderRadius.circular(r) ou BorderRadius.only(...)
border W cor dentroBorder.all(width: W, color: …) (dentro é o padrão do Flutter; centro/fora precisam de strokeAlign)
drop-shadow x,y blur B spread SBoxShadow(offset: Offset(x, y), blurRadius: B, spreadRadius: S, color: …)
background-blur RClipRRect + BackdropFilter(filter: ImageFilter.blur(sigmaX: R/2, sigmaY: R/2))
opacidadeOpacity (ou alpha de cor para pinturas)
text tamanho/alturaLinhaTextStyle(fontSize: size, height: lineHeight / size). Para %: height: pct/100. Defina leadingDistribution: TextLeadingDistribution.even para corresponder ao centralizamento vertical do Figma.
weight 600FontWeight.w600
ls px / ls %letterSpacing: px / letterSpacing: size * pct / 100
ellipsis maxLines NmaxLines: N, overflow: TextOverflow.ellipsis
align CENTERtextAlign: TextAlign.center. Para telas RTL, use TextAlign.start e EdgeInsetsDirectional.
assets/x.svgSvgPicture.asset('assets/…/x.svg', width:, height:) (flutter_svg)
image fill FILL / FITImage.asset(fit: BoxFit.cover / BoxFit.contain)

Mapeamento Web (CSS / Tailwind / React)

FigmaCSS
column / rowdisplay:flex; flex-direction: column / row; gap: Gpx
wrap, rowGap Rflex-wrap: wrap; column-gap: G; row-gap: R
pad t,r,b,lpadding: t r b l (mesma ordem do CSS)
main MIN / CENTER / MAX / SPACE_BETWEENjustify-content: flex-start / center / flex-end / space-between
cross MIN / CENTER / MAX / BASELINEalign-items: flex-start / center / flex-end / baseline
HUGwidth/height: fit-content (ou apenas auto)
FILL (eixo principal)flex: 1 1 0; min-width: 0
FILL (eixo transversal)align-self: stretch
FIXEDwidth: Wpx; height: Hpx; flex-shrink: 0
@x,y / absolutepai position: relative; filho position:absolute; left:x; top:y (use pin para right/bottom)
cores #RRGGBBAACSS válido como está
gradient-linear Ndeglinear-gradient(Ndeg, c1 p1%, c2 p2%)
drop-shadowbox-shadow: x y B S cor (inner-shadow adiciona inset)
layer-blur / background-blur Rfilter: blur(R/2 px) / backdrop-filter: blur(R/2 px)
textfont: weight size/lineHeight family; letter-spacing (ls % → pct/100 em)
ellipsis maxLines Ndisplay:-webkit-box; -webkit-line-clamp:N; -webkit-box-orient:vertical; overflow:hidden
assets/x.svg<img src> ou SVG inline; mantenha o tamanho exportado

spec.json também contém o CSS gerado pelo próprio Figma (css) para a maioria das camadas. Use-o para verificar cruzadamente os valores CSS; tokens e estrutura de layout ainda vêm da árvore acima.

Regras

  • Valores do spec superam o que você vê na imagem. Quando houver conflito, confie no spec e mencione o conflito.
  • Não arredonde ou "melhore" valores (14 permanece 14, não 16) a menos que o usuário peça normalização para tokens.
  • Camadas ocultas não são exportadas. Não invente estados (hover, erro, vazio) que não estejam na exportação; peça esses frames.
  • Sinalize fontes ausentes. Se a família de fontes não estiver incluída no projeto, informe e diga ao usuário o que adicionar (fontes pubspec / @font-face).
  • Para vários breakpoints ou estados, peça ao usuário para exportar cada frame. Cada um se torna sua própria pasta.

Habilidades Relacionadas