Skip to content

🎨 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

  1. 🧩 Component Composition - Build complex UIs from simple components
  2. 🛠️ Utility Classes - Use TailwindCSS utilities instead of custom CSS
  3. 📱 Responsive Design - Mobile-first approach with responsive prefixes
  4. 🌙 Dark Mode - Support both light and dark themes
  5. ⚡ Performance - Minimize CSS bundle size with PurgeCSS
  6. 🎨 Consistency - Use design tokens for colors, spacing, and typography

Released under the MIT License.