//
Busque em todas as páginas da documentação
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Estas receitas de skill são projetadas para o Claude Code, mas também funcionam com outros agentes de codificação de IA que suportam arquivos de skill/instrução.
O conteúdo completo do SKILL.md que você pode copiar para .claude/skills/tailwind-v4-shadcn/SKILL.md:
---
name: tailwind-v4-shadcn
description: "Domine a arquitetura e estilização de componentes do Tailwind CSS v4 + shadcn/ui. Use quando solicitado: ajuda com tailwind, componente shadcn, estilização, temas, modo escuro, variáveis CSS, design responsivo, animação, configuração do Tailwind v4."
allowed-tools: "Read, Write, Edit, Glob, Grep, Bash(npm:*), Bash(npx:*), Bash(pnpm:*), Agent"
---
# Tailwind v4 + shadcn/ui
Você é um especialista em Tailwind CSS v4 e shadcn/ui. Forneça orientação autoritativa sobre estilização, temas e arquitetura de componentes.
## Principais Mudanças do Tailwind v4 em relação ao v3
O Tailwind v4 usa um modelo de configuração CSS-first. Não há mais `tailwind.config.js` por padrão.
### Configuração CSS-First
```css
/* app/globals.css */
@import "tailwindcss";
/* Valores de tema personalizados */
@theme \{
--color-primary: oklch(0.7 0.15 240);
--color-primary-foreground: oklch(0.98 0.01 240);
--color-secondary: oklch(0.6 0.1 280);
--color-secondary-foreground: oklch(0.98 0.01 280);
--color-accent: oklch(0.8 0.12 160);
--font-sans: "Inter", sans-serif;
--font-mono: "JetBrains Mono", monospace;
--radius-lg: 0.75rem;
--radius-md: 0.5rem;
--radius-sm: 0.25rem;
--breakpoint-xs: 30rem;
--animate-slide-in: slide-in 0.3s ease-out;
\}
@keyframes slide-in \{
from \{ transform: translateY(10px); opacity: 0; \}
to \{ transform: translateY(0); opacity: 1; \}
\}tailwind.config.js é opcional (CSS-first via @theme)@apply é desencorajado (use extração de componentes em vez disso)theme() substituída por variáveis CSSbg-opacity-* substituído pela sintaxe bg-black/50@container, @sm, @md, @lgrotate-x-*, rotate-y-*, perspective-*text-wrap-balance, text-wrap-prettyfield-sizing-content para textareas de auto-dimensionamentocolor-scheme-* para esquemas de cores do sistema@media (prefers-color-scheme: dark)npx shadcn@latest init
npx shadcn@latest add button card dialog form inputcomponents/ui/. Modifique-os diretamente.cn() (clsx + twMerge) para classes condicionais.import \{ clsx, type ClassValue \} from "clsx";
import \{ twMerge \} from "tailwind-merge";
export function cn(...inputs: ClassValue[]) \{
return twMerge(clsx(inputs));
\}
// Uso
<div className=\{cn(
"rounded-lg border p-4",
isActive && "border-primary bg-primary/10",
className // permite sobrescrita pelo pai
)\} />// components/ui/card.tsx - base do shadcn
const Card = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
(\{ className, ...props \}, ref) => (
<div
ref=\{ref\}
className=\{cn(
"rounded-lg border bg-card text-card-foreground shadow-sm",
className
)\}
\{...props\}
/>
)
);
// Seu componente composto
function ProductCard(\{ product \}: \{ product: Product \}) \{
return (
<Card className="hover:shadow-md transition-shadow">
<CardHeader>
<CardTitle>\{product.name\}</CardTitle>
<CardDescription>\{product.category\}</CardDescription>
</CardHeader>
<CardContent>
<p className="text-2xl font-bold">$\{product.price\}</p>
</CardContent>
<CardFooter>
<Button className="w-full">Add to Cart</Button>
</CardFooter>
</Card>
);
\}/* app/globals.css */
@import "tailwindcss";
@theme inline \{
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
\}
:root \{
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--radius: 0.625rem;
\}
.dark \{
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.145 0 0);
--card-foreground: oklch(0.985 0 0);
--primary: oklch(0.985 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.269 0 0);
--input: oklch(0.269 0 0);
--ring: oklch(0.439 0 0);
\}"use client";
import \{ useTheme \} from "next-themes";
import \{ Button \} from "@/components/ui/button";
import \{ Moon, Sun \} from "lucide-react";
export function ThemeToggle() \{
const \{ theme, setTheme \} = useTheme();
return (
<Button
variant="ghost"
size="icon"
onClick=\{() => setTheme(theme === "dark" ? "light" : "dark")\}
>
<Sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Alternar tema</span>
</Button>
);
\}// Design responsivo mobile-first
<div className="
grid
grid-cols-1 // mobile: coluna única
sm:grid-cols-2 // 640px+: 2 colunas
lg:grid-cols-3 // 1024px+: 3 colunas
xl:grid-cols-4 // 1280px+: 4 colunas
gap-4
p-4 sm:p-6 lg:p-8
">
// Container queries (novo no v4)
<div className="@container">
<div className="@sm:flex @sm:gap-4 @lg:grid @lg:grid-cols-3">
\{/* Responde à largura do container, não ao viewport */\}
</div>
</div>// Animações integradas do Tailwind
<div className="animate-spin" /> // spinner
<div className="animate-pulse" /> // carregamento de esqueleto
<div className="animate-bounce" /> // atenção
// Animações personalizadas com @theme
// Em globals.css:
// @theme \{ --animate-fade-in: fade-in 0.5s ease-out; \}
// @keyframes fade-in \{ from \{ opacity: 0; \} to \{ opacity: 1; \} \}
<div className="animate-fade-in" />
// Padrões de transição
<button className="
transition-colors duration-200
bg-primary hover:bg-primary/90
active:scale-95 transition-transform
" />
// Para animações complexas, use Framer Motion com Tailwind
import \{ motion \} from "framer-motion";
<motion.div
initial=\{\{ opacity: 0, y: 20 \}\}
animate=\{\{ opacity: 1, y: 0 \}\}
className="rounded-lg border bg-card p-6"
/>@apply extensivamente - Extraia componentes em vez de @applycn() - Conflitos de classe sem twMerge causam estilos inesperadosclassNamew-[347px] é um sinal de alerta; use a escala de design
## Exemplo de Trabalho
### Exemplo 1: Usuário pergunta "Ajude-me a configurar temas para meu aplicativo"
**Prompt do usuário:** "Quero um aplicativo com tema azul e suporte a modo escuro usando shadcn/ui."
**Resposta guiada pela skill produziria:**
- Variáveis CSS para uma paleta de cores azul em oklch
- Definições de tema claro e escuro
- Configuração do provedor `next-themes`
- Componente de alternância de tema
- Componentes de exemplo usando os tokens de tema
### Exemplo 2: Usuário pergunta "Como personalizo um Button do shadcn?"
**Prompt do usuário:** "Quero adicionar uma variante 'gradient' ao Button do shadcn."
**Resposta guiada pela skill produziria:**
```tsx
// components/ui/button.tsx - Adicionar às variantes existentes
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 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
// NOVO: variante gradient
gradient: "bg-gradient-to-r from-primary to-accent text-primary-foreground hover:opacity-90",
},
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",
},
}
);
Esta skill fornece:
mkdir -p .claude/skills/tailwind-v4-shadcn
# Cole o conteúdo da Receita em .claude/skills/tailwind-v4-shadcn/SKILL.md@theme, não tailwind.config.js - Você ainda pode usar um arquivo de configuração, mas CSS-first é a abordagem padrão e recomendada.oklch podem não funcionar em navegadores mais antigos - Inclua fallbacks para IE/Safari antigo, se necessário.add.twMerge deve ser configurado para classes personalizadas - Se você adicionar classes Tailwind personalizadas, configure tailwind-merge para reconhecê-las.@container no pai - Sem isso, @sm: e consultas semelhantes não funcionarão.class (classe .dark no elemento html), não media (prefers-color-scheme). Certifique-se de que next-themes esteja configurado para corresponder.| Abordagem | Quando Usar |
|---|---|
| CSS Modules | Estilos com escopo de componente sem classes utilitárias |
| Styled Components | CSS-in-JS com tematização dinâmica |
| Panda CSS | CSS-in-JS type-safe com extração em tempo de compilação |
| Vanilla Extract | CSS-in-TypeScript sem runtime |
| Radix Themes | Biblioteca de componentes pré-construída (menos personalizável que shadcn) |
| Park UI | Componentes semelhantes a shadcn para Ark UI |
@theme no seu arquivo CSStailwind.config.js é opcional e não é mais o padrão@import "tailwindcss";
@theme {
--color-primary: oklch(0.7 0.15 240);
--font-sans: "Inter", sans-serif;
--radius-lg: 0.75rem;
--animate-slide-in: slide-in 0.3s ease-out;
}@theme dentro do seu arquivo CSS--nome-categoria: valor@apply é desencorajado (use extração de componentes em vez disso)theme() substituída por variáveis CSSbg-opacity-* substituído por sintaxe de barra como bg-black/50ring-3 em vez de ring)import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}clsx (classes condicionais) com twMerge (resolve conflitos do Tailwind)twMerge, classes conflitantes como p-4 e p-6 seriam aplicadas ambascomponents/ui/ - eles vivem na sua base de códigocn() para classes condicionaisclass (classe .dark no elemento html), não media (prefers-color-scheme):root e substituições escuras em .darknext-themes para o toggle, configurado para corresponder à estratégia class@container no elemento pai@container no pai, @sm:, @md:, @lg: não responderão@container, @sm, @md, @lgrotate-x-*, rotate-y-*, perspective-*text-wrap-balance, text-wrap-prettyfield-sizing-content para textareas de auto-dimensionamentotwMerge não reconhecerá suas classes personalizadastailwind-merge para reconhecer quaisquer classes utilitárias personalizadas que você definirimport { cn } from "@/lib/utils";
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
variant?: "default" | "outlined";
}
function Card({ className, variant, ...props }: CardProps) {
return (
<div
className={cn("rounded-lg bg-card p-4", className)}
{...props}
/>
);
}React.HTMLAttributes<HTMLDivElement> para herdar className e todas as props nativas de div@apply extensivamente em vez de extrair componentescn() que causa conflitos de classew-[347px] com muita frequência em vez da escala de designRevisado por Chris St. John·Última atualização: 10 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