Back to catalog

tailwind-component-builder

Build Astro/React components with TailwindCSS patterns and utility classes

  • Category: discovered
  • Tags: github, community
  • Version: 1.0.0
  • Author: walid
  • Downloads: 0
  • Updated: 2025-11-22

Download the latest version (v1.0.0) from this page.

SKILL.md

---
name: tailwind-component-builder
description: Build Astro/React components with TailwindCSS patterns and utility classes
activation:
  keywords:
    - tailwind component
    - utility classes
    - tailwind patterns
    - @apply
  triggers:
    - "tailwind"
    - "@apply"
  auto_load_project: cv-astro
---

# Tailwind Component Builder

## What This Is

Build components with TailwindCSS 3.4 best practices:
- Utility-first approach
- `@apply` directive for reusable patterns
- Responsive design patterns
- Dark mode support (if needed)
- Component variants

**For**: CV_Astro project (TailwindCSS 3.4.1)

---

## When to Activate

Auto-activates when keywords detected:
- "tailwind component"
- "utility classes"
- "@apply pattern"

---

## TailwindCSS Patterns

### 1. Card Component

```astro
---
// src/components/Card.astro
interface Props {
  title: string;
  description: string;
  link?: string;
}

const { title, description, link } = Astro.props;
---

<article class="card">
  <h3 class="card-title">{title}</h3>
  <p class="card-description">{description}</p>
  {link && (
    <a href={link} class="card-link">
      Learn more →
    </a>
  )}
</article>

<style>
  .card {
    @apply bg-white rounded-lg shadow-md p-6 mb-4;
    @apply hover:shadow-xl transition-shadow duration-300;
  }

  .card-title {
    @apply text-2xl font-bold text-gray-900 mb-3;
  }

  .card-description {
    @apply text-gray-600 leading-relaxed mb-4;
  }

  .card-link {
    @apply inline-block text-blue-600 hover:text-blue-800;
    @apply font-medium transition-colors;
  }
</style>
```

---

### 2. Button Variants

```astro
---
// src/components/Button.astro
interface Props {
  variant?: 'primary' | 'secondary' | 'outline';
  size?: 'sm' | 'md' | 'lg';
  href?: string;
  type?: 'button' | 'submit';
}

const { variant = 'primary', size = 'md', href, type = 'button' } = Astro.props;
const Tag = href ? 'a' : 'button';
---

<Tag
  class:list={['btn', `btn-${variant}`, `btn-${size}`]}
  href={href}
  type={href ? undefined : type}
>
  <slot />
</Tag>

<style>
  .btn {
    @apply inline-flex items-center justify-center;
    @apply font-medium rounded-lg transition-all;
    @apply focus:outline-none focus:ring-2 focus:ring-offset-2;
  }

  /* Sizes */
  .btn-sm {
    @apply text-sm px-3 py-2;
  }

  .btn-md {
    @apply text-base px-4 py-2;
  }

  .btn-lg {
    @apply text-lg px-6 py-3;
  }

  /* Variants */
  .btn-primary {
    @apply bg-blue-600 text-white hover:bg-blue-700;
    @apply focus:ring-blue-500;
  }

  .btn-secondary {
    @apply bg-gray-600 text-white hover:bg-gray-700;
    @apply focus:ring-gray-500;
  }

  .btn-outline {
    @apply bg-transparent border-2 border-blue-600 text-blue-600;
    @apply hover:bg-blue-600 hover:text-white;
    @apply focus:ring-blue-500;
  }
</style>
```

**Usage**:
```astro
<Button variant="primary" size="lg">Click me</Button>
<Button variant="outline" href="/contact">Contact</Button>
```

---

### 3. Form Input

```astro
---
// src/components/FormInput.astro
interface Props {
  label: string;
  name: string;
  type?: string;
  placeholder?: string;
  required?: boolean;
  error?: string;
}

const {
  label,
  name,
  type = 'text',
  placeholder,
  required = false,
  error
} = Astro.props;
---

<div class="form-group">
  <label for={name} class="form-label">
    {label}
    {required && <span class="required">*</span>}
  </label>

  <input
    type={type}
    id={name}
    name={name}
    placeholder={placeholder}
    required={required}
    class:list={['form-input', error && 'form-input-error']}
  />

  {error && <p class="form-error">{error}</p>}
</div>

<style>
  .form-group {
    @apply mb-4;
  }

  .form-label {
    @apply block text-sm font-medium text-gray-700 mb-2;
  }

  .required {
    @apply text-red-500 ml-1;
  }

  .form-input {
    @apply w-full px-4 py-2 border border-gray-300 rounded-lg;
    @apply focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent;
    @apply transition-all;
  }

  .form-input-error {
    @apply border-red-500 focus:ring-red-500;
  }

  .form-error {
    @apply text-sm text-red-600 mt-1;
  }
</style>
```

---

### 4. Grid Layout

```astro
---
// src/components/ProjectGrid.astro
---

<div class="project-grid">
  <slot />
</div>

<style>
  .project-grid {
    @apply grid gap-6;
    @apply grid-cols-1 sm:grid-cols-2 lg:grid-cols-3;
  }
</style>
```

---

### 5. Responsive Navigation

```astro
---
// src/components/Navigation.astro
const navItems = [
  { label: 'Home', href: '/' },
  { label: 'About', href: '/about' },
  { label: 'Projects', href: '/projects' },
  { label: 'Contact', href: '/contact' }
];
---

<nav class="navigation">
  <div class="nav-container">
    <a href="/" class="nav-logo">Oriol Macías</a>

    <ul class="nav-menu">
      {navItems.map(item => (
        <li class="nav-item">
          <a href={item.href} class="nav-link">
            {item.label}
          </a>
        </li>
      ))}
    </ul>
  </div>
</nav>

<style>
  .navigation {
    @apply bg-white shadow-sm;
  }

  .nav-container {
    @apply max-w-7xl mx-auto px-4 py-4;
    @apply flex items-center justify-between;
  }

  .nav-logo {
    @apply text-2xl font-bold text-gray-900;
    @apply hover:text-blue-600 transition-colors;
  }

  .nav-menu {
    @apply hidden md:flex items-center space-x-8;
  }

  .nav-link {
    @apply text-gray-600 hover:text-blue-600;
    @apply font-medium transition-colors;
  }
</style>
```

---

## Responsive Patterns

### Mobile-First Approach

```css
/* Default (mobile) */
.container {
  @apply px-4 py-6;
}

/* Tablet */
@screen sm {
  .container {
    @apply px-6 py-8;
  }
}

/* Desktop */
@screen lg {
  .container {
    @apply px-8 py-12 max-w-7xl mx-auto;
  }
}
```

### Breakpoint Utilities

```html
<!-- Hide on mobile, show on desktop -->
<div class="hidden lg:block">Desktop only</div>

<!-- Show on mobile, hide on desktop -->
<div class="block lg:hidden">Mobile only</div>

<!-- Responsive grid -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
  <!-- Content -->
</div>
```

---

## Common Patterns

### Container

```css
.container {
  @apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
}
```

### Section Spacing

```css
.section {
  @apply py-12 sm:py-16 lg:py-20;
}
```

### Heading Hierarchy

```css
.heading-1 {
  @apply text-4xl sm:text-5xl lg:text-6xl font-bold;
}

.heading-2 {
  @apply text-3xl sm:text-4xl lg:text-5xl font-bold;
}

.heading-3 {
  @apply text-2xl sm:text-3xl lg:text-4xl font-semibold;
}
```

### Text Colors

```css
.text-primary {
  @apply text-gray-900;
}

.text-secondary {
  @apply text-gray-600;
}

.text-muted {
  @apply text-gray-500;
}

.text-accent {
  @apply text-blue-600;
}
```

---

## Best Practices

### ✅ DO

1. **Use @apply for reusable patterns**:
   ```css
   .btn {
     @apply px-4 py-2 rounded-lg font-medium transition-colors;
   }
   ```

2. **Mobile-first responsive design**:
   ```html
   <div class="text-sm sm:text-base lg:text-lg">
   ```

3. **Semantic class names**:
   ```css
   .card-title { /* Not .text-2xl-bold */ }
   ```

4. **Group related utilities**:
   ```html
   <div class="flex items-center justify-between">
   ```

### ❌ DON'T

1. **Don't inline all classes**:
   ```html
   <!-- ❌ Bad -->
   <div class="bg-white rounded-lg shadow-md p-6 mb-4 hover:shadow-xl transition-shadow duration-300 text-gray-900">

   <!-- ✅ Good -->
   <div class="card">
   <style>
     .card { @apply bg-white rounded-lg shadow-md p-6 mb-4 hover:shadow-xl transition-shadow; }
   </style>
   ```

2. **Don't create too many custom classes**:
   - Use @apply sparingly
   - Utility classes in HTML are OK for simple cases

3. **Don't forget responsive modifiers**:
   ```html
   <!-- ❌ Bad -->
   <div class="grid-cols-3">

   <!-- ✅ Good -->
   <div class="grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
   ```

---

## Quick Reference

| Pattern | Classes |
|---------|---------|
| **Container** | `max-w-7xl mx-auto px-4 sm:px-6 lg:px-8` |
| **Card** | `bg-white rounded-lg shadow-md p-6` |
| **Button** | `px-4 py-2 rounded-lg font-medium transition-colors` |
| **Grid** | `grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6` |
| **Flex** | `flex items-center justify-between` |
| **Text** | `text-gray-900 text-lg leading-relaxed` |

**Breakpoints**: `sm` (640px), `md` (768px), `lg` (1024px), `xl` (1280px)