Files
Portfolio-Codex/docs/stories/1.2.configuration-tailwind.md

11 KiB

Story 1.2: Configuration de Tailwind CSS avec CLI

Status

Ready for Dev

Story

As a développeur, I want configurer Tailwind CSS avec le CLI et le build optimisé, so that je bénéficie d'un CSS performant avec purge automatique.

Acceptance Criteria

  1. Node.js et npm sont utilisés uniquement pour le build (pas en production)
  2. tailwind.config.js est créé avec les chemins des fichiers PHP à scanner
  3. Le fichier assets/css/input.css contient les directives Tailwind (@tailwind base, components, utilities)
  4. La commande npm run build génère assets/css/output.css minifié
  5. Une commande npm run dev permet le développement en temps réel (watch)
  6. Le fichier CSS généré fait moins de 50kb après purge
  7. La palette de couleurs personnalisée est configurée (thème sombre)

Tasks / Subtasks

  • [] Task 1 : Initialiser npm et installer les dépendances (AC: 1)

    • [] Créer package.json avec npm init -y
    • [] Installer Tailwind CSS : npm install -D tailwindcss postcss autoprefixer
    • [] Vérifier que node_modules/ est dans .gitignore
  • [] Task 2 : Créer la configuration Tailwind (AC: 2, 7)

    • [] Créer tailwind.config.js avec les chemins PHP à scanner
    • [] Configurer la palette de couleurs personnalisée (primary, background, surface, text, etc.)
    • [] Configurer les polices (Inter, JetBrains Mono)
    • [] Configurer les tailles de texte personnalisées
    • [] Configurer les ombres personnalisées
  • [] Task 3 : Créer le fichier CSS source (AC: 3)

    • [] Créer assets/css/input.css
    • [] Ajouter les directives @tailwind base, @tailwind components, @tailwind utilities
    • [] Ajouter les styles de base dans @layer base
    • [] Ajouter les composants réutilisables dans @layer components (btn, card, input, badge, etc.)
    • [] Ajouter les animations dans @layer utilities
  • [] Task 4 : Configurer PostCSS (AC: 1)

    • [] Créer postcss.config.js avec tailwindcss et autoprefixer
  • [] Task 5 : Configurer les scripts npm (AC: 4, 5)

    • [] Ajouter le script build dans package.json
    • [] Ajouter le script dev (watch) dans package.json
    • [] Tester les deux scripts
  • [] Task 6 : Valider la taille du CSS (AC: 6)

    • [] Exécuter npm run build
    • [] Vérifier que output.css < 50kb (6,4 Ko)
    • [] Vérifier que le purge fonctionne correctement

Dev Notes

Dépendances npm (devDependencies uniquement)

{
  "devDependencies": {
    "tailwindcss": "^3.4.0",
    "postcss": "^8.4.0",
    "autoprefixer": "^10.4.0"
  }
}

Configuration tailwind.config.js Complète

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './*.php',
    './pages/**/*.php',
    './templates/**/*.php',
    './assets/js/**/*.js'
  ],
  theme: {
    extend: {
      colors: {
        primary: {
          DEFAULT: '#FA784F',
          light: '#FB9570',
          dark: '#E5623A',
        },
        background: '#17171F',
        surface: {
          DEFAULT: '#1E1E28',
          light: '#2A2A36',
        },
        border: '#3A3A48',
        text: {
          primary: '#F5F5F7',
          secondary: '#A1A1AA',
          muted: '#71717A',
        },
        success: '#34D399',
        warning: '#FBBF24',
        error: '#F87171',
        info: '#60A5FA',
      },
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif'],
        mono: ['JetBrains Mono', 'monospace'],
      },
      fontSize: {
        'display': ['2.5rem', { lineHeight: '1.2', fontWeight: '700' }],
        'heading': ['2rem', { lineHeight: '1.3', fontWeight: '600' }],
        'subheading': ['1.5rem', { lineHeight: '1.4', fontWeight: '600' }],
        'body': ['1rem', { lineHeight: '1.6', fontWeight: '400' }],
        'small': ['0.875rem', { lineHeight: '1.5', fontWeight: '400' }],
      },
      maxWidth: {
        'content': '1280px',
      },
      boxShadow: {
        'card': '0 4px 20px rgba(0, 0, 0, 0.25)',
        'card-hover': '0 10px 40px rgba(0, 0, 0, 0.3)',
        'input-focus': '0 0 0 3px rgba(250, 120, 79, 0.2)',
      },
    },
  },
  plugins: [],
}

Configuration postcss.config.js

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  }
}

Contenu assets/css/input.css

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  html {
    @apply scroll-smooth;
  }

  body {
    @apply bg-background text-text-primary font-sans antialiased;
  }

  h1 { @apply text-display text-text-primary; }
  h2 { @apply text-heading text-text-primary; }
  h3 { @apply text-subheading text-text-primary; }
  p { @apply text-body text-text-secondary; }

  a {
    @apply text-primary hover:text-primary-light transition-colors duration-150;
  }

  :focus-visible {
    @apply outline-none ring-2 ring-primary ring-offset-2 ring-offset-background;
  }

  ::selection {
    @apply bg-primary/30 text-text-primary;
  }
}

