A Anthropic lançou recentemente uma nova interação de UI generativa no Claude. Ela ajuda a introduzir conceitos e informações visualmente dentro do fluxo do chat, tornando tudo muito mais fácil de entender do que texto simples. !Image Eu estava procurando soluções semelhantes e, quando o Claude lançou a deles, senti que precisava acelerar meu trabalho. Ao mesmo tempo, pude fazer engenharia reversa da abordagem deles como referência. Depois de dois dias instruindo intensamente o Codex e o Claude, eu realmente consegui! !https://pbs.twimg.com/amplify_video_thumb/2033112086713364480/img/EUmHCjsTK7tfnToZ.jpg Esse recurso permite que a IA desenhe gráficos interativos diretamente no chat com saída em streaming, renderizando enquanto gera. Antes, ao pedir para a IA escrever uma página web, você precisava esperar todo o código ser gerado para renderizar, o que demorava uma eternidade. Agora é diferente. Você pode ver os gráficos sendo desenhados traço por traço no canvas, com os nós SVG aparecendo um após o outro. O próprio processo de geração é impressionante, e é interativo imediatamente após a conclusão. Experimente diretamente no meu produto Agent, o Code Pilot: https://github.com/op7418/CodePilot Neste post, vou apresentar seu uso, o processo de implementação específico e alguns cuidados. ## Quais são alguns casos de uso divertidos? Análise de Dados: Finalmente, os números fazem sentido Por exemplo, peça para desenhar um gráfico para "Estimativa de custo diário do conflito EUA-Irã". Antes, a IA te dava um monte de texto onde as relações numéricas eram difíceis de ver. Agora, ela gera um gráfico diretamente, tornando o valor de cada parte claro de imediato. Texto e gráficos são gerados juntos, explicando onde for necessário e desenhando onde for necessário. !Image Ferramentas Pequenas: Crie uma calculadora interativa ou algo similar Peça para fazer uma calculadora de juros compostos. Arraste controles deslizantes para mudar o valor inicial ou os anos de investimento, e os gráficos e números abaixo são atualizados em tempo real. Isso não é uma imagem estática; é uma ferramenta verdadeiramente interativa. Cálculos de empréstimos, conversões de unidades e coisas semelhantes podem ser feitas. !Image Diagramas de Arquitetura: O favorito dos programadores Você pode pedir para ajudar a desenhar a arquitetura de um projeto ou visualizar um plano de implementação. Por exemplo, aqui pedi para desenhar o fluxo completo da API até a autenticação JWT. Comparações de recursos, fluxogramas e estruturas hierárquicas são todos gráficos, tornando a arquitetura muito mais rápida de entender do que ler descrições em texto. !Image Analisar Dados Online Outra forma de usar é jogar um link de repositório do GitHub nele; ele vai rastrear os dados e fazer uma análise visual. Por exemplo, enviei o endereço do meu próprio projeto, CodePilot, para análise. Estrelas, forks, stack de tecnologia, design de arquitetura e módulos principais são todos desenhados em gráficos. Você pode ver o panorama completo do projeto de relance, o que é muito melhor do que ler um texto longo. !Image Explicações Interativas e Aprofundadas A parte mais forte é sua integração estreita com o modelo; não é apenas uma saída única. Você pode interagir com os diagramas gerados e pedir explicações mais detalhadas. Por exemplo, aqui pedi para explicar a relação entre monções e correntes oceânicas. !Image Se quisermos saber mais, podemos clicar no botão do mecanismo de corrente oceânica. Ele vai enviar automaticamente um comando para o modelo atual continuar gerando um diagrama do mecanismo de corrente oceânica. !Image Claro, podemos realizar interações mais complexas, como visualizar fórmulas comuns de física e matemática. Isso é muito útil para estudantes; cada parâmetro pode ser controlado via controles deslizantes e entradas, e a animação muda imediatamente. !Image Suporte para Modelos Chineses Uma vez implementado no CodePilot, não é só para o Claude. Kimi K2.5, Minimax M2.5 e os modelos nativos da Anthropic funcionam bem. Acho que os gráficos desenhados pelo K2.5 são ainda mais bonitos que o Sonnet 3.5, e a análise de arquitetura é muito detalhada. Se você usar esse recurso, recomendo testar o K2.5 primeiro. Ok, é basicamente isso para as demonstrações do modelo. Se você não se importa com como foi implementado, pode simplesmente instalar o CodePilot e se divertir. ## Como foi implementado? !Image Como o Claude faz O Claude.ai oficialmente usa o mecanismo tool_use. O modelo chama uma ferramenta dedicada para gerar conteúdo de widget estruturado, e o frontend analisa os parâmetros de entrada da chamada da ferramenta para renderizar. Essa solução funciona bem na própria arquitetura do Claude.ai. Mas não funciona para o CodePilot por três razões: Primeiro, limitações do SDK. O CodePilot usa o modo predefinido claude_code do SDK do Claude Agent, que não permite registrar ferramentas personalizadas. O SDK expõe um fluxo de texto delta, então não pode ser estendido no nível da ferramenta. Segundo, a experiência de streaming. Os resultados de tool_use precisam esperar o input_json_delta terminar antes de renderizar, e não suporta renderização HTML incremental. Com cercas de código, o HTML chega com o fluxo de texto, permitindo renderizar enquanto gera. Terceiro, isolamento de renderização. O Claude.ai usa Shadow DOM para isolamento. Nós escolhemos um iframe de sandbox. O isolamento por iframe é mais completo—um ambiente de execução JS completamente independente, CSP controla precisamente o carregamento de recursos, e não há vazamento de estilo ou escape de script. Como nós fizemos Gatilho: Cercas de Código O modelo gera uma cerca de código Markdown especial para acionar a renderização: ``show-widget {"title":"training_flow","widget_code":"<svg width=\"100%\" viewBox=\"0 0 680 400\">...</svg>"} ` Esse formato reutiliza os modos de cerca de código existentes do CodePilot (image-gen-request, batch-plan, etc.), que a cadeia do analisador do frontend suporta naturalmente.  **Renderização: Iframe de Sandbox** Cada widget é renderizado em um iframe com sandbox="allow-scripts". O srcdoc do iframe é uma página receptora cuidadosamente construída. A política CSP só permite scripts externos de 4 domínios CDN, e connect-src 'none' proíbe todas as requisições de rede. As atualizações de conteúdo são recebidas via postMessage. Durante a fase de pré-visualização em streaming, widget:update é enviado sem executar scripts. A renderização final envia widget:finalize, que executa scripts. Um ResizeObserver monitora mudanças na altura do conteúdo e as reporta para a página pai via postMessage. Todos os cliques em <a> são interceptados e encaminhados para a página pai para abrir em uma nova janela. A sincronização de tema depende do monitoramento de mudanças de classe na página pai para alternar entre modos escuro/claro em tempo real.  **Ponte de Variáveis CSS** Isso é chave para fazer o widget se misturar visualmente com o aplicativo. O CodePilot usa variáveis CSS no espaço de cor OKLCH. As diretrizes de design de widget da Anthropic usam nomes de variáveis padrão como --color-background-primary. A camada de ponte injeta os valores das variáveis do CodePilot no :root do iframe quando ele é inicializado. O CSS escrito pelo modelo de acordo com as diretrizes pode usar diretamente as cores do tema atual. Ao alternar para o modo escuro, a página pai detecta a mudança de classe, recalcula os valores das variáveis e os envia para o iframe.  **Renderização em Streaming** Esta é a parte mais complexa de toda a implementação. O modelo gera token por token. A qualquer momento, o código do widget recebido pode ser um JSON incompleto, HTML incompleto ou uma tag <script> incompleta. O fluxo de processamento é o seguinte: A regex corresponde a `show-widget para distinguir entre estados "não fechado" e "fechado". Localize manualmente o conteúdo após "widget_code":" e desescape caractere por caractere. JSON.parse não pode ser usado porque o JSON não está terminado. Quando uma tag <script> não fechada é detectada, trunque antes do <script para evitar exibir código JavaScript como texto visível. Um debounce de 120ms impede que o iframe seja atualizado com muita frequência. O conteúdo em streaming remove todos os scripts e manipuladores de eventos; a interação não é necessária durante a fase de pré-visualização.  **Polindo a Experiência: Detalhes que não deveriam ser notados** Do ponto de vista de código ou implementação, não é tão complexo; a complexidade está em polir a experiência. Há muitos lugares que podem afetar a experiência, e os usuários precisam não notar esses detalhes e o processo de geração. Isso requer lidar com cada estágio de forma diferente: 1. Detalhes que não parecem streaming 2. Conteúdo que não deveria aparecer  **Desaparecimento de Texto** O modelo primeiro gera um texto introdutório ("Deixe-me explicar visualmente..."), então inicia a cerca do widget. Assim que a cerca aparece, o texto anterior desaparece de repente e só retorna após o widget terminar de renderizar. A razão é que parseAllShowWidgets() retorna um array vazio para texto simples. Quando a cerca aparece mas não está fechada, o texto antes da cerca é passado para esta função e é descartado. Correção: Quando o texto antes da cerca não contém uma cerca de widget completa, renderize-o diretamente como <MessageResponse>, ignorando a função de análise. **Saltos de Altura** No momento em que o widget termina de renderizar, toda a área do chat treme. A altura inicial do iframe é 0px. Quando o conteúdo reporta sua altura real pela primeira vez, pode ser 400px+, e uma transição CSS faz essa mudança acontecer ao longo de 300ms, resultando em um salto perceptível. Correção: Desabilite temporariamente as transições CSS durante o primeiro relatório de altura para que a altura se ajuste instantaneamente. Ajustes de altura subsequentes usam transições suaves. **Cintilação na Finalização** Quando o widget muda da pré-visualização em streaming para a renderização final, o conteúdo pisca. O iframe receptor substitui todo o DOM com root.innerHTML = html durante a finalização. Mesmo que o conteúdo novo e antigo sejam idênticos (widget SVG puro), o navegador aciona um quadro de repintura. Correção: Durante a finalização, primeiro analise o novo HTML em um contêiner temporário e separe os elementos de script. Compare o HTML visual (sem scripts) com o DOM atual—se forem iguais, pule a substituição innerHTML e apenas anexe os scripts para execução. Widgets SVG puros alcançam finalização sem repintura. **Salto de Rolagem** O chat está rolando automaticamente para o fundo, então de repente volta várias centenas de pixels e volta novamente. Quando o streaming termina, o componente StreamingMessage é desmontado e o componente MessageItem é montado. Estes são dois componentes React completamente diferentes, e o WidgetRenderer interno é destruído e reconstruído. A altura do iframe da nova instância começa em 0, fazendo com que a altura da área de conteúdo caia drasticamente, o que aciona um ajuste de rolagem em use-stick-to-bottom. Correção: Cache de altura em nível de módulo. Sempre que um widget reporta sua altura, ela é escrita em um cache usando os primeiros 200 caracteres do widgetCode como chave. A nova instância de WidgetRenderer lê a altura do cache durante a inicialização useState, então o iframe começa a renderizar na altura correta, eliminando a transição 0→real. **Vazamento de Código de Script** Quando um widget com Chart.js carrega, um grande bloco de código JavaScript é exibido na parte inferior. As tags <script> geradas pelo modelo chegam caractere por caractere. Quando a tag de abertura chega mas a tag de fechamento não, sanitizeForStreaming remove a tag de abertura, mas o código JavaScript dentro se torna um nó de texto simples renderizado como conteúdo visível. Correção: Após extrair o código parcial em StreamingMessage, verifique se o último <script tem um </script> correspondente. Se não, trunque na posição <script. As diretrizes do widget especificam que os scripts vão no final, então o truncamento não afeta o conteúdo visual. Durante o truncamento, uma máscara shimmer é mostrada, e a barra de status exibe "Adicionando animações interativas à visualização." **Condição de Corrida do Iframe Ready** Em casos raros, o widget não renderiza, permanecendo com altura 0px. WidgetRenderer registra um ouvinte de evento de mensagem via useEffect. No entanto, o script receptor do iframe envia widget:ready assim que carrega. Se o iframe carregar mais rápido que o efeito React executar, widget:ready é enviado antes do ouvinte ser registrado, e iframeReady nunca se torna verdadeiro. Correção: Adicione um callback onLoad ao elemento iframe como fallback. Quando onLoad é acionado, o script receptor deve ter terminado de executar, fornecendo um sinal de prontidão confiável. **Estabilidade da Árvore de Componentes React** O widget pisca no momento em que a cerca fecha. Dois problemas se sobrepõem: o widget parcial em streaming não tem chave React, e após fechar, ele recebe key="w-0". A mudança de chave causa uma remontagem. Além disso, a sobreposição shimmer foi implementada com um <div> envolvente, que mudou a estrutura da árvore de componentes e causou outra remontagem. Correção: Atribua uma chave estável ao widget parcial (w-N, onde N é a posição esperada no array final de segmentos), consistente com a chave após o fechamento. Mova a sobreposição shimmer para dentro do WidgetRenderer, controlada via uma prop showOverlay. A árvore de componentes permanece <WidgetRenderer key="w-N"> durante todo o processo. ## **Considerações Finais** Para todo o sistema de UI generativa, a parte difícil não é "fazer um pedaço de HTML rodar em um iframe". Isso é simples. A complexidade real está em manter esse iframe visualmente estável durante transições de estado como streaming, mudanças de ciclo de vida de componentes e alterações de tema. Cada "flash", "salto" ou "desaparecimento" requer entender a reconciliação do React, o pipeline de renderização do navegador e o tempo do postMessage`. O efeito final é que os usuários veem gráficos e diagramas naturalmente intercalados nas respostas do modelo, como se sempre estivessem destinados a estar lá. É isso por hoje. Se você achou isso útil, por favor, dê um like ou compartilhe com amigos que possam precisar.
Eu repliquei a nova interação de UI generativa do Claude!
- Visualizações
- 265K
- Curtidas
- 446
- Reposts
- 63
- Comentários
- 34
- Salvos
- 815
TL;DR
Este artigo detalha a replicação da UI generativa do Claude no Code Pilot. Ele aborda obstáculos técnicos como renderização em sandbox iframe, análise de JSON via streaming e refinamentos de UX para garantir uma experiência fluida e sem oscilações.
Você está lendo a tradução em PORTUGUÊS





