Home Design shadcn-tailwindshadcn-tailwind ui Safe Intermediate Claude MCP Cursor
How to Install
macOS / Linux Windows Cursor
Claude Code: git clone --depth 1 https://github.com/mwathiben/hush-private-bookmarks.git && cp hush-private-bookmarks/.claude/skills/shadcn-tailwind ~/.claude/skills/shadcn-tailwind -rCopy
Claude Code (Windows): git clone --depth 1 https://github.com/mwathiben/hush-private-bookmarks.git && xcopy hush-private-bookmarks\.claude\skills\shadcn-tailwind %USERPROFILE%\.claude\skills\shadcn-tailwind\ /Y /E /ICopy
Cursor: Open SKILL.md on GitHub → copy all content → paste into your project root .cursorrules fileCopy
---
name: shadcn-tailwind
description: Build UIs with Tailwind CSS v4 and shadcn/ui. Covers CSS variables with OKLCH colors, component variants with CVA, responsive design, dark mode, and Tailwind v4.2 features. Supports Radix UI and Base UI primitives, CLI 3.0, and visual styles. Use when building interfaces with Tailwind, styling shadcn/ui components, implementing themes, or working with utility-first CSS. Triggers on tailwind, shadcn, utility classes, CSS variables, OKLCH, component styling, theming, dark mode, radix ui.
---
# Styling with Tailwind CSS
Build accessible UIs using Tailwind CSS v4 utility classes and shadcn/ui component patterns. **Tailwind v4 uses CSS-first configuration only - never create or modify `tailwind.config.js`/`tailwind.config.ts`.** Supports Radix UI (default) or Base UI as primitive libraries.
## Critical Rules
### No `tailwind.config.js` - CSS-First Only
Tailwind v4 configures everything in CSS. Migrate any JS/TS config:
- `theme.extend.colors` → `@theme { --color-*: ... }`
- `plugins` → `@plugin "..."` or `@utility`
- `content` → `@source "..."`
- `tailwindcss-animate` → `@import "tw-animate-css"`
- `@layer utilities` → `@utility name { ... }`
### Always Use Semantic Color Tokens
```tsx
// CORRECT - respects themes and dark mode
// WRONG - breaks theming
```
Always pair `bg-*` with `text-*-foreground`. Extend with success/warning/info in [theming.md](theming.md).
### Never Build Class Names Dynamically
```tsx
// WRONG - breaks Tailwind scanner
// CORRECT - complete strings via lookup
const colorMap = { red: "bg-red-500", blue: "bg-blue-500" } as const
```
### cn() Merge Order
Defaults first, consumer `className` last (tailwind-merge last-wins):
```tsx
className={cn(buttonVariants({ variant, size }), className)} // correct
className={cn(className, buttonVariants({ variant, size }))} // wrong
```
### Animation Performance
```tsx
// WRONG - transition-all causes layout thrashing
// CORRECT - transition only what changes
// CORRECT - respect reduced motion
```
### `@theme` vs `@theme inline`
- `@theme` - static tokens, overridable by plugins
- `@theme inline` - references CSS variables, follows dark mode changes
```css
@theme { --color-brand: oklch(0.6 0.2 250); } /* static */
@theme inline { --color-primary: var(--primary); } /* dynamic */
```
See [components.md](components.md) for more pitfalls and [theming.md](theming.md) for color system reference.
## Core Patterns
### CSS Variables for Theming
shadcn/ui uses semantic CSS variables mapped to Tailwind utilities:
```css
/* globals.css - Light mode */
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--border: oklch(0.922 0 0);
--radius: 0.5rem;
}
/* Dark mode */
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
}
/* Tailwind v4: Map variables */
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
}
```
**Usage in components:**
```tsx
// Background colors omit the "-background" suffix
```
### Component Authoring Pattern
Components use plain functions with `data-slot` attributes (React 19 - no `forwardRef`):
```tsx
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 px-3 text-xs",
lg: "h-10 px-8",
icon: "size-9",
},
},
defaultVariants: { variant: "default", size: "default" },
}
)
// Plain function with React.ComponentProps (not forwardRef)
function Button({
className,
variant,
size,
...props
}: React.ComponentProps<"button"> & VariantProps
) {
return (
)
}
// Usage
Click me
```
**Icon spacing with `data-icon`:**
```tsx
Generating...
Save Changes
```
### Responsive Design
Mobile-first breakpoints:
```tsx
// Stack on mobile, grid on tablet+
// Hide on mobile
// Different layouts per breakpoint
// Responsive text sizes
```
### Container Queries
First-class in Tailwind v4, no plugin needed:
```tsx
Responds to container width, not viewport
// Named containers
```
### Dark Mode
```tsx
// Use dark: prefix - but prefer semantic colors over manual dark: overrides
// auto dark mode
// manual override
// Use next-themes for toggle: useTheme() → setTheme("dark" | "light")
// Always add suppressHydrationWarning to to prevent flash
```
## Common Component Patterns
### Card
```tsx
```
### Form Field
```tsx
```
### Badge
```tsx
const badgeVariants = cva(
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors",
{
variants: {
variant: {
default: "border-transparent bg-primary text-primary-foreground shadow",
secondary: "border-transparent bg-secondary text-secondary-foreground",
destructive: "border-transparent bg-destructive text-destructive-foreground",
outline: "text-foreground",
},
},
}
)
```
## Layout Patterns
### Centered Layout
```tsx
```
### Sidebar Layout
```tsx
```
### Dashboard Grid
```tsx
Wide card
Regular
Regular
Full width
```
## Accessibility Patterns
### Focus Visible
```tsx
```
### Screen Reader Only
```tsx
Close dialog
```
### Disabled States
```tsx
```
## Tailwind v4 Features
### CSS-First Configuration
```css
@import "tailwindcss";
/* Custom utilities (replaces @layer utilities) */
@utility tab-highlight-none {
-webkit-tap-highlight-color: transparent;
}
/* Custom variants */
@custom-variant pointer-fine (@media (pointer: fine));
/* Source control */
@source inline("{hover:,}bg-red-{50,100,200}");
@source not "./legacy";
```
### @theme Directive
```css
@theme {
--color-primary: oklch(0.205 0 0);
--font-sans: "Inter", system-ui;
}
/* With CSS variables (shadcn/ui pattern) */
@theme inline {
--color-primary: var(--primary);
}
```
### Animation
```css
@import "tw-animate-css";
```
```tsx
```
### v4.1 Features
```tsx
// Text shadows
// Gradient masks for fade effects
Fades to transparent at bottom
// Pointer-aware sizing
// Form validation after user interaction
// Overflow wrap for long strings
verylongwordthatneedstowrap
```
### v4.2 Features (February 2026)
```tsx
// Logical block properties (RTL/writing-mode aware)
// Logical sizing (replaces w-*/h-* for logical layouts)
// Font feature settings
Tabular numbers
// New color palettes: mauve, olive, mist, taupe
```
**Deprecation:** `start-*`/`end-*` deprecated in favor of `inset-s-*`/`inset-e-*`.
## OKLCH Colors
All shadcn/ui colors use OKLCH format: `oklch(lightness chroma hue)`. Lightness 0-1, chroma 0-0.4 (0 = gray), hue 0-360. Base palettes: Neutral, Zinc, Slate, Stone, Gray. See [theming.md](theming.md) for complete palettes and OKLCH reference.
## Best Practices
### Prefer Semantic Colors
```tsx
// Good - uses theme
// Avoid - hardcoded
```
### Group Related Utilities
```tsx
```
### Avoid Arbitrary Values
```tsx
// Prefer design tokens
// Avoid when unnecessary
```
## Installation & CLI
```bash
# Create new project with visual style + primitive selection
npx shadcn create
# Initialize in existing project
pnpm dlx shadcn@latest init
# Add components
pnpm dlx shadcn@latest add button card form
# Add from community registries
npx shadcn add @acme/button @internal/auth-system
# View/search registries
npx shadcn view @acme/auth-system
npx shadcn search @tweakcn -q "dark"
npx shadcn list @acme
# Add MCP server for AI integration
npx shadcn@latest mcp init
# Update existing components
pnpm dlx shadcn@latest add button --overwrite
```
### Visual Styles
`npx shadcn create` offers 5 built-in visual styles:
- **Vega** - Classic shadcn/ui look
- **Nova** - Compact, reduced padding
- **Maia** - Soft and rounded, generous spacing
- **Lyra** - Boxy and sharp, pairs with mono fonts
- **Mira** - Dense, for data-heavy interfaces
These rewrite component code (not just CSS variables) to match the selected style.
## Troubleshooting
**Colors not updating:** Check CSS variable in globals.css → verify `@theme inline` includes the mapping → clear build cache.
**Dark mode flash on load:** Add `suppressHydrationWarning` to `` tag and ensure ThemeProvider wraps app with `attribute="class"`.
**Found `tailwind.config.js`:** Delete it. Run `npx @tailwindcss/upgrade` to auto-migrate to CSS-first config. All customization belongs in your CSS file via `@theme`, `@utility`, `@plugin`.
**Classes not detected:** Check `@source` directives cover your component paths. Never construct class names dynamically (see Critical Rules).
## Component Patterns
For detailed component patterns see [components.md](components.md):
- **Composition**: asChild pattern, data-slot attributes
- **Typography**: Heading scales, prose styles, inline code
- **Forms**: React Hook Form + Zod, Field component with FieldSet/FieldGroup
- **Icons**: Lucide icons with data-icon attributes
- **Inputs**: OTP, file, grouped inputs
- **Dialogs**: Modal patterns and composition
- **Data Tables**: TanStack table integration
- **Toasts**: Sonner notifications
- **Pitfalls**: cn() order, form defaultValues, dialog nesting, sticky, server/client
## Resources
See [theming.md](theming.md) for complete color system reference:
- `@theme` vs `@theme inline` (critical for dark mode)
- Status color extensions (success, warning, info)
- Z-index scale and animation tokens
- All base palettes (Neutral, Zinc, Slate, Stone, Gray)
## Summary
Key concepts:
- **v4 CSS-first only** - no `tailwind.config.js`, all config in CSS
- **Semantic colors only** - never use raw palette (`bg-blue-500`), always `bg-primary`
- **Always pair** `bg-*` with `text-*-foreground`
- **Never build class names dynamically** - use object lookup with complete strings
- **cn() order** - defaults first, consumer `className` last
- **No `transition-all`** - transition only specific properties
- **`@theme inline`** for dynamic theming, `@theme` for static tokens
- Author components as plain functions with `data-slot` (React 19)
- Apply CVA for component variants
- Use `motion-safe:` / `motion-reduce:` for animations
- Choose Radix UI or Base UI as primitive library
This skill targets Tailwind CSS v4.2 with shadcn/ui. For component-specific examples, see [components.md](components.md). For color system, see [theming.md](theming.md).
Works Well With Skills from the same repository — often designed to work together
© 2026 SkillsNav — Privacy | Contact
How to cite: SkillsNav. (2026). AI Agent Skills Directory . https://skillsnav.net/