- Publicado em
O que é shadcn/ui? Entendendo seu propósito, benefícios e uso em aplicações React modernas
- Autores
O que é shadcn/ui? Entendendo seu propósito, benefícios e uso em aplicações React modernas
Projetos React modernos frequentemente enfrentam um equilíbrio difícil: usar uma biblioteca de interface pronta (rápida, mas inflexível) ou projetar seu próprio sistema (flexível, mas demorado de construir)?
É aí que entra o shadcn/ui, uma nova abordagem para o desenvolvimento de interfaces que oferece controle total sobre seu código com o acabamento de uma biblioteca madura de componentes.
Neste guia, vamos explorar o que é shadcn/ui, por que se tornou tão popular entre desenvolvedores React e Next.js e como você pode usá-lo para acelerar seu trabalho de interface sem perder flexibilidade.
O que é shadcn/ui?
shadcn/ui (frequentemente escrito apenas como shadcn) não é um pacote npm tradicional nem uma biblioteca de componentes com temas como Material UI ou Chakra UI.
Em vez disso, é uma coleção de componentes React de alta qualidade e de código aberto, construídos com:
- Tailwind CSS (para estilização)
- Radix UI (para primitivas acessíveis e sem estilo)
- Lucide Icons (para ícones SVG limpos e consistentes)
Mas há uma diferença:
Em vez de instalá-lo como dependência, você copia o código-fonte real de cada componente para seu próprio projeto.
Isso significa que cada botão, caixa de diálogo ou menu suspenso reside em sua própria base de código, editável, personalizável com temas e com versões controladas por você.
Você pode pensar nele como um gerador de componentes ou kit inicial de interface, não como uma dependência.
Como funciona
O projeto shadcn/ui fornece uma ferramenta de linha de comando que gera a estrutura dos componentes diretamente no seu projeto:
npx shadcn-ui@latest add button
Esse comando baixa um componente Button acessível e pronto e o adiciona à sua pasta local components/ui/. A partir daí, você pode personalizá-lo, alterar classes Tailwind, ajustar variantes ou adaptá-lo ao seu sistema de design.
Cada componente é apenas React + Tailwind + Radix, sem lógica oculta nem dependência de execução.
Por que os desenvolvedores usam shadcn/ui
1. Propriedade completa do código
Diferentemente de bibliotecas de interface em que você depende de dependências opacas, shadcn fornece o código-fonte completo do componente. Você pode:
- Editar os estilos diretamente
- Adicionar propriedades ou variantes
- Integrar lógica personalizada (como análise de uso ou permissões)
A interface é sua, as regras são suas, sem esperar que os mantenedores aceitem uma solicitação de pull.
2. Construído sobre bases comprovadas
Cada componente é construído usando:
- Tailwind CSS → estilização baseada em classes utilitárias
- Radix UI → primitivas básicas acessíveis e sem estilo
- Lucide Icons → ícones SVG modernos
- clsx / tailwind-variants → gerenciamento condicional organizado de classes
Isso garante que seus componentes sejam acessíveis e prontos para produção, seguindo boas práticas de sistemas de design por padrão.
3. Consistência e velocidade
Você recebe um ponto de partida coeso e bonito para sua interface:
- Espaçamento, tipografia e sistema de cores consistentes
- Modo escuro e temas por meio de variáveis CSS
- Padrões de layout e interação prontos para uso (menus suspensos, modais, dicas de contexto)
Você pode começar a entregar interfaces que parecem ter sido projetadas, sem reinventar cada componente.
4. Sem dependência do fornecedor
Como os componentes são apenas código, você pode:
- Criar versões derivadas
- Substituí-los
- Combiná-los com outras bibliotecas
Se o shadcn/ui mudar ou deixar de atender às suas necessidades, seus componentes continuam pertencendo inteiramente a você.
Componentes comuns e exemplos
Aqui estão alguns dos componentes mais populares do shadcn/ui e como ficam em ação.
Exemplo 1: botão
import { Button } from '@/components/ui/button'
export default function Example() {
return (
<div className="space-x-2">
<Button>Default</Button>
<Button variant="outline">Outline</Button>
<Button variant="destructive">Delete</Button>
</div>
)
}
Por que é ótimo:
- Variantes integradas como
outline,destructiveeghost. - Temas totalmente personalizáveis com os tokens de design do Tailwind.
- Simples o suficiente para personalizar sem perder consistência.
Entendendo as variantes do botão
Quando você executa:
npx shadcn-ui@latest add button
A ferramenta de linha de comando cria um arquivo button.tsx dentro de components/ui/, normalmente assim:
// components/ui/button.tsx
import * as React from 'react'
import { cva } from 'class-variance-authority'
import { cn } from '@/lib/utils'
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: 'h-10 px-4 py-2',
sm: 'h-9 rounded-md px-3',
lg: 'h-11 rounded-md px-8',
icon: 'h-10 w-10',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
function Button({ className, variant, size, ...props }: ButtonProps) {
return <button className={cn(buttonVariants({ variant, size, className }))} {...props} />
}
export { Button, buttonVariants }
Então, o que são outline, destructive e ghost?
São variantes de estilo predefinidas nessa configuração buttonVariants. Você não precisa defini-las manualmente, elas já vêm por padrão com o componente gerado.
Cada variante corresponde a um padrão diferente de classes Tailwind:
| Variante | Estilo visual | Uso típico |
|---|---|---|
default | Botão primário sólido (bg-primary, texto branco) | Chamada principal à ação (por exemplo, “Salvar”, “Enviar”). |
outline | Fundo transparente, borda visível | Ação secundária ou menor destaque (“Cancelar”). |
destructive | Vermelho/cor de perigo (bg-destructive) | Ações com consequências destrutivas (“Excluir”, “Remover”). |
ghost | Estilo mínimo, efeito sutil ao passar o cursor | Botões de pouco destaque (por exemplo, ícones, links secundários). |
link | Estilizado como link de texto | Navegação dentro do próprio texto. |
Assim, quando você escreve:
<Button variant="destructive">Delete</Button>
está instruindo o componente Button a usar o estilo vermelho de perigo, porque a variante corresponde a bg-destructive e text-destructive-foreground.
O que são “tokens de design do Tailwind”?
“Tokens de design” são variáveis nomeadas de cor e espaçamento usadas em todo o seu tema. No shadcn/ui, eles são definidos no seu globals.css (ou tailwind.config.js) assim:
:root {
--background: 0 0% 100%;
--foreground: 222.2 47.4% 11.2%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
/* etc. */
}
Depois, o Tailwind os referencia como “tokens”, usando sua sintaxe theme() ou atalhos de classes:
className = 'bg-primary text-primary-foreground hover:bg-primary/90'
Esses tokens:
- Mantêm as cores consistentes entre os componentes.
- Oferecem suporte automático ao modo escuro por meio de variáveis CSS.
- Permitem que designers e desenvolvedores compartilhem uma linguagem visual (por exemplo, “primário”, “destaque”, “destrutivo”) em vez de códigos hexadecimais brutos.
Por que isso é útil
- Você pode adicionar ou modificar variantes (por exemplo,
success,warning) facilmente no mesmobutton.tsx. - Sua interface permanece visualmente consistente, pois todas as variantes usam tokens de design compartilhados.
- Atualizar seu tema (cores, espaçamento etc.) atualiza instantaneamente todos os componentes.
- É flexível, use as variantes integradas ou amplie-as para corresponder à sua marca.
Em resumo: Essas variantes (outline, destructive, ghost etc.) são estilos prontos baseados em tokens de design que você pode ampliar ou substituir. Elas são parte do que torna os componentes shadcn/ui prontos para produção por padrão, consistentes, adaptados ao tema e facilmente personalizáveis.
Exemplo 2: caixa de diálogo (modal)
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog'
export default function Example() {
return (
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Confirm Action</DialogTitle>
</DialogHeader>
<p>This action cannot be undone.</p>
</DialogContent>
</Dialog>
)
}
Por que é ótimo: A caixa de diálogo usa primitivas Radix internamente, o que significa que é acessível por teclado, compatível com leitores de tela e responsiva por padrão.
Exemplo 3: componentes de entrada e formulário
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
export default function LoginForm() {
return (
<form className="space-y-4">
<div>
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="you@example.com" />
</div>
<Button type="submit">Login</Button>
</form>
)
}
Organizados, mínimos e fáceis de ampliar para qualquer página de autenticação ou configurações.
Quando usar (e quando não usar) shadcn/ui
✅ Use quando
- Está criando um produto personalizado (SaaS, painel, aplicação) e quer uma interface consistente rapidamente.
- Precisa de controle total sobre o design e a acessibilidade.
- Já usa Tailwind CSS e Next.js.
❌ Evite quando
- Prefere um sistema de design pronto para incorporar (como MUI, Chakra UI).
- Não usa Tailwind (a integração é estreita).
- Quer avançar extremamente rápido sem mexer no código dos componentes.
Primeiros passos (configuração rápida)
Instale Tailwind CSS (se ainda não estiver instalado):
npx create-next-app my-app cd my-app npx tailwindcss init -pInicialize shadcn/ui
npx shadcn-ui@latest initAdicione componentes
npx shadcn-ui@latest add button card dialog inputImporte e personalize Seus novos componentes aparecerão em
components/ui/.
🧩 shadcn comparado a outras bibliotecas de interface
| Recurso | shadcn/ui | Chakra UI | Material UI | Headless UI |
|---|---|---|---|---|
| Propriedade do código | ✅ Você é o proprietário | ❌ Controlado pela biblioteca | ❌ Controlado pela biblioteca | ✅ Você é o proprietário |
| Estilização | Tailwind | Styled System | Emotion / CSS | Tailwind |
| Acessibilidade | ✅ Radix UI | ✅ | ✅ | ✅ |
| Temas | ✅ (variáveis CSS + Tailwind) | ✅ | ✅ | ⚙️ Personalizados |
| Curva de aprendizado | 🟢 Baixa | 🟢 Média | 🔴 Alta | 🟡 Média |
| Liberdade de personalização | 🟢 Total | 🟡 Parcial | 🔴 Limitada | 🟢 Total |
Principais conclusões
- shadcn/ui não é um pacote, é um modelo de componentes de copiar e assumir a propriedade.
- Você recebe controle real, ausência de dependência do fornecedor e ótima experiência de desenvolvimento.
- Construído com Tailwind, Radix e padrões React modernos, é ideal para equipes que querem uma base de design organizada, acessível e extensível.
É o equilíbrio perfeito entre “construir tudo sozinho” e “depender de uma biblioteca de interface pesada”.