2 pontos por GN⁺ 2026-01-21 | 4 comentários | Compartilhar no WhatsApp
  • Embora o botão de opção já seja um elemento HTML simples embutido no navegador, a biblioteca de UI Shadcn o reconstrói em várias camadas de componentes React
  • O <RadioGroup> e o <RadioGroupItem> do Shadcn encapsulam novamente componentes do Radix UI e usam ícones do lucide-react junto com dezenas de classes do Tailwind
  • O Radix usa atributos ARIA para acessibilidade e customização, mas na prática reutiliza elementos de botão em vez do <input type="radio"> nativo
  • Mesmo sendo possível obter o mesmo estilo com CSS simples, essa estrutura adiciona centenas de linhas de código e várias dependências, gerando complexidade desnecessária
  • Ao não reutilizar elementos HTML nativos, aumentam a perda de desempenho e a carga de manutenção, comprometendo a simplicidade do desenvolvimento web

Análise da estrutura dos botões de opção no Shadcn

  • O Shadcn implementa botões de opção por meio de dois componentes: <RadioGroup> e <RadioGroupItem>
    • Cada componente encapsula primitivas importadas de @radix-ui/react-radio-group e usa o CircleIcon do lucide-react
    • Há mais de 45 linhas de código, 3 imports externos e estilização com mais de 30 classes do Tailwind
  • A estrutura chega a carregar uma biblioteca de ícones SVG apenas para exibir um simples círculo
    • Algo que poderia ser substituído por border-radius no CSS ou por um elemento <circle>

O papel do Radix UI

  • O Radix usado pelo Shadcn é uma biblioteca de componentes de UI de baixo nível voltada para acessibilidade e customização
    • A implementação do grupo de botões de opção no Radix tem cerca de 215 linhas de código React e importa 7 arquivos
  • O Radix adiciona atributos ARIA ao elemento <button> para fazê-lo se comportar como um botão de opção
    • Porém, o primeiro princípio do uso de ARIA da W3C afirma que, sempre que possível, deve-se usar elementos HTML nativos
    • O Radix não segue esse princípio e reutiliza botões no lugar de <input>
  • Dentro de <form>, ele só adiciona um <input type="radio"> oculto, o que reduz a consistência da abordagem

Uma alternativa simples possível com CSS

  • O botão de opção HTML nativo pode ser estilizado com facilidade usando appearance: none, ::before, :checked, border-radius e outros recursos
    • No código de exemplo, a customização completa é feita sem dependências, JavaScript ou atributos ARIA
    • O mesmo efeito também pode ser implementado com Tailwind
  • A percepção de que “estilizar botões de opção é difícil” é um problema do passado; hoje é possível ter controle suficiente apenas com CSS puro

O problema do acúmulo de complexidade

  • Ao usar Shadcn junto com Radix, é preciso entender duas bibliotecas e centenas de linhas de código
    • Para um único botão de opção simples, são carregados vários KB de JavaScript adicionais
    • O usuário precisa esperar o parsing e a execução do JS apenas para alternar um botão
  • Essa estrutura leva a mais carga cognitiva, maior possibilidade de bugs e pior desempenho na web

De volta à simplicidade

  • O navegador já fornece botões de opção nativamente, e uma única linha como <input type="radio" name="beverage" value="coffee" /> já basta
  • Abstrações desnecessárias e o uso de bibliotecas em camadas prejudicam a simplicidade e a eficiência originais do desenvolvimento web
  • Mesmo em pequenos elementos de UI, um design que reaproveita funcionalidades nativas é melhor tanto para manutenção quanto para desempenho

4 comentários

 
crawler 2026-01-21

Entediante e pedante:

