12k
All articles

shadcn/ui Migrou de Radix para Base UI

shadcn/ui trocou novos projetos de Radix para Base UI. Veja o que mudou, quem não precisa migrar e o custo real da mudança.

OpenReplay Team
OpenReplay Team
shadcn/ui Migrou de Radix para Base UI

Se sua aplicação shadcn/ui roda sobre Radix, você não precisa migrar. Base UI agora é o padrão para novos projetos, mas o Radix continua totalmente suportado, as atualizações são publicadas para ambas as bibliotecas, e a equipe do shadcn ainda usa Radix em suas próprias aplicações em produção.

A mudança entrou em vigor em 3 de julho de 2026. Boa parte da cobertura desde então deu a entender que uma reescrita está a caminho, o que não é o que o changelog diz.

Duas perguntas determinam o que você faz a seguir: se você precisa agir, e quanto custa uma migração caso você opte por ela. O custo se divide entre mudanças que o compilador detecta e mudanças que ele não detecta, e é na segunda categoria que mora o risco.

Principais Conclusões

  • Base UI é o padrão para novos projetos shadcn/ui; Radix não foi descontinuado, e -b radix mantém o Radix em um init novo.
  • Aplicações Radix existentes não precisam de alterações: as atualizações são publicadas para ambas as bibliotecas, e a equipe do shadcn ainda roda Radix em produção.
  • O padrão mudou porque o Base UI havia atingido uma versão estável 1.6.0 com mais de seis milhões de downloads semanais, e os usuários do shadcn/create o escolhiam em vez do Radix numa proporção de dois para um.
  • Uma migração se divide entre mudanças que quebram o build (asChild para render, Positioner/Popup, valores nulos em Select) e mudanças silenciosas de comportamento (ativação manual de abas, menus que permanecem abertos), que representam o custo real.
  • Se você migrar, mantenha ambas as bibliotecas instaladas, mova um componente por commit e use a skill oficial do shadcn em vez de um codemod.

O Que Mudou em 3 de Julho de 2026

Novos projetos shadcn/ui agora usam Base UI por padrão, e nada mais em um projeto existente mudou. Três coisas se moveram. Executar npx shadcn init seleciona Base UI a menos que você diga o contrário, o shadcn/create coloca Base UI no topo de sua lista, e a documentação de componentes agora abre na aba Base UI, com uma aba Radix ao lado. O Radix em si não foi descontinuado.

Manter o Radix em um novo projeto exige apenas uma flag:

pnpm dlx shadcn init -b radix

Em qualquer lugar onde a CI ou um script de scaffolding chame shadcn init sem prompt e assuma que receberá Radix, passe essa flag agora. O padrão por trás desses scripts mudou.

Você Precisa Migrar para os Componentes shadcn Base UI?

Não. O changelog assume o compromisso de publicar cada atualização e cada novo componente em ambas as bibliotecas, com a única exceção dos componentes que existem no Base UI e não têm contrapartida no Radix. Também afirma que o próprio código de produção da equipe continua em Radix, sem planos de migrá-lo. Uma aplicação Radix estável não tem prazo forçado, nem janela de descontinuação, nem penhasco de manutenção. O restante deste artigo é para equipes que escolhem migrar, não para equipes que precisam migrar.

Por Que o Padrão Mudou?

O changelog apresenta quatro razões. A biblioteca havia atingido uma versão estável 1.6.0 e ultrapassava seis milhões de downloads por semana. Seus mantenedores continuam adicionando primitivas úteis. A equipe do shadcn já havia padronizado seu uso para tudo que fosse novo. E, entre as pessoas criando projetos com o shadcn/create, o Base UI vencia com aproximadamente duas escolhas para cada uma que ia para o Radix.

Esses números são os citados no changelog. O Base UI continuou publicando desde então: a versão 1.8.0 chegou em 4 de setembro de 2026. O changelog também aponta que o Base UI vem das mesmas pessoas que construíram o Radix. O pacote a instalar é @base-ui/react; o nome mais antigo @base-ui-components/react traz um aviso de descontinuação no npm redirecionando para ele.

O Que Uma Migração Realmente Muda

A metade da migração que quebra o build é mecânica: renomeações e mudanças de tipo que o compilador detecta imediatamente.

RadixBase UI
asChild em triggersprop render
Portal > ContentPortal > Positioner > Popup
OverlayBackdrop
variantes data-[state=open]:variantes data-open:
onOpenChange(open) + event.preventDefault()onOpenChange(open, details) + details.cancel()

Uma nuance: a divisão Positioner/Popup se aplica a popups ancorados como Menu, Select, Popover e Tooltip. O Dialog não tem Positioner; é Dialog.Backdrop mais Dialog.Popup.

A mudança no callback fica assim:

// Radix: block closing via the event
onEscapeKeyDown={(event) => event.preventDefault()}

// Base UI: one callback, with a reason and a cancel()
onOpenChange={(open, details) => {
  if (details.reason === "escape-key") {
    details.cancel()
    return
  }
  setOpen(open)
}}

Os tipos de valor também mudam. Um Select controlado agora retorna Value | null em vez de uma string, o que torna essa a quebra de build mais comum:

const [fruit, setFruit] = useState<string | null>(null)

Os valores de Accordion e Toggle Group são sempre arrays, mesmo no modo de seleção única, então value="a" se torna value={["a"]}.

As Mudanças Que Compilam mas Se Comportam de Forma Diferente

