tailwind-ui
SKILL.md
Tailwind CSS UI Development
Build beautiful, responsive interfaces using Tailwind CSS utility-first approach.
Instructions
- Use utility classes directly - Avoid custom CSS when Tailwind utilities exist
- Mobile-first approach - Start with base styles, add responsive modifiers
- Extract components - When patterns repeat 3+ times, create a component
- Use design tokens - Leverage Tailwind's spacing, color, and typography scales
- Implement dark mode - Use
dark:variant for theme support
Core Patterns
Responsive Design
// Mobile-first: base → sm → md → lg → xl → 2xl
<div className="
w-full // Mobile: full width
sm:w-1/2 // 640px+: half width
md:w-1/3 // 768px+: third width
lg:w-1/4 // 1024px+: quarter width
p-4 sm:p-6 lg:p-8 // Responsive padding
">
Content
</div>
Dark Mode
<div className="
bg-white dark:bg-gray-900
text-gray-900 dark:text-gray-100
border border-gray-200 dark:border-gray-700
">
<h2 className="text-gray-800 dark:text-gray-200">
Title
</h2>
</div>
Flexbox & Grid Layouts
// Flexbox
<div className="flex items-center justify-between gap-4">
<div className="flex-1">Content</div>
<div className="flex-shrink-0">Fixed</div>
</div>
// Grid
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div>Card 1</div>
<div>Card 2</div>
<div>Card 3</div>
</div>
// Auto-fit grid
<div className="grid grid-cols-[repeat(auto-fit,minmax(300px,1fr))] gap-4">
{items.map(item => <Card key={item.id} {...item} />)}
</div>
Component Examples
Button Variants
const buttonVariants = {
primary: "bg-blue-600 hover:bg-blue-700 text-white",
secondary: "bg-gray-200 hover:bg-gray-300 text-gray-900 dark:bg-gray-700 dark:text-gray-100",
danger: "bg-red-600 hover:bg-red-700 text-white",
ghost: "hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-300",
outline: "border-2 border-gray-300 hover:border-gray-400 text-gray-700",
};
const buttonSizes = {
sm: "px-3 py-1.5 text-sm",
md: "px-4 py-2 text-base",
lg: "px-6 py-3 text-lg",
};
interface ButtonProps {
variant?: keyof typeof buttonVariants;
size?: keyof typeof buttonSizes;
children: React.ReactNode;
}
export function Button({ variant = 'primary', size = 'md', children }: ButtonProps) {
return (
<button className={`
${buttonVariants[variant]}
${buttonSizes[size]}
inline-flex items-center justify-center
font-medium rounded-lg
transition-colors duration-200
focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500
disabled:opacity-50 disabled:cursor-not-allowed
`}>
{children}
</button>
);
}
Card Component
export function Card({ children, className = '' }: { children: React.ReactNode; className?: string }) {
return (
<div className={`
bg-white dark:bg-gray-800
rounded-xl shadow-sm
border border-gray-200 dark:border-gray-700
overflow-hidden
${className}
`}>
{children}
</div>
);
}
Card.Header = ({ children }: { children: React.ReactNode }) => (
<div className="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
{children}
</div>
);
Card.Body = ({ children }: { children: React.ReactNode }) => (
<div className="px-6 py-4">{children}</div>
);
Card.Footer = ({ children }: { children: React.ReactNode }) => (
<div className="px-6 py-4 bg-gray-50 dark:bg-gray-900/50 border-t border-gray-200 dark:border-gray-700">
{children}
</div>
);
Input with Label
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
label: string;
error?: string;
hint?: string;
}
export function Input({ label, error, hint, id, ...props }: InputProps) {
const inputId = id || label.toLowerCase().replace(/\s+/g, '-');
return (
<div className="space-y-1">
<label
htmlFor={inputId}
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
>
{label}
</label>
<input
id={inputId}
className={`
w-full px-3 py-2 rounded-lg
border transition-colors duration-200
${error
? 'border-red-500 focus:ring-red-500'
: 'border-gray-300 dark:border-gray-600 focus:ring-blue-500'
}
bg-white dark:bg-gray-800
text-gray-900 dark:text-gray-100
placeholder-gray-400 dark:placeholder-gray-500
focus:outline-none focus:ring-2 focus:ring-offset-0
disabled:bg-gray-100 disabled:cursor-not-allowed
`}
aria-invalid={!!error}
aria-describedby={error ? `${inputId}-error` : hint ? `${inputId}-hint` : undefined}
{...props}
/>
{hint && !error && (
<p id={`${inputId}-hint`} className="text-sm text-gray-500 dark:text-gray-400">
{hint}
</p>
)}
{error && (
<p id={`${inputId}-error`} className="text-sm text-red-600 dark:text-red-400" role="alert">
{error}
</p>
)}
</div>
);
}
Tailwind Configuration
Custom Theme
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
darkMode: 'class',
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
colors: {
brand: {
50: '#eff6ff',
100: '#dbeafe',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
},
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
spacing: {
'18': '4.5rem',
'88': '22rem',
},
animation: {
'fade-in': 'fadeIn 0.3s ease-out',
'slide-up': 'slideUp 0.3s ease-out',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
},
},
},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
],
};
shadcn/ui Integration
# Initialize shadcn/ui
npx shadcn@latest init
# Add components
npx shadcn@latest add button card input dialog
// Using shadcn/ui components
import { Button } from "@/components/ui/button";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
function Dashboard() {
return (
<Card>
<CardHeader>
<CardTitle>Analytics</CardTitle>
</CardHeader>
<CardContent>
<Button variant="outline">View Details</Button>
</CardContent>
</Card>
);
}
Best Practices
- Use
cn()utility - Merge class names conditionally with clsx/tailwind-merge - Group related utilities - Keep layout, spacing, colors together
- Avoid arbitrary values - Use theme tokens when possible
- Use CSS variables for themes - Dynamic theming with HSL colors
- Purge unused styles - Configure content paths correctly
When to Use
- Styling React/Vue/Svelte applications
- Building component libraries
- Rapid prototyping
- Design system implementation
- Responsive web design
Notes
- Requires PostCSS configuration
- Use Tailwind CSS IntelliSense VS Code extension
- Consider class variance authority (CVA) for complex variants
- Pair with Headless UI for accessible components
Weekly Installs
1
Repository
fgarofalo56/sup…t_fabricFirst Seen
13 days ago
Security Audits
Installed on
amp1
cline1
openclaw1
opencode1
cursor1
kimi-cli1