function RadioGroup({  
  className,  
  ...props  
}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {  
  return (  
    <RadioGroupPrimitive.Root  
      data-slot="radio-group"  
      className={cn("grid gap-3", className)}  
      {...props}  
    />  
  );  
}  
...  

Termina rapidinho, fica na memória por muito tempo:

<input type="radio" name="beverage" value="coffee" />  
 
slowandsnow 2026-01-22

Se você olhar o componente de botão do React Aria, vai quase desmaiar kkk

 
preserde 2026-01-21

Como alguém da área de frontend, é um problema que enfrento há muito tempo e, sinceramente, é um problema realmente difícil de resolver. A implementação continua mudando conforme a época, mas o fato de não resolverem isso com input type é igual em qualquer era... Tentar imitar o comportamento de botões de rádio e checkbox do navegador e ainda implementar separadamente as especificações de acessibilidade... afinal, qual é a ideia disso...? Não sei... Como o texto diz, hoje já existem alternativas até com CSS, então ver gente insistindo em implementar isso como componente a qualquer custo chega a ser meio engraçado.

 
GN⁺ 2026-01-21
Comentários do Hacker News
  • Não trabalho com frontend com tanta frequência, mas desde a época em que o React virou mainstream já dava para ver sinais de aumento de complexidade
    Outras camadas de abstração tendem a simplificar, mas o React acaba criando uma abstração muito mais complexa do que a tecnologia subjacente
    Tenho a sensação de que desenvolvedores que só conhecem React vão empilhando camadas cada vez mais altas, o que leva a resultados excessivamente arquitetados

    • Agora, acho que o maior problema é o clima em que todo mundo simplesmente assume que React é o padrão
      Por exemplo, Shadcn e Radix são bibliotecas de UI exclusivas para React, mas olhando só o marketing parecem bibliotecas de UI genéricas
    • Há mais de 15 anos eu crio UI com JavaScript puro e a DOM API
      Quando a escala cresce, no fim você acaba criando seu próprio framework ou ficando insatisfeito com os existentes, e o React resolve parte desse problema
      Vejo o problema mais na complexidade excessiva do ecossistema do que no React em si. Se você souber usar React bem, ainda pode ser bem agradável
    • Isso não é só um problema do React; acho que o problema maior é que as pessoas não querem aprender CSS moderno
      Só tentam contornar CSS com ferramentas como Tailwind. Eu gerencio estado com React, mas prefiro fazer o styling diretamente em CSS
      A parte mais difícil é convencer o time a aprender CSS
    • Abstração deveria ser, por natureza, uma ferramenta filosófica para esconder complexidade, mas hoje em dia muitas vezes faz o oposto
      Eu evito esses frameworks “modernos” e prefiro, sempre que possível, as tecnologias básicas
    • O núcleo do React é a abstração por componentes
      React só fornece a “caixa”, e o que vai dentro dela é decisão do desenvolvedor. Esse é o verdadeiro poder do React
  • Este exemplo de radio button é engraçado e impressionante ao mesmo tempo
    O resultado final é indistinguível de um radio button com CSS básico, então fico me perguntando por que fazer algo tão complexo
    Tenho curiosidade se existem exemplos de sites de grande escala feitos sem esse tipo de complexidade desnecessária

    • O site da McMaster-Carr é frequentemente citado como um bom exemplo. Também há uma thread no Hacker News sobre isso
    • Há 15 anos eu fiz um webapp colaborativo de vídeo, e o frontend era quase todo uma estrutura vanilla baseada em jQuery
      Tinha mais código do que hoje, mas a interface passava uma sensação de resposta imediata
      Dá para ver no código do projeto Takeoff
    • “E este site?” — talvez o próprio Hacker News seja um exemplo disso
    • Quanto maior a empresa, mais os gestores querem uma stack padronizada
      Como diz o ditado, “ninguém foi demitido por escolher React”, então virou a opção segura
    • A UI é algo que todo mundo vê e sobre a qual todo mundo opina, então a complexidade cresce como uma tragédia dos comuns
  • Desenvolvedores precisam lembrar que sempre podem contestar exigências de design
    Eu vi um desenvolvedor desperdiçar 4 horas em um problema simples de layout no React Native; sugeri perguntar se o design podia mudar um pouco, e resolveu em 10 minutos

    • Hoje em dia eu prefiro frameworks de UI sem JS (Pico.CSS, Skeleton, Bulma, Tailwind/daisyUI)
      Só com CSS já dá para obter resultados muito bons. Queria saber se alguém aqui recomenda esse tipo de abordagem
  • O maior erro de 2025 foi ter escolhido Shadcn
    Ver imports contínuos do Radix foi o primeiro alerta, e ver o componente de radio foi o segundo
    Como o projeto já estava em andamento, acabei seguindo e ajustando tudo com Copilot, mas no fim também não gostei dessa dependência de IA
    O POC anterior era muito mais simples e eficiente. Um dia quero refazer tudo em HTML vanilla

    • A combinação React+NextJS+Tailwind+Shadcn é o ápice da complexidade
      Remix e React Router 7 pelo menos tentavam se manter mais próximos dos padrões da web
      Foi no Tailwind que pensei “isso não dá”, e se meus amigos continuarem dizendo que ficou bom depois da refatoração, talvez eu reveja isso
    • Na verdade, Tailwind e React não combinam tão bem
      React já tem styling baseado em props, então não faz muito sentido usar blocos enormes de classes CSS
      Se o foco for acessibilidade, só o Radix UI já basta
  • O problema é que o elemento <input> do navegador, especialmente radio e select, é difícil de customizar
    O radio button padrão tem usabilidade ruim no mobile

    • Na verdade, até controles nativos podem ser estilizados suficientemente bem com CSS
      Gostaria de entender com mais detalhe quais problemas você teve no mobile
    • O próprio texto mostra como estilizar radio buttons com CSS. Esse é mesmo o problema?
    • Se você envolver com <label> e adicionar padding, no mobile já fica bastante utilizável
    • “select” continua sendo chato de estilizar, mas o resto dá para customizar com bastante flexibilidade
  • A maioria dos projetos começa com boas intenções, mas em algum momento acaba cheia de radio buttons com 200 linhas de código e 7 imports
    É assim que começa a deterioração do código (code rot)

  • Usei daisyUI recentemente e gostei bastante
    Como é baseado em CSS puro, consegue aproveitar bem novos recursos do navegador (como dialog)

    • Mas em termos de acessibilidade ainda deixa bastante a desejar
      Por exemplo, o Drawer não faz focus trap, e o Accordion usa radio buttons de forma abusiva como substituto de JS
      É por isso que bibliotecas como Radix inevitavelmente acabam ficando complexas
  • Concordo com a ideia central do texto, mas se o designer criou no Figma um estilo exato que precisa ficar idêntico em todos os navegadores, será que CSS vanilla dá conta?
    Dá para reproduzir completamente algo como a demo do Radix?

    • Com alguns ajustes, dá para chegar bem perto
      Veja este exemplo no CodePen
    • No fim das contas, mesmo por baixo desses frameworks complexos, CSS continua sendo o núcleo
      Basta extrair o CSS e aplicá-lo a um componente React simples
    • Como neste exemplo, se você aplicar o mesmo CSS a um input vanilla, a compatibilidade entre navegadores também fica boa
    • O próprio autor do texto apareceu para dizer que “o exemplo básico foi apenas adaptado ao estilo do Shadcn; se quiser, dá para customizar o quanto quiser
    • Mas fica a questão de até onde vale perseguir perfeição
      Será que vale mesmo adicionar dezenas de KB de código e custo de manutenção só para evitar pequenas diferenças visuais?
      Como no ditado de Nam June Paik, “se ficar perfeito demais, Deus fica bravo”
  • O custo real não é o código, e sim o tempo de onboarding
    Para um desenvolvedor novo entender um radio button de 47 linhas baseado em Radix, podem ir semanas
    Já uma abordagem vanilla dá para fazer em um dia e explicar em 20 minutos
    Claro, se for um produto como Figma ou Linear, onde acessibilidade e navegação por teclado são cruciais, essa complexidade pode ser justificável

    • Fica a dúvida se uma boa biblioteca não deveria permitir uso sem que você precisasse entender sua estrutura interna
  • Muita gente critica o Shadcn, mas eu acho justamente que ele incentiva bem a estrutura de componentes e a reutilização
    A essência do Shadcn é a filosofia de “possua e modifique seus próprios componentes”
    Isso é uma abordagem fundamentalmente diferente das bibliotecas de UI tradicionais