Communitygithub.com

pafelab/stretchy-morph-ui

Transforme a interface web do usuário em uma UI que se deforma elasticamente, onde transições se comprimem, esticam, ultrapassam o alvo e se acomodam usando molas em vez de curvas de easing.

O que é stretchy-morph-ui?

Esta skill transforma interfaces de usuário estáticas em experiências vivas e animadas, onde cada transição de estado se deforma como um material elástico. Ao ser invocada, a skill primeiro audita o código existente do usuário para identificar componentes que podem se beneficiar desse comportamento (abas, botões, modais, dropdowns, carrosséis, etc.), lista as possibilidades e pede confirmação antes de qualquer edição. Ela inclui um motor de molas, 24 componentes de referência funcionais, um scanner de código, um verificador de navegador e um método para inventar novos componentes elásticos. Suporta plataformas como Claude Code e Cursor, e é ideal sempre que o usuário desejar micro-interações animadas, com sensação de mola, elástico, saltitante ou pegajoso.

Funciona com✓Claude Code~Codex CLI~Cursor✓Antigravity
npx skills add https://github.com/pafelab/stretchy-morph-ui/tree/HEAD

Perguntar na sua IA favorita

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

Documentação

Stretchy morph UI

Esta skill produz interfaces onde cada mudança de estado morfoseia: um indicador de aba se estica como uma minhoca a caminho da próxima aba, um botão se comprime em um círculo de carregamento e incha de volta, uma imagem de produto se levanta do cartão, encolhe em um chip e cai no carrinho. Foi destilada da construção de um showcase de 24 componentes (em assets/showcase.html) e dos bugs e correções de design encontrados ao longo do caminho.

A aparência vem de uma ideia: o alongamento é causado por algo. Um elemento se deforma porque suas partes discordam (uma borda chega antes da outra), porque está se movendo rapidamente (alonga-se ao longo de seu caminho), porque está sendo comprimido (incha no outro sentido para manter seu volume), ou porque acabou de ser atingido (oscila). Uma oscilação aleatória em loop parece barata; alongamento com causa parece material.

Etapa 0, sempre: audite o código do usuário e confirme

Antes de construir ou editar qualquer coisa, descubra o que na própria interface do usuário pode se tornar elástico e deixe-o escolher. Detalhes, critérios de julgamento e modelos de mensagem estão em references/audit.md; a versão resumida:

  1. Encontre o código: código colado, arquivos anexados (no claude.ai, liste /mnt/user-data/uploads), o diretório de trabalho ou repositório, um link de artefato (leia com a ferramenta de artefato), ou uma fonte que o usuário indicar. Se não houver, diga o que procurou e ofereça dois caminhos: compartilhe o código ou construa algo novo do zero.
  2. Escaneie-o: python scripts/audit_ui.py <caminhos> relata a pilha, movimento existente, manipulação ausente de movimento reduzido e candidatos por categoria de UI com arquivo:linha, cada um mapeado para um componente de showcase e técnica.
  3. Leia cada acerto em contexto e mantenha apenas candidatos reais. Para cada um, anote onde está, o que acontece agora, a frase de transformação que se tornaria, esforço (pequeno, médio, grande) e qualquer risco (marcação de biblioteca de componentes, biblioteca de animação existente, um controle nativo cujo seletor móvel seria perdido, listas muito longas).
  4. Priorize por visibilidade × frequência × adequação, agrupe duplicatas (todos os botões que usam um Button compartilhado são um item), limite a lista a cerca de dez, e liste qualquer coisa contra a qual você aconselhe com o motivo.
  5. Peça confirmação na linguagem do usuário: as propostas numeradas, depois uma pergunta convidando-o a escolher números, pegar todas as recomendadas ou digitar partes extras que ele deseja que sejam elásticas e que não estão na lista. Use uma ferramenta de escolha tocável se o ambiente tiver uma, caso contrário texto simples. Termine o turno aí; não faça edições antes da resposta.
  6. Construa o que eles escolheram mais o que eles adicionaram, depois siga o Fluxo de Trabalho abaixo e relate por item.

Se o usuário já nomeou as partes que deseja, ainda audite: coloque as partes dele em primeiro lugar, ofereça o restante como opcional e mantenha a pergunta curta.

Arquivos

Todos os caminhos são relativos à pasta desta skill (a pasta que contém este SKILL.md), não ao projeto do usuário. Resolva-os em relação à pasta da skill quando você os ler ou executar.

CaminhoO que éQuando abrir
assets/stretchy-core.jsO motor de molas mais ajudantes (pares de borda, indicador segmentado, escala de volume, bordas SVG que incham, reordenação FLIP, objetos lançados)Cole em cada página que você construir. Leia uma vez para conhecer os ajudantes.
assets/starter.htmlEsqueleto da página: tokens claro/escuro, fonte variável com suporte a tailandês, tratamento de movimento reduzido, o core embutido, um componente de exemploComece uma nova página a partir dele
assets/showcase.htmlTodos os 24 componentes funcionais da construção original. Cada seção JS começa com um banner como /* ---------- tabs ---------- */Quando uma solicitação corresponder a um componente do catálogo, grep -n "/\* ---------- " assets/showcase.html e leia apenas aquela seção mais seu CSS
references/audit.mdComo encontrar, escanear, julgar e priorizar o código do usuário, e os modelos de mensagem de confirmação (tailandês e inglês)Na Etapa 0, sempre
references/techniques.mdAs 11 técnicas de alongamento em profundidade, com código e números de ajusteAntes de construir algo que você não construiu antes
references/components.mdCatálogo: receita de cada componente, valores de mola e pegadinhasQuando a solicitação nomear ou se assemelhar a um componente do catálogo
references/new-components.mdComo projetar uma versão elástica de qualquer componente, mais 14 designs trabalhados não presentes no showcaseSempre que a solicitação estiver fora do catálogo
scripts/audit_ui.pyScanner para o código do usuário: pilha, movimento existente e candidatos elásticos com arquivo:linhaNa Etapa 0, sempre
scripts/check_page.pyVerificação headless do navegador: erros JS, transbordamento lateral no celular e desktop, elementos invisíveis roubando cliques e folhas de contato de quadros de animaçãoApós cada construção, antes de entregar qualquer coisa

Se uma skill de design visual estiver disponível (por exemplo frontend-design ou ui-ux-pro-max), leia-a também. Essa skill decide como a página se parece (paleta, tipografia, layout); esta decide como ela se move. O polimento do movimento não pode resgatar uma página de aparência genérica.

Fluxo de trabalho (após o usuário confirmar)

  1. Escreva a frase de transformação para cada componente. "Quando gatilho, forma A se torna forma B, e ela se alonga porque causa." Exemplo: "Quando uma aba é clicada, o indicador se move para ela, e ele se alonga porque sua borda dianteira é mais rígida que a traseira." Se você não conseguir preencher a causa, escolha uma da tabela abaixo. Esta frase é o design; todo o resto é implementação.
  2. Escolha a(s) técnica(s) da tabela. A maioria dos componentes usa um alongamento primário mais uma pequena oscilação de feedback.
  3. Defina estados de repouso como números: larguras, alturas, raios, posições, progresso de 0 a 1. Molas animam números e você os escreve em style no onUpdate. Transições CSS lidam apenas com cor e opacidade (e crossfades curtos de conteúdo).
  4. Planeje o conteúdo. Texto e ícones não devem refluir ou se achatar enquanto o contêiner se transforma. Dê a cada estado de conteúdo sua própria camada em seu tamanho final, ancorada (geralmente centralizada), e faça crossfade: saída rápida (≈150 ms), entrada após um atraso de ≈100–150 ms com uma ligeira escala ou desfoque. O overflow:hidden do contêiner revela o conteúdo à medida que ele cresce.
  5. Construa a partir de assets/starter.html com o core embutido. Escreva estilos diretamente em callbacks de molas; nunca acione uma re-renderização de framework por quadro.
  6. Passagem de acessibilidade e interrupção (lista de verificação abaixo).
  7. Teste e observe. Execute scripts/check_page.py, depois capture folhas de contato de quadros das interações importantes e realmente olhe para elas. A animação de adicionar ao carrinho na construção original "funcionou" mas parecia barata até os quadros serem inspecionados; as correções estão em "Fazendo parecer bom".

De onde vem o alongamento

SituaçãoTécnica (detalhes em references/techniques.md)Visto em
Algo se move entre posiçõesPar de bordas: duas molas para bordas dianteira e traseira, dianteira rígida, trocada por direçãoAbas, pontos de carrossel, interruptores, chips de escolha, ponto de rádio, stepper, destaque de dropdown, cápsula de avaliação, navegação de barra lateral
Um contêiner muda de tamanho ou formaEixos divididos: molas separadas para largura, altura, raio com rigidez diferente, de modo que um eixo lideraIlha dinâmica, FAB para formulário, modal a partir de botão, dropdown, botão de adicionar ao carrinho
Algo fica mais estreito ou mais largo rapidamentePreservação de volume: escalar o outro eixo pela velocidade, scaleY = clamp(1 − v/k)Botão de envio, campo de pesquisa, largura de dropdown
Algo viaja rápidoAlongamento por velocidade: alongar na direção do movimento, afinar transversalmentePolegar de controle deslizante, item de carrinho lançado, cartões de carrossel (inclinação), dica de ferramenta
Uma superfície grande se moveBorda que incha: desenhar a superfície como um caminho SVG cujo ponto de controle de borda é deslocado por −velocidadeBarra lateral, folha inferior
Uma parte depende de uma parte móvelSeguidor atrasado: uma mola mais suave persegue a principal; use a lacuna para inclinação ou deslocamentoBolha de valor de controle deslizante, texto interno de acordeão
Feedback para um toque ou chegadaChute: adicionar velocidade a uma mola em repouso em 0, ela oscila e se acomodaCaixa de seleção, chips, carrinho, estrelas, emblema, tremor de limite de quantidade
Blobs se juntam ou se separamFiltro pegajoso: desfoque mais limite alfa, fonte nítida composta em cimaMenu pegajoso
Um elemento se torna um elemento diferenteTransformação de contêiner: comece no retângulo do gatilho, vá para o retângulo alvo com mola, crossfade de conteúdoModal, FAB, lançamento de carrinho
A mudança precisa de uma pausa no meioTransformação sequenciada através de uma forma intermediária que carrega significado (spinner, verificação)Botão de envio, botão de adicionar ao carrinho
Arrastar além de um limite, ou uma lista reordenaElástico (dividir overscroll por ≈3) e FLIP com molas que mantêm velocidadeCarrossel, folha, lista de produtos ordenada

O motor em um parágrafo

Spring é um oscilador harmônico amortecido integrado com Euler semi-implícito em 8 subpassos por quadro (delta do quadro limitado a 1/30 s para que uma aba em segundo plano não o exploda). to(alvo) redireciona sem redefinir a velocidade, que é o que torna cliques rápidos contínuos em vez de reiniciar. set(x) pula sem animação, drag(x, v) segue um ponteiro enquanto registra a velocidade, kick(v) injeta um impulso. O amortecimento é multiplicado por um fator global bounce a cada tick, então um controle no nível da página (suave 1.8, saltitante 1, elástico 0.5) reajusta cada componente ao vivo. Sob prefers-reduced-motion: reduce, to() vai direto ao alvo e dispara onRest imediatamente, para que a lógica que espera uma animação ainda seja executada.

Razão de amortecimento ζ = c / (2√k). Mudanças de estado da UI parecem corretas em torno de ζ 0.6–0.8; feedback lúdico em 0.3–0.5; acima de 1 nada ultrapassa. As predefinições usadas no showcase:

FunçãokcNotas
Borda dianteira de um par de bordas420–52030–34Chega primeiro
Borda traseira140–17017–19Atrasa, o que cria o alongamento
Largura do contêiner (transformação)240–32018–24
Altura do contêiner (transformação)150–17015–17Mais lenta que a largura, então a forma se alonga lateralmente primeiro
Seguidor de ponteiro (controle deslizante)65042Apertado, mas ainda tem velocidade para ler
Seguidor atrasado (bolha)15011Propositalmente solto
Feedback de chute380–42012–16Chute com 6–10
Altura com ultrapassagem visível (acordeão)21014

Regras práticas

  • Limite toda deformação. Controles: preservação de volume dentro de ±7–15 %. Coisas pequenas e rápidas (um chip lançado, um polegar de controle deslizante): até 35–70 % de alongamento. Sempre limite os tamanhos a um mínimo positivo, já que uma mola subamortecida pode ultrapassar abaixo de zero.
  • Troque a rigidez por direção. Em um par de bordas, qualquer borda que enfrente a direção do movimento recebe a mola rígida. Sem a troca, o indicador se alonga corretamente em um sentido e comprime no outro.
  • Tempo oposto no retorno. Se a largura lidera a altura ao abrir, deixe a altura liderar a largura ao fechar. A forma então refaz um caminho diferente, que é lido como elástico em vez de um rebobinado.
  • Molas para mudanças de estado, curvas baseadas em tempo para caminhos cuja forma importa. Um objeto lançado precisa de um arco previsível (Bézier quadrática, progresso ease-in-out, cerca de 800 ms). Molas x/y independentes dão caminhos errantes. Derive o alongamento da velocidade quadro a quadro de qualquer forma.
  • Mantenha o conteúdo reto. Para alongar algo em uma direção arbitrária sem girar sua imagem ou texto, use rotate(a) scale(1+s, 1−s·0.45) rotate(−a).
  • Um movimento ousado por componente. O resto do componente permanece quieto: uma mudança de cor, um fade curto.
  • Calmo quando ocioso. Nada oscila por conta própria. No máximo um momento orquestrado no carregamento da página (o showcase abre a ilha uma vez após 900 ms).

Fazendo parecer bom (lições da construção)

A primeira versão de adicionar ao carrinho voou uma bola colorida lisa ao longo de duas molas independentes, encolheu o botão em uma oval violeta vazia e esmagou o carrinho. O usuário disse que não era bonito. O que consertou generaliza:

  • Mova a coisa real. Clone a imagem do produto, levante-a ligeiramente com uma sombra, depois encolha-a em um chip redondo que ainda mostra a imagem enquanto voa. Pontos abstratos parecem saída de depuração.
  • Formas intermediárias devem carregar significado. Um botão encolhido é uma bolha vazia a menos que mostre algo: um spinner, uma marca de verificação que se desenha, uma contagem. O botão de adicionar agora se torna um círculo verde com uma marca, depois cresce para o stepper − n +.
  • Volume sutil em controles. Um inchaço vertical de ±18 % em um botão parecia um ovo em forma de pílula. ±7 % parece material macio.
  • A chegada precisa de um receptor. O ícone do carrinho mergulha e inclina, um anel pulsa para fora, o emblema aparece. Algo deve visivelmente pegar o que foi lançado.
  • Não corte marcas de status. Um emblema dentro de uma pílula com overflow:hidden em transformação é cortado; coloque-o em um wrapper fora do clipe.
  • Não repita informações. A pílula do carrinho mostrava "3 ชิ้น 195 บาท" ao lado de um emblema dizendo 3. Agora mostra apenas o total.
  • Desenhe ilustrações em uma proporção fixa. Formas CSS posicionadas por porcentagem dentro de um bloco se alongam quando o bloco se alarga. Use um SVG inline com um viewBox, centralizado no bloco.

Lista de verificação de acessibilidade e robustez

  • Respeite movimento reduzido (o core o faz; certifique-se de que keyframes CSS e transições também sejam cortados em uma media query prefers-reduced-motion).
  • Use button, input, role="switch", role="tab", role="slider" reais, etc. com o estado aria-* correto, atualizado na mesma chamada que inicia a animação.
  • Conteúdo que está oculto por uma transformação recebe inert (e não deve interceptar cliques: dê a camadas invisíveis pointer-events:none, depois ligue-o novamente com o estado visível).
  • Mova o foco deliberadamente quando o controle focado desaparecer em uma transformação: para o controle de substituição, de volta ao gatilho após um diálogo fechar, e apenas depois que o elemento estiver visível novamente (um elemento visibility:hidden não pode receber foco).
  • Apenas uma mola global bounce por página. Não aninhe; um bounce aninhado distorce as proporções de amortecimento.
  • A mola de um componente vive até que sua página seja descartada. Se o componente for removido do DOM, pare a mola ou ela continuará a definir estilos em um nó removido.

Habilidades Relacionadas