
building-ui-with-shadcn
by OxFrancesco
SKILL.md
name: building-ui-with-shadcn description: Builds accessible, consistent UI components using shadcn/ui with Tailwind v4 following strict design system guidelines. Use for frontend development, component creation, design implementation, and UI consistency across projects.
Building UI with shadcn/ui and Tailwind v4
Implements components using shadcn/ui and Tailwind v4 while adhering to a strict design system based on 4-size typography, 8pt grid spacing, and 60/30/10 color distribution.
Core Design Principles
1. Typography System: 4 Sizes, 2 Weights Only
Font Sizes:
- Size 1: Large headings (largest)
- Size 2: Subheadings and important content
- Size 3: Body text (default)
- Size 4: Small text and labels (smallest)
Font Weights:
- Semibold: Headings and emphasis only
- Regular: Body text and general UI elements
Never introduce additional font sizes or weights—maintain visual hierarchy through consistent sizing patterns.
2. 8pt Grid System
All spacing values MUST be divisible by 8 or 4:
✅ Correct:
- p-4 (16px), p-6 (24px), p-8 (32px)
- m-2 (8px), m-4 (16px), m-6 (24px)
- gap-2 (8px), gap-4 (16px), gap-8 (32px)
- Custom: 8, 16, 24, 32, 40, 48, 56, 64px
❌ Incorrect:
- 25px padding → Use 24px instead
- 11px margin → Use 12px instead
- 15px gap → Use 16px instead
- 7px, 13px, arbitrary values
Why: Creates visual harmony, simplifies decisions, establishes predictable patterns.
3. 60/30/10 Color Rule
Color Distribution:
-
60%: Neutral color (bg-background)
- Light mode: White or light gray
- Dark mode: Dark gray or black
- Usage: Primary backgrounds, cards, containers
-
30%: Complementary color (text-foreground)
- Light mode: Dark gray or black
- Dark mode: Light gray or white
- Usage: Text, icons, subtle UI elements
-
10%: Accent color (brand color)
- Your primary brand color (red, blue, etc.)
- Usage: Call-to-action buttons, highlights, important indicators
- ⚠️ Avoid overuse—reserve for elements needing attention
4. Clean Visual Structure
- Logical Grouping: Related elements visually connected
- Deliberate Spacing: Follow 8pt grid system
- Proper Alignment: Elements aligned within containers
- Simplicity First: Clarity and function before flashiness
Foundation
Tailwind v4 Setup
npx create-next-app@latest my-app
cd my-app
npx shadcn-ui@latest init
Configuration
tailwind.config.js (Tailwind v4):
import defaultConfig from 'tailwindcss/defaultConfig'
export default {
content: [
'./app/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
colors: {
background: 'var(--background)',
foreground: 'var(--foreground)',
primary: 'var(--primary)',
'primary-foreground': 'var(--primary-foreground)',
},
},
},
}
CSS Variables
app/globals.css (Tailwind v4):
@import "tailwindcss";
@theme {
--color-background: oklch(1 0 0);
--color-foreground: oklch(0.145 0 0);
--color-primary: oklch(0.205 0 0);
--color-primary-foreground: oklch(0.985 0 0);
--color-secondary: oklch(0.15 0 0);
--color-secondary-foreground: oklch(0.98 0 0);
--color-muted: oklch(0.96 0 0);
--color-muted-foreground: oklch(0.5 0 0);
--color-destructive: oklch(0.62 0.22 29.23);
--color-destructive-foreground: oklch(0.985 0 0);
}
@dark {
--color-background: oklch(0.08 0 0);
--color-foreground: oklch(0.98 0 0);
--color-primary: oklch(0.85 0.1 60);
--color-primary-foreground: oklch(0.12 0 0);
}
Typography System
Font Sizes Implementation
Use consistent sizing throughout your app:
// Heading 1 (Size 1 - largest)
<h1 className="text-4xl font-semibold">Main Title</h1>
// Heading 2 (Size 2)
<h2 className="text-2xl font-semibold">Section Title</h2>
// Body (Size 3 - default)
<p className="text-base font-regular">Body text content here</p>
// Small/Label (Size 4 - smallest)
<label className="text-sm font-regular">Label Text</label>
Typography Hierarchy
Always maintain clear hierarchy with limited options:
✅ Good hierarchy:
<div className="space-y-6">
<h1 className="text-4xl font-semibold">Page Title</h1>
<p className="text-base font-regular text-muted-foreground">Intro text</p>
<h2 className="text-2xl font-semibold mt-8">Section</h2>
<p className="text-base font-regular">Content</p>
<label className="text-sm font-regular">Input label</label>
</div>
❌ Inconsistent hierarchy:
// Too many different sizes and weights
<h1 className="text-5xl font-bold">Title</h1>
<h2 className="text-xl font-medium">Subtitle</h2>
<p className="text-lg font-semibold">Body</p>
8pt Grid System
Spacing Implementation
Always use multiples of 4 or 8:
// Correct spacing
<div className="p-6 space-y-4">
<div className="flex gap-2">Content</div>
<div className="m-4">Properly spaced</div>
</div>
// Incorrect spacing
<div className="p-5 space-y-3"> {/* ❌ 5 and 3 not divisible */}
<div className="flex gap-1.5">Content</div>
<div className="m-3">Inconsistent</div>
</div>
Common Spacing Values
| Purpose | Tailwind | Pixels | When to Use |
|---|---|---|---|
| Tight spacing | gap-2, p-2 | 8px | Small component padding |
| Standard spacing | gap-4, p-4 | 16px | Default padding/gaps |
| Loose spacing | gap-6, p-6 | 24px | Section padding |
| Very loose | gap-8, p-8 | 32px | Large section separation |
| Extra loose | gap-12, p-12 | 48px | Major section breaks |
Responsive Grid
Grid system applies to all breakpoints:
<div className="flex gap-4 md:gap-6 lg:gap-8">
{/* Gap increases from 16px → 24px → 32px */}
</div>
Color Implementation
Color Variables
Use CSS variables following OKLCH color format:
/* Light mode */
:root {
--background: oklch(1 0 0); /* White */
--foreground: oklch(0.145 0 0); /* Dark gray/black */
--primary: oklch(0.205 0 0); /* Brand color */
--secondary: oklch(0.15 0 0); /* Secondary */
--muted: oklch(0.96 0 0); /* Light gray bg */
--muted-foreground: oklch(0.5 0 0); /* Medium gray text */
--destructive: oklch(0.62 0.22 29.23); /* Red */
}
/* Dark mode */
@dark {
--background: oklch(0.08 0 0); /* Very dark */
--foreground: oklch(0.98 0 0); /* Light text */
--primary: oklch(0.85 0.1 60); /* Bright brand */
--muted: oklch(0.15 0 0); /* Dark gray bg */
--muted-foreground: oklch(0.7 0 0); /* Light gray text */
}
60/30/10 in Practice
// Correct color distribution
export function Card() {
return (
<div className="bg-background p-6"> {/* 60% - neutral background */}
<h2 className="text-foreground font-semibold">Title</h2> {/* 30% - text */}
<button className="bg-primary text-primary-foreground"> {/* 10% - accent */}
Action
</button>
</div>
);
}
❌ Overusing accent:
// Too many accent colors
<div className="bg-primary p-4">
<h2 className="text-primary font-semibold">Title</h2>
<button className="bg-primary">Button</button>
<div className="bg-secondary">More accents</div>
</div>
Component Architecture
shadcn/ui Structure
2-layered architecture:
- Behavior Layer: Radix UI primitives (accessibility, keyboard nav)
- Style Layer: Tailwind CSS + CVA (variants)
Component with data-slot
import { Button } from '@/components/ui/button'
// shadcn/ui v4 components use data-slot for styling
export function MyComponent() {
return (
<Button
variant="default"
size="lg"
className="w-full"
>
Click me
</Button>
)
}
Creating Custom Components
// components/ui/card.tsx
import { ReactNode } from 'react'
interface CardProps {
children: ReactNode
className?: string
}
export function Card({ children, className }: CardProps) {
return (
<div className={`bg-background border border-border rounded-lg p-6 ${className}`}>
{children}
</div>
)
}
// Usage with 8pt grid
<Card className="space-y-4">
<h2 className="text-2xl font-semibold">Title</h2>
<p className="text-base font-regular">Content</p>
</Card>
Installing Components
# Install individual components
npx shadcn-ui@latest add button
npx shadcn-ui@latest add card
npx shadcn-ui@latest add dialog
npx shadcn-ui@latest add input
Visual Hierarchy
Implementation Checklist
- Headings use Size 1 or 2 with semibold weight
- Body text uses Size 3 with regular weight
- Labels use Size 4 with regular weight
- Related elements grouped with consistent gap-4 or gap-6
- Important elements use accent color (10% max)
- Sufficient contrast between text and background
- Spacing follows 8pt grid throughout
Layout Example
export function Section() {
return (
<div className="space-y-6"> {/* Major spacing: 24px */}
<div>
<h2 className="text-2xl font-semibold">Section Title</h2>
<p className="text-sm text-muted-foreground mt-2">Subtitle</p>
</div>
<div className="space-y-4"> {/* Content spacing: 16px */}
<div className="flex gap-4"> {/* Item spacing: 16px */}
<img src="..." className="w-16 h-16 rounded" />
<div>
<h3 className="text-base font-semibold">Item</h3>
<p className="text-sm text-foreground">Description</p>
</div>
</div>
</div>
<button className="bg-primary text-primary-foreground px-6 py-3">
Action {/* Accent color: 10% */}
</button>
</div>
)
}
AI-Assisted Code Generation with Gemini CLI
Generate UI code using Google's Gemini AI while maintaining design system compliance.
Prerequisites
-
Get a Gemini API key:
- Visit Google AI Studio
- Create a new API key
- Save it securely
-
Set environment variable:
export GEMINI_API_KEY="your-api-key-here" -
Install Gemini CLI:
# Install globally (recommended) npm install -g @google/generative-ai-cli # Or use with npx (no installation) npx @google/generative-ai-cli
Prompting Gemini for UI Code
Use specific, design-system-aware prompts to generate compliant code:
Good prompt:
Create a React shadcn/ui component for a user profile card with:
- Title using text-2xl font-semibold
- Subtitle using text-sm font-regular
- Spacing following 8pt grid (use only gap-4, gap-6, gap-8, p-4, p-6, p-8)
- Colors: 60% neutral background, 30% text-foreground, 10% primary accent
- Only 4 font sizes and 2 weights (semibold, regular)
- Use Tailwind v4 utilities
Better prompt (with constraints):
Create a React component using shadcn/ui and Tailwind v4.
DESIGN CONSTRAINTS:
- Typography: Use ONLY text-4xl, text-2xl, text-base, text-sm with font-semibold or font-regular
- Spacing: Use ONLY gap-2, gap-4, gap-6, gap-8, p-2, p-4, p-6, p-8, m-2, m-4, m-6, m-8
- Colors: Follow 60/30/10 rule (bg-background 60%, text-foreground 30%, bg-primary 10%)
- Use className with Tailwind utilities, no custom CSS
Component: [Your specific component request here]
Running Gemini CLI
Interactive mode:
gemini
# Select "Use Gemini API key"
# Paste your prompt
Single query:
gemini "Create a button component with text-base font-semibold, p-4, bg-primary text-primary-foreground"
Workflow: Generate → Review → Integrate
-
Generate code with Gemini CLI:
gemini "Create a login form with email and password inputs, using 4 font sizes, 8pt grid spacing, and shadcn/ui components" -
Copy the generated code to your component file
-
Review against checklist:
- Only 4 font sizes (text-4xl, text-2xl, text-base, text-sm)
- Only 2 weights (font-semibold, font-regular)
- Spacing divisible by 4 or 8 (8px, 16px, 24px, 32px, etc.)
- Colors follow 60/30/10 rule
- Uses shadcn/ui components
- No custom CSS
-
Fix any violations:
- Replace non-compliant spacing: 5px → 4px, 11px → 12px
- Remove extra font weights: font-medium → use text size instead
- Adjust color distribution if needed
-
Integrate into your project:
// components/features/LoginForm.tsx import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' // [Paste generated code here after review]
Example: Generating a Dashboard Widget
Prompt:
Create a React component for a dashboard metric widget using shadcn/ui and Tailwind v4.
REQUIREMENTS:
- Display a number metric with label
- Show trend indicator (up/down)
- Typography: Use only text-2xl (metric), text-base (label), text-sm (description)
- All spacing values must be 8, 16, 24, 32, 48 pixels (p-2, p-4, p-6, p-8, p-12)
- Colors: bg-background, text-foreground, accent with bg-primary only on one element (trend indicator)
- Include border and rounded corners using Tailwind
Component name: MetricWidget
What you get back:
export function MetricWidget({ metric, label, trend }) {
return (
<div className="bg-background border border-border rounded-lg p-6 space-y-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-regular text-muted-foreground">
{label}
</p>
<p className="text-2xl font-semibold text-foreground mt-2">
{metric}
</p>
</div>
<div className={`px-4 py-2 rounded ${trend > 0 ? 'bg-primary' : 'bg-destructive'}`}>
<span className="text-sm font-regular text-primary-foreground">
{trend > 0 ? '↑' : '↓'} {Math.abs(trend)}%
</span>
</div>
</div>
<p className="text-sm font-regular text-muted-foreground">
Last 30 days
</p>
</div>
)
}
After review: This code already follows all guidelines! Copy it directly into your project.
Bypassing Generated Code to Main Agent
Once generated and validated:
// In your main agent or build process
import { MetricWidget } from '@/components/features/MetricWidget'
// Use in your application
export default function Dashboard() {
return (
<div className="space-y-6">
<MetricWidget metric="2,345" label="Total Users" trend={12} />
<MetricWidget metric="$45,231" label="Revenue" trend={8} />
</div>
)
}
The main agent can:
- Import and use the component directly
- Test it against the design system
- Request modifications if needed
- Integrate into larger layouts
Dark Mode
Configuration
// Automatic dark mode detection
<html className="dark">
{/* Dark mode CSS variables apply */}
</html>
Testing Dark Mode
# Toggle dark mode in browser DevTools
# Or use Tailwind's class-based approach
<html className={theme === 'dark' ? 'dark' : ''}>
Code Review Checklist
Design Principles
- Typography: Exactly 4 font sizes, only semibold/regular weights
- Spacing: All values divisible by 8 or 4 (no arbitrary values)
- Colors: 60% neutral, 30% complementary, 10% accent
- Structure: Elements logically grouped with consistent gaps
Technical
- Uses OKLCH color variables
- Leverages @theme directive for variables
- Components use proper data-slot attributes
- Class Variance Authority for variants
- Dark mode implemented consistently
- Accessibility: Good contrast, keyboard nav, semantic HTML
Common Issues to Flag
- ❌ More than 4 font sizes
- ❌ Extra font weights (medium, bold, etc.)
- ❌ Spacing not divisible by 4 or 8 (5px, 7px, 11px, etc.)
- ❌ Random padding/margins (inconsistent grid)
- ❌ Overused accent colors (exceeding 10%)
- ❌ Poor contrast between text and background
- ❌ Unnecessary custom CSS (when Tailwind utilities exist)
Resources
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon