Panda CSS 2.0 substitui seu compilador baseado em TypeScript por um mecanismo escrito em Rust sobre Oxc: você mantém a mesma API css(), mas a migração é manual. A versão 2.0.0 saiu em 29 de setembro de 2026 e hoje npm serve a 2.1.2. Não há codemod, e você precisa de Node 22 e um projeto ESM antes de começar.
O que é Panda CSS e o que tem a ver com Chakra UI?
Panda CSS é um framework de CSS-in-JS zero-runtime e com tipagem estrita, pensado para construir sistemas de design. É desenvolvido pelo time do Chakra UI, com Segun Adebayo à frente; o repositório fica em chakra-ui/panda, tem 6.2k estrelas no GitHub e usa licença MIT. Você escreve estilos como objetos tipados com css(), recipes, patterns e props de estilo em JSX. No tempo de build, Panda os extrai e gera CSS atômico, então o navegador recebe uma folha de estilos normal e não um runtime de estilos.
Os tokens, as condições e as recipes ficam em panda.config.ts, e a partir dessa configuração Panda gera uma pasta styled-system com helpers tipados. Se você vem do Chakra UI, a documentação oficial inclui um guia de migração específico, junto com guias do Tailwind CSS, StyleX, Emotion, Styled Components e vanilla-extract.
O que muda no Panda CSS 2.0?
Muda o mecanismo; a forma de escrever estilos não.
Na v1, a extração passava por ts-morph, um wrapper do compilador completo de TypeScript, e um interpretador de JavaScript avaliava os valores constantes. Na v2, Oxc analisa cada arquivo uma única vez, e esse único parse é compartilhado entre imports, chamadas a css(), JSX e resolução de identificadores. Os arquivos que nunca importam Panda, incluindo a maior parte de node_modules, são pulados completamente. O CSS é emitido nativamente em Rust em vez de passar por PostCSS.
O mecanismo é distribuído de duas formas:
| Binding | Pacote | Onde roda |
|---|---|---|
| Nativo (NAPI) | @pandacss/compiler |
CLI, Vite, PostCSS |
| WebAssembly | @pandacss/compiler-wasm (~490 KB gzip) |
Navegador, playground |
Ambos envolvem os mesmos crates de Rust, então um build em Node e um no navegador produzem exatamente o mesmo CSS.
Quanto mais rápido é Panda CSS 2.0?
Estas cifras são benchmarks do próprio time da Chakra, medidos sobre seus fixtures, que chegam até um projeto sintético de mil arquivos:
| Medição | v1 | v2 |
|---|---|---|
| Extração a frio | — | 15–37× mais rápida |
| Parse a frio, 100 arquivos | 187 ms | 7,5 ms |
| Re-parse em modo watch, por arquivo | ~650 µs | menos de 2 µs |
| Passagem de parse, projeto Next.js | 762 ms | 31 ms |
staticCss, config de ~29.000 regras |
25,7 s | ~0,3 s |
| Instanciações de tipos gerados | ~2.600 | ~20 |
O time também reporta entre 21 e 25 por cento menos de memória em tsc, entre 40 e 60 por cento menos de tempo de type-check, e css() e recipes com memoização, até cerca de 4 vezes mais rápidos para os estilos que se resolvem em runtime.
O que resolve o novo mecanismo que a v1 não conseguia?
A v2 segue os imports. Na v1, um valor de estilo importado de outro arquivo não produzia CSS. A v2 lê imports com nome, re-exports, barrels com export * e alias de rotas de tsconfig, e gera a regra. Também resolve em build membros de objetos, aritmética em template literals e os dois ramos de um ternário. Se você adicionou entradas em staticCss só porque a v1 não via um import, já pode removê-las.
Há duas formas de import que ainda não são seguidas: os imports padrão e os de namespace (import * as theme). Use imports com nome.
Como migrar para Panda CSS 2.0?
Seu panda.config.ts se mantém, e os binários panda e pandacss conservam seus nomes. O resto é uma lista de mudanças que convém fazer nesta ordem. Os detalhes seguem o guia oficial Upgrading to v2 tal como estava em 8 de outubro de 2026.
1. Vá para Node 22 e ESM
A v2 é apenas ESM e não tem build de CommonJS. Defina "type": "module" em package.json (ou use .mjs) e converta qualquer require():
// Antes
const { defineConfig } = require('@pandacss/dev')
// Depois
import { defineConfig } from '@pandacss/dev'
Deixe postcss.config.cjs como está: continua em CommonJS de propósito, porque Next.js ainda espera esse arquivo em CJS.
2. Atualize todos os pacotes @pandacss/* juntos
npm install @pandacss/dev@latest
Todos os pacotes @pandacss/* são publicados com uma única versão: não misture pacotes da v1 com a v2. Atualize também para a mesma versão as integrações que você usa: @pandacss/postcss, @pandacss/vite, @pandacss/webpack, @pandacss/rollup ou @pandacss/bun.
3. Faça um build limpo
panda build --clean # codegen + cssgen em uma passada
panda codegen --clean # ou, se você só executa codegen
Você só precisa de --clean uma vez, mas não pule. A v2 não deleta os arquivos que já não gera, e a v1 escrevia .mjs onde a v2 escreve .js. Vite resolve index.mjs antes de index.js, então um arquivo sobrante da v1 pode ganhar do novo sem que você perceba.
4. Execute panda doctor
panda doctor substitui inspect, validate e info com um único check de saúde do projeto. Adicione --json se vai usar em scripts. É o mais parecido com uma ferramenta automática de migração que a v2 traz.
5. Corrija a configuração, começando pelas mudanças silenciosas
Duas dessas mudanças não produzem nenhum erro:
-
Os presets não se adicionam sozinhos. A v1 injetava
@pandacss/preset-baseautomaticamente; a v2 não. Se sua configuração lista apenas seus próprios presets, você perde as utilidades e condições base. O build continua funcionando, com avisosunknown_condition. Se faltam componentes comoFlex, é por isso.export default defineConfig({ presets: ['@pandacss/preset-base', '@acme/preset'] }) -
theme.containerSizesagora étheme.containers. A chave antiga é ignorada sem aviso, e todas as condições de container@name/sizedeixam de funcionar.
O resto das mudanças:
- Os hooks se moveram para
plugins. Cada hook vive agora em um plugin com nome, com umfiltere umhandler.cssgen:donepassou a ser somente leitura: você pode ler o CSS, mas não reescrevê-lo. Se você usava para remover tokens ou keyframes sem uso, mude paraoptimize.removeUnusedTokenseoptimize.removeUnusedKeyframes. createStyleContextse dividiu em dois:createSlotRecipeContextpara slot recipes (sva) ecreateRecipeContextpara config recipes (cva).- A sintaxe de template literal foi eliminada. Remova a opção
syntaxe reescrevacss`color: red;`comocss({ color: 'red' }). definePartsnão existe mais. Escreva você o seletor[data-part="…"]ou usedefineSlotRecipe.- Nove opções de configuração foram eliminadas:
studio,eject,emitTokensOnly,gitignore,clean,watch,poll,lightningcssebrowserslist. - Os imports de tipos mudaram.
@pandacss/devagora exporta apenasConfig,PreseteUserConfig; o resto vem de@pandacss/types. - Você não precisa mais de
@pandacss/plugin-vuenem@pandacss/plugin-svelte. O compilador lê arquivos.vue,.sveltee.astrodiretamente.
Panda CSS 2.0 quebra seu CI?
Pode quebrar, mas por seus scripts de package.json e não por seus estilos. Revise os scripts com o mesmo cuidado que a configuração:
| v1 | v2 |
|---|---|
panda codegen --silent |
panda codegen --log-level silent |
panda cssgen "src/**/*.tsx" |
panda cssgen --include "src/**/*.tsx" |
--cpu-prof |
--profile (escreve trace.json e timings.json, não .cpuprofile) |
panda inspect / validate / info |
panda doctor |
panda mcp |
npx -y @pandacss/mcp |
panda ship |
panda lib |
--poll |
eliminado |
A mudança dos globs posicionais é a mais perigosa. Em cssgen, analyze e debug, um glob sobrante não falha: Panda simplesmente o ignora e escaneia a lista include de sua configuração. O build termina bem, mas escaneia arquivos distintos do que você esperava.
Além dos scripts, sua imagem de CI precisa de Node 22 ou superior.
O que muda no CSS gerado?
O CSS se mantém igual ao da v1, exceto uma lista curta de mudanças deliberadas. Conheça-as antes de comparar a saída:
- Os breakpoints usam sintaxe de intervalo,
@media (width >= 48rem), em lugar demin-width. - Os overrides de borda se ordenam por propriedade, não por ordem no código. Um
borderWidthque se aplica a todos os lados agora sempre ganha de umborderInlineEndde um único lado. Quando um override tem que ganhar, use a propriedade longa:borderInlineEndWidth: '0'. - Desaparece o reset universal de variáveis. As 34 variáveis que a v1 colocava em cada elemento agora se registram com
@propertye só são emitidas quando usadas. Isso requer Chrome 85+, Safari 16.4+ ou Firefox 128+. Ativeoptimize.propertyFallback: truese você dá suporte a navegadores mais antigos. sizes.proseé mais estreita em@pandacss/preset-panda: 60ch em lugar de 65ch.scrollbarWidthaceita palavras-chave (auto | thin | none), não tokens de tamanho.
Se você migra gradualmente, fique atento às cascade layers. Panda emite seu CSS dentro de @layer, e de acordo com a especificação de CSS qualquer regra sem camada ganha de todas as regras com camada. Seus estilos legados vão ganhar dos componentes já convertidos, a menos que você remova o envoltório de camada com postcss-cascade-layers ou mantenha uma fronteira clara por rota ou por diretório.
O que vale a pena ativar depois de migrar?
-
O plugin de ESLint. Valida com o mesmo mecanismo de extração que seu build usa, e também roda sob oxlint:
// eslint.config.jsimport panda from '@pandacss/eslint-plugin'export default [panda.configs.recommended]Inclui regras como
no-invalid-token-paths,prefer-token,no-shorthand-longhand-mix,no-deprecatede umconsistent-property-stylecom autofix. -
viewTransition()permite estilizar a View Transitions API do seu styled system. -
firstThatWorks()emite um valor moderno com seu fallback, por exemplofirstThatWorks('100dvh', '100vh'). -
keyframes()epositionTry()definem animações e fallbacks de anchor positioning junto do componente que os usa, com tree-shaking de acordo com o que o build realmente referencia. -
panda libedesignSystempermitem publicar um sistema de design como pacote npm e consumi-lo sem extrair novamente na app. -
transform: truenos plugins de Vite, webpack, Rollup ou Bun reescreve as chamadas estáticas acss()como strings de classes, de modo que o runtime de estilos desaparece do bundle.
Panda CSS ou Tailwind?
Ambos geram CSS atômico em tempo de build; a diferença está em onde você escreve os estilos. Tailwind usa classes utilitárias no markup. Panda usa objetos de estilo e props tipados que são validados contra seus tokens, e com a v2 o plugin de ESLint faz cumprir esses tokens também no momento de fazer lint. Se você quer avaliar a mudança, a documentação do Panda inclui um guia de migração do Tailwind CSS.
E você? Qual mudança da v2 te preocupa mais ao migrar seu projeto?
- Tailwind CSS
- Panda CSS
- CSS-in-JS com runtime (Emotion, Styled Components)
- Prefiro outra opção (nos conte qual)
Comente abaixo ou, se este artigo chegou para você por email, responda diretamente ao email: sua resposta é publicada aqui.
Relacionado: Feature Friday: Vite 6.0 - A Revolução das Build Tools que Redefine a Velocidade