@layer components {
  /* Container */
  .container-content {
    @apply max-w-content mx-auto px-4 sm:px-6 lg:px-8;
  }

  /* Boutons */
  .btn {
    @apply inline-flex items-center justify-center gap-2
           px-6 py-3 font-medium rounded-lg
           transition-all duration-150
           focus:outline-none focus:ring-2 focus:ring-offset-2
           focus:ring-offset-background
           disabled:opacity-50 disabled:cursor-not-allowed;
  }

  .btn-primary {
    @apply btn bg-primary text-background
           hover:bg-primary-light active:bg-primary-dark
           focus:ring-primary;
  }

  .btn-secondary {
    @apply btn border-2 border-primary text-primary bg-transparent
           hover:bg-primary hover:text-background
           focus:ring-primary;
  }

  .btn-ghost {
    @apply btn text-primary bg-transparent
           hover:text-primary-light hover:bg-surface-light
           focus:ring-primary;
  }

  /* Badges */
  .badge {
    @apply inline-flex items-center px-2.5 py-1
           text-xs font-medium rounded
           bg-surface-light text-text-secondary;
  }

  .badge-primary {
    @apply bg-primary/20 text-primary;
  }

  .badge-muted {
    @apply bg-border text-text-muted;
  }

  /* Cartes */
  .card {
    @apply bg-surface rounded-lg overflow-hidden
           border border-border/50
           transition-all duration-200;
  }

  .card-interactive {
    @apply card cursor-pointer
           hover:-translate-y-1 hover:shadow-card-hover
           hover:border-border;
  }

  .card-body {
    @apply p-4 sm:p-6;
  }

  /* Inputs */
  .input {
    @apply w-full px-4 py-3
           bg-surface border border-border rounded-lg
           text-text-primary placeholder-text-muted
           transition-all duration-150
           focus:outline-none focus:border-primary focus:shadow-input-focus;
  }

  .input-error {
    @apply border-error focus:border-error
           focus:shadow-[0_0_0_3px_rgba(248,113,113,0.2)];
  }

  .textarea {
    @apply input min-h-[150px] resize-y;
  }

  .label {
    @apply block text-sm font-medium text-text-secondary mb-2;
  }

  .label-required::after {
    content: '*';
    @apply text-error ml-1;
  }

  .error-message {
    @apply text-sm text-error mt-1.5 flex items-center gap-1;
  }

  /* Sections */
  .section {
    @apply py-16 sm:py-24;
  }

  .section-header {
    @apply text-center mb-12;
  }

  .section-title {
    @apply text-heading mb-4;
  }

  .section-subtitle {
    @apply text-body text-text-secondary max-w-2xl mx-auto;
  }

  /* Témoignage */
  .testimonial {
    @apply bg-surface-light rounded-lg p-6 border-l-4 border-primary;
  }

  /* Breadcrumb */
  .breadcrumb {
    @apply flex items-center gap-2 text-sm text-text-muted;
  }

  .breadcrumb-link {
    @apply text-text-secondary hover:text-primary transition-colors;
  }

  .breadcrumb-current {
    @apply text-text-primary;
  }
}

@layer utilities {
  .animate-fade-in {
    animation: fadeIn 0.6s ease-out forwards;
  }

  .animate-fade-in-up {
    animation: fadeInUp 0.6s ease-out forwards;
  }

  .animation-delay-100 { animation-delay: 100ms; }
  .animation-delay-200 { animation-delay: 200ms; }
  .animation-delay-300 { animation-delay: 300ms; }

  .aspect-thumbnail {
    aspect-ratio: 16 / 9;
  }
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Accessibilité - Réduction de mouvement */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Scripts package.json

{
  "scripts": {
    "dev": "tailwindcss -i ./assets/css/input.css -o ./assets/css/output.css --watch",
    "build": "tailwindcss -i ./assets/css/input.css -o ./assets/css/output.css --minify"
  }
}

Palette de Couleurs (Thème Sombre)

Couleur Hex Usage
Primary #FA784F CTA, liens, accents
Primary Light #FB9570 Hover
Primary Dark #E5623A Active/pressed
Background #17171F Fond de page
Surface #1E1E28 Cartes, navbar
Surface Light #2A2A36 Hover cartes
Border #3A3A48 Bordures
Text Primary #F5F5F7 Titres
Text Secondary #A1A1AA Texte secondaire
Text Muted #71717A Placeholders

Testing

Validation Manuelle

  • npm install s'exécute sans erreur
  • npm run build génère output.css
  • npm run dev lance le watch mode
  • Le fichier output.css < 50kb
  • Les classes Tailwind fonctionnent dans le navigateur

Commandes de Test

# Installer les dépendances
npm install

# Build production
npm run build

# Vérifier la taille du CSS
ls -lh assets/css/output.css

# Lancer le watch pour le dev
npm run dev

Test Visuel

Créer un fichier HTML temporaire pour tester les classes :

  • .btn-primary → bouton orange
  • .bg-background → fond sombre #17171F
  • .text-primary → texte orange
  • .card → carte avec fond surface

Change Log

Date Version Description Author
2026-01-22 0.1 Création initiale de la story Sarah (PO)

Dev Agent Record

Agent Model Used

Claude Opus 4.5 (claude-opus-4-5-20251101)

Debug Log References

À compléter par le dev agent

Completion Notes List

  • Package.json mis à jour (v2.0.0) avec scripts dev/build Tailwind
  • Dépendances installées : tailwindcss ^3.4.0, postcss ^8.4.0, autoprefixer ^10.4.0
  • tailwind.config.js créé avec palette couleurs sombre, polices Inter/JetBrains Mono
  • input.css complet avec @layer base, components (btn, card, input, badge, etc.), utilities (animations)
  • postcss.config.js configuré
  • Build validé : output.css = 6,4 Ko (< 50 Ko requis)
  • Warning normal : pas encore de fichiers PHP utilisant les classes

File List

Fichier Action
package.json Modifié
package-lock.json Modifié
tailwind.config.js Créé
postcss.config.js Créé
assets/css/input.css Créé
assets/css/output.css Généré

QA Results

À compléter par le QA agent