🎨 TailwindCSS
📋 Overview
TailwindCSS is a utility-first CSS framework that provides low-level utility classes to build custom designs without leaving your HTML. We've extended it with our custom design tokens and component patterns.
🚀 Utility-First Approach
TailwindCSS provides utility classes that allow rapid UI development:
tsx
function EventCard({ event }: { event: Event }) {
return (
<div className="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow duration-200">
<h3 className="text-xl font-semibold text-gray-900 mb-2">
{event.title}
</h3>
<p className="text-gray-600 mb-4">
{event.description}
</p>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-500">
{formatDate(event.date)}
</span>
<button className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md transition-colors duration-200">
Learn More
</button>
</div>
</div>
)
}🎨 Custom Design System
We've extended TailwindCSS with our custom design tokens:
tsx
export default {
theme: {
extend: {
colors: {
primary: {
50: '#fef2f2',
100: '#fee2e2',
500: '#ef4444',
600: '#dc2626',
700: '#b91c1c',
},
secondary: {
50: '#f8fafc',
100: '#f1f5f9',
500: '#64748b',
600: '#475569',
700: '#334155',
}
},
fontFamily: {
sans: ['var(--font-inter)', 'system-ui', 'sans-serif'],
display: ['var(--font-poppins)', 'system-ui', 'sans-serif'],
},
animation: {
'fade-in': 'fadeIn 0.5s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out',
}
}
}
}🧩 Component Variants
Using TailwindCSS with a component library approach:
tsx
const buttonVariants = {
primary: 'bg-primary-600 hover:bg-primary-700 text-white px-4 py-2 rounded-md',
secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-900 px-4 py-2 rounded-md',
outline: 'border border-gray-300 hover:bg-gray-50 text-gray-700 px-4 py-2 rounded-md',
}
function Button({
variant = 'primary',
children,
...props
}: {
variant?: keyof typeof buttonVariants
children: React.ReactNode
} & React.ButtonHTMLAttributes<HTMLButtonElement>) {
return (
<button
className={buttonVariants[variant]}
{...props}
>
{children}
</button>
)
}📱 Responsive Design
tsx
function EventGrid({ events }: { events: Event[] }) {
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
{events.map(event => (
<EventCard key={event.id} event={event} />
))}
</div>
)
}🌙 Dark Mode Support
tsx
function ThemeToggle() {
const [isDark, setIsDark] = useState(false)
return (
<button
onClick={() => setIsDark(!isDark)}
className="p-2 rounded-lg bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white"
>
{isDark ? <SunIcon /> : <MoonIcon />}
</button>
)
}✨ Animation & Transitions
tsx
function AnimatedEventCard({ event }: { event: Event }) {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
whileHover={{ y: -5 }}
className="bg-white rounded-lg shadow-md p-6"
>
<h3 className="text-xl font-semibold">{event.title}</h3>
<p className="text-gray-600">{event.description}</p>
</motion.div>
)
}🧩 Common Patterns
🃏 Card Components
tsx
export default function EventCard({ event }: { event: Event }) {
return (
<div className="
bg-white
rounded-lg
shadow-md
hover:shadow-lg
transition-shadow
duration-200
overflow-hidden
">
{/* Event Image */}
{event.media.thumbnail && (
<div className="relative h-48 bg-gray-200">
<Image
src={event.media.thumbnail.url}
alt={event.title}
fill
className="object-cover"
/>
</div>
)}
{/* Event Content */}
<div className="p-6">
<div className="flex items-center justify-between mb-2">
<span className="
px-2 py-1
text-xs
font-medium
rounded-full
text-white
bg-primary-500
">
{event.eventType}
</span>
<span className="text-sm text-gray-500">
{event.date.toLocaleDateString()}
</span>
</div>
<h3 className="text-xl font-semibold text-gray-900 mb-2">
{event.title}
</h3>
<p className="text-gray-600 mb-4">
{event.description}
</p>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-500">
{event.venue.name}
</span>
{event.booking.bookable && (
<button className="
bg-primary-600
hover:bg-primary-700
text-white
px-4
py-2
rounded-md
transition-colors
duration-200
">
Book Now
</button>
)}
</div>
</div>
</div>
)
}🏗️ Layout Components
tsx
export default function PageLayout({ children }: { children: React.ReactNode }) {
return (
<div className="min-h-screen bg-gray-50">
{/* Header */}
<header className="bg-white shadow-sm border-b border-gray-200">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<Logo />
<Navigation />
</div>
</div>
</header>
{/* Main Content */}
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
{children}
</main>
{/* Footer */}
<footer className="bg-gray-800 text-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<FooterContent />
</div>
</footer>
</div>
)
}✨ Best Practices
- 🧩 Component Composition - Build complex UIs from simple components
- 🛠️ Utility Classes - Use TailwindCSS utilities instead of custom CSS
- 📱 Responsive Design - Mobile-first approach with responsive prefixes
- 🌙 Dark Mode - Support both light and dark themes
- ⚡ Performance - Minimize CSS bundle size with PurgeCSS
- 🎨 Consistency - Use design tokens for colors, spacing, and typography