A metade perigosa da migração passa na verificação de tipos sem problemas e ainda assim muda o comportamento em tempo de execução. Três diferenças se destacam:

  • Abas ativam manualmente por padrão. As setas do teclado movem o foco entre os triggers sem trocar o painel visível, a menos que você defina activateOnFocus em Tabs.List, cujo padrão é false. O Radix usava ativação automática por padrão.
  • Itens de checkbox e radio do menu mantêm o menu aberto. closeOnClick tem padrão false em Menu.CheckboxItem e Menu.RadioItem, o oposto do fechar-ao-selecionar do Radix. O Menu.Item simples continua com padrão true, então o comportamento difere conforme o tipo de item.
  • NavigationMenu abre mais rápido no hover. O delay do Base UI tem padrão de 50ms; o delayDuration do Radix tem padrão de 200ms. Menus pelos quais os usuários passavam de raspão agora abrem.

Nada disso produz um erro. Um menu que permanece aberto após um clique e abas que ignoram as setas do teclado são invisíveis para o monitoramento de erros, porque nada é lançado. É no session replay que essa classe de regressão vem à tona: você assiste um usuário pressionar uma seta, ou clicar duas vezes em um item de checkbox, e vê a UI não responder da forma que ele espera.

Quem Deve Migrar para o Base UI e Quem Não Deve?

Migre se você precisa de Combobox, Autocomplete ou Number Field, que o Radix nunca entregou, ou se quiser permanecer alinhado com os novos componentes do registry conforme eles chegam. Fique no Radix se sua aplicação estiver estável e nada disso se aplicar; o compromisso de suporte é explícito, e uma aplicação em produção que funciona não ganha nada com uma troca de primitivas.

Não baseie a decisão em rumores sobre lacunas de componentes. O Base UI entrega Context Menu, Toast e uma primitiva de hover-card sob o nome Preview Card, e a documentação Base UI do shadcn cobre todos os três.

Como Migrar, Caso Você Decida Migrar

Use a skill oficial, não um codemod, e mova progressivamente. O raciocínio se sustenta. Um codemod só conhece a versão original de um arquivo, então ele lida bem com os componentes que você deixou intactos e falha nos que você alterou. A skill lê o que você realmente tem, transfere suas edições e reporta diferenças de comportamento em vez de reescrevê-las silenciosamente.

pnpm dlx skills add shadcn/ui

Depois peça ao seu agente de código para migrar um componente, por exemplo migrate accordion to base-ui. Você pode manter ambas as bibliotecas instaladas ao mesmo tempo, então o build permanece verde entre as etapas. Cada execução faz a verificação de tipos do que produziu, escreve uma nota sobre aquele componente em uma pasta .migration/ e a entrega como um commit próprio em uma branch que você pode descartar. Comece pelos componentes-folha, como button e label, antes dos componentes que os importam, e leia a seção de mudanças de comportamento de cada relatório antes de fazer o merge.

Um aviso: alguns guias sugerem apontar o components.json para o Base UI e readicionar todos os componentes com --overwrite. Isso descarta todas as edições locais que você fez nesses arquivos, que é exatamente a falha que a skill existe para evitar.

Onde Isso Deixa Você

O padrão mudou; suas obrigações não. Aplicações Radix existentes continuam sendo publicadas, novos projetos recebem Base UI a menos que você passe -b radix, e uma migração é um projeto opcional cujo custo visível são as renomeações e cujo custo oculto é o comportamento. Se você migrar, reserve tempo de QA para as diferenças silenciosas, porque é aí que o compilador deixa de ajudar. Comece lendo a entrada do changelog você mesmo, depois decida se Combobox ou o alinhamento com o registry vale a branch.

Perguntas Frequentes

O Base UI está pronto para produção em comparação ao Radix?

Sim. O Base UI lançou uma versão estável 1.0.0 em dezembro de 2025 sob o pacote '@base-ui/react' e vem publicando releases de forma consistente desde então, chegando à 1.8.0 em 4 de setembro de 2026. Ele vem dos criadores do Radix, do Floating UI e do Material UI, e sua equipe afirma que moldou a API para se parecer com a do Radix de propósito, para que a transição entre as duas exija menos trabalho. A equipe do shadcn também usa Base UI em todo novo projeto que inicia.

Todas as props de valor são arrays no Base UI?

Não. O 'value' do Accordion é sempre um array e o 'value' do Toggle Group é sempre um array de strings, mesmo no modo de seleção única, mas o 'value' das Tabs continua sendo um valor único com padrão 0, e o Select é tipado como um valor único, um array ou null. Envolva os valores de Accordion e Toggle Group em arrays, tipe o estado controlado do Select como nulo, e deixe as Tabs inalteradas.

Migrar para o Base UI afeta componentes shadcn que nunca usaram Radix?

Não. O Command envolve o cmdk, o Sonner é uma biblioteca de toast independente, o Calendar usa react-day-picker, o Input OTP usa input-otp, e os Charts são construídos sobre recharts. Nenhum deles depende de primitivas do Radix, então uma migração de Radix para Base UI os deixa intocados. Apenas componentes cujas primitivas vieram do Radix, como Dialog, Menu, Select, Tabs e Popover, precisam de alguma alteração.

A skill de migração do shadcn exige pnpm?

Não. O changelog documenta a instalação da skill para pnpm, npm, yarn e bun, então 'npx skills add shadcn/ui' é um equivalente válido baseado em npm do comando pnpm. Após a instalação, a skill roda através do seu agente de código, que migra um componente por vez e produz código com verificação de tipos, um relatório por componente no diretório '.migration' e um commit por componente, independentemente do gerenciador de pacotes.

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.