Communitygithub.com

shadcn-ui/ui

Migra projetos e componentes React do Radix UI para Base UI. Use quando solicitado a migrar do Radix, mudar para base-ui, converter primitivas Radix ou trocar a biblioteca base de um projeto shadcn. Lida com componentes individuais ('migrar accordion') e projetos inteiros.

O que é ui?

Esta habilidade automatiza a migração de wrappers shadcn e composições Radix para `@base-ui/react`, garantindo que o projeto permaneça compilável a cada etapa. É particularmente útil para desenvolvedores que desejam trocar a biblioteca base de seus projetos shadcn (de Radix para Base UI) de forma progressiva ou completa. A habilidade suporta dois modos: progressivo (migrando um componente por vez, mantendo ambos coexistentes) e projeto completo (migrando todos os componentes de uma vez). Ela prioriza o uso do CLI do shadcn para estilos conhecidos (golden pair), aplica merge de três vias para wrappers personalizados e usa um mecanismo de transformação manual para componentes não shadcn. Inclui regras rígidas para evitar tocar em bibliotecas não Radix (como cmdk, vaul, sonner), lida com gaps de funcionalidade sem equivalentes no Base UI e gera relatórios detalhados por componente em `.migration/`. A verificação é contínua: typecheck por arquivo, build por lote e build completo ao final, comparado com a linha de base.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/shadcn-ui/ui/tree/HEAD/skills/migrate-radix-to-base

Perguntar na sua IA favorita

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

Documentação

Migração Radix UI -> Base UI

Você migra wrappers shadcn, composições Radix feitas manualmente e seus consumidores para @base-ui/react, mantendo o projeto compilável em cada etapa. Seja preciso; nunca adivinhe um mapeamento. Quando uma prop ou parte não estiver nestes arquivos de referência, verifique node_modules/@base-ui/react/**/*.d.ts antes de transformar e registre as lacunas no relatório.

Pré-voo (sempre)

  1. npx shadcn@latest info --json (ou o runner do projeto): fornece a base atual, STYLE (ex.: radix-lyra), versão do Tailwind, aliases, componentes instalados e gerenciador de pacotes. Confie nele em vez de inferir.
  2. Detecte o gerenciador de pacotes (campo packageManager / lockfile: pnpm-lock.yaml, bun.lock, yarn.lock, package-lock.json) e use ELE para cada instalação. Nunca deixe um lockfile obsoleto.
  3. Exija uma árvore git limpa; trabalhe em uma branch; um commit por componente.
  4. Verificação de linha de base ANTES de tocar em dependências: execute o typecheck/build do projeto para que falhas pré-existentes nunca sejam atribuídas a você.
  5. Instale @base-ui/react junto com radix. Os pacotes Radix são removidos apenas após o ÚLTIMO componente ser migrado (ambos coexistem bem).

Estratégia: golden pair primeiro, mecanismo de transformação depois

  • Golden pair via CLI (preferido). Se o projeto é shadcn com um estilo conhecido (radix-<style>), o próprio CLI do shadcn é o executor do golden pair:
    1. Classifique CADA wrapper ui PRIMEIRO: compare o arquivo do usuário com sua origem padrão, usando o estilo do components.json VERBATIM na URL (https://ui.shadcn.com/r/styles/<style>/<component>.json, files[0].content). Isso funciona para estilos prefixados (radix-nova) E legados não prefixados (new-york, new-york-v4, default), todos ainda servidos.
    2. Modo PROJETO COMPLETO: altere o estilo radix-<style> em components.json para base-<style> agora. Modo PROGRESSIVO: NÃO altere ainda (o projeto ainda está majoritariamente radix; a alteração acontece uma vez, após o último componente); busque as variantes base diretamente pela URL (https://ui.shadcn.com/r/styles/base-<style>/<component>.json).
    3. Wrappers ÍNTEGROS, modo projeto completo: shadcn add <component> --overwrite entrega a variante base com a resolução exata de ícone/fonte/preset do projeto. Nunca faça --all --overwrite em lote; vá componente por componente, ou você se afogará em deriva de versão não relacionada do registro. Modo PROGRESSIVO: nunca use --overwrite (ele destrói o original que os consumidores ainda importam); escreva o conteúdo da variante base buscada em <component>-base.tsx.
    4. Wrappers PERSONALIZADOS: busque a variante base e replique o diff do usuário nela (suas personalizações devem SOBREVIVER; --overwrite as destruiria). Implementação mecânica que funciona em escala: git merge-file user.tsx radix-golden.tsx base-golden.tsx (merge de três vias, radix golden como ancestral) resolve automaticamente a maioria dos arquivos; resolva conflitos manualmente com as tabelas de referência.
    5. VARREDURA OBRIGATÓRIA de resíduos em CADA arquivo golden pair, incluindo os que mesclaram "limpo": grep -n "radix-ui\|@radix-ui\|IconPlaceholder" por arquivo. O registro às vezes reordena funções entre variantes, o que faz o merge de três vias relatar zero conflitos enquanto deixa fragmentos radix obsoletos no lugar. Um merge limpo NÃO é prova de um arquivo limpo. Isso é mais confiável do que reconstruir transformações; use-o sempre que o par existir. Código de consumidor/app não tem mecanismo via CLI: sempre migre manualmente contra consumer-props.md.
  • Estilos legados (new-york, new-york-v4, default): classificação apenas, sem replay. Estes não têm contraparte base (não existe base-new-york), e redirecionar para uma variante base- reformataria o app do usuário. Use o radix golden APENAS para detectar personalizações, depois execute o mecanismo de transformação no PRÓPRIO arquivo do usuário: reconecte primitivas, mantenha suas classes exatas, aplique renomeações de class-mapping. A aparência deles permanece a mesma. No final de uma migração de projeto completo legada, SINALIZE (não corrija): o nome do estilo ainda aparece como radix para o CLI, então futuros shadcn add entregarão variantes radix; o usuário decide se muda o estilo ou adiciona manualmente.
  • Mecanismo de transformação (fallback). Código radix feito manualmente, projetos não shadcn, estilos desconhecidos: transforme usando universal-patterns.md (imports em AMBAS as formas: radix-ui e @radix-ui/react-*; asChild->render com o exemplo trabalhado; Portal>Positioner>Popup; a regra FORWARD do positioner; renomeações de partes), as tabelas de props por família (overlays.md, menus.md, form-controls.md, disclosure.md, display-misc.md), class-mapping.md para reescritas de data-attribute/CSS-var, e wrapper-shapes.md para formas alvo exatas (seta de tooltip, defaults de SubContent, anatomia de select).

Modos

Progressivo (padrão). "Migrar accordion" = um componente, strangler-fig:

  1. Detecte estado em andamento primeiro: um <component>-base.tsx existente, consumidores divididos entre importações antigas/novas. Os arquivos SÃO o estado; retome, nunca recomece.
  2. Se o componente importa outros wrappers ui ainda em radix (select -> button), PARE e recomende migrar aqueles primeiro, de baixo para cima.
  3. Escreva a versão migrada em <component>-base.tsx (original intocado; conteúdo golden pair buscado por URL, ou transformado manualmente, de acordo com a estratégia acima); faça typecheck. Reaponte os consumidores UM DE CADA VEZ (importações + as props de ponto de chamada em consumer-props.md); faça typecheck em cada um. Quando nenhum consumidor importar o original: exclua-o, renomeie -base -> original, reverta as importações, verificação final, commit. Quando o ÚLTIMO wrapper radix no projeto for finalizado, altere components.json para base-<style> e remova as dependências radix.

Projeto completo (apenas quando explicitamente solicitado): mesmo trabalho por componente em ordem de dependência (wrappers de folha/compartilhados como button e label primeiro). Após os wrappers, varra TODO o código do app contra consumer-props.md — a superfície de quebra no ponto de chamada é muito maior do que asChild. Em seguida, remova as dependências radix, instale, build completo.

Regras rígidas

  • NUNCA toque em bibliotecas não Radix ou seus wrappers: cmdk (command), vaul (drawer), sonner, input-otp, react-day-picker (calendar), recharts (chart). Relate-os como intencionalmente não tocados.
  • Sem contraparte Base UI: AspectRatio -> div com aspect-ratio CSS; Label -> <label> nativo; VisuallyHidden -> sr-only; Direction -> Direction Provider (prop direction, não dir). Popover Anchor e NavigationMenu Indicator não têm equivalente: passagem inerte + sinalização.
  • button.tsx migra para a primitiva REAL @base-ui/react/button, nunca um wrapper useRender feito manualmente.
  • Deltas de comportamento são SINALIZADOS, nunca corrigidos silenciosamente (ativação manual de tabs, itens de menu não fechando ao clicar, delay de 50ms do nav-menu). O alvo é Base UI idiomático correspondendo ao registro base do shadcn.
  • Relato honesto: arquivos pulados/revertidos são listados como sinalizados, nunca como migrados. Falhas pré-existentes são nomeadas como pré-existentes.

Verificar e relatar

Typecheck por arquivo, build por lote, build completo no final vs linha de base.

Os relatórios residem em um diretório .migration/ na raiz do projeto, UM ARQUIVO POR COMPONENTE: .migration/<component>.md (ex.: .migration/accordion.md). Regras:

  • Cada execução escreve (ou sobrescreve completamente) o arquivo para cada componente que migrou. Reexecutar um componente substitui seu relatório; nunca toque nos arquivos de outros componentes.
  • Uma execução com vários componentes ("migrar alert-dialog e dropdown-menu") escreve um arquivo por componente, cada um autocontido; notas de varredura de consumidor compartilhadas são repetidas em cada arquivo afetado.
  • Modo projeto completo escreve os arquivos por componente mais .migration/project.md (troca de dependência, resumo da varredura de código do app, resultado do build final).
  • NÃO há arquivo de índice. O status da migração é derivado do disco, não mantido: escaneie o diretório ui do projeto (o alias ui do shadcn info, ex.: components/ui ou src/components/ui) em busca de importações radix restantes quando perguntado "o que ainda falta". Termine cada resumo de execução com essa contagem derivada ("N wrappers permanecem em Radix").

Cada .migration/<component>.md usa EXATAMENTE esta estrutura (é documentado publicamente; os relatórios devem corresponder a ele):

# <component>

<data, estratégia usada (golden pair via CLI / merge / mecanismo), veredito de uma linha>

## Alterado

<todos os arquivos tocados, com o que mudou e por quê; inclua arquivo:linha
para qualquer coisa notável. Confirme que a varredura de resíduos está
limpa:
grep -n "radix-ui\|@radix-ui" nestes arquivos do componente>

## Deixado de lado

<arquivos que parecem relacionados mas foram intencionalmente não tocados,
com o motivo (cmdk/vaul/sonner não são radix; deriva não relacionada; etc.)>

## Mudanças de comportamento

<diferenças que compilam bem mas agem de forma diferente; sinalizadas,
nunca corrigidas (ativação de tabs, fechamento ao clicar em menu,
delays...). Seção vazia se nenhuma>

## Verificar manualmente

<pequena lista de verificação de QA manual para esta família de primitivas:
retorno de foco em diálogos, navegação por teclado + typeahead em
menus/select, sensação de delay de tooltip, eventos de commit de slider.
Passos concretos, um minuto de cliques>

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Habilidades Relacionadas