Tailwind Avancé

Extraction de composants & Design System

Objectifs de la leçon

1. Utiliser @apply

Extraire des composants CSS réutilisables

2. Personnaliser tailwind.config

Couleurs, fonts, spacing custom

3. Design tokens

Système de design cohérent

4. Animations custom

animate-* et @keyframes

5. Introduction à Radix UI

Composants headless accessibles

Plan du cours

1

@apply : extraction de composants CSS

Quand et comment l'utiliser (et pourquoi ne pas en abuser)

2

Personnaliser tailwind.config

Couleurs du projet, fonts, spacing custom

3

Design tokens

Définir un système de design cohérent avec Tailwind

4

Animations built-in et custom

animate-spin, animate-pulse, animations personnalisées

5

Introduction à Radix UI

Primitives headless pour composants accessibles

Module 1

@apply : Extraction de composants

Quand et comment extraire des classes répétées

Le problème : Classes répétées

Vous avez le même bouton à 10 endroits différents...

<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">

Sauvegarder

</button>

...

<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">

Envoyer

</button>

... (x10)

Copier-coller = maintenance difficile. Si on veut changer le padding ?

La solution : @apply

Extraire les classes dans une classe CSS personnalisée

@layer components {

.btn-primary {

@apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded;

}

}

<button class="btn-primary">Sauvegarder</button>

<button class="btn-primary">Envoyer</button>

Une seule classe = maintenance centralisée

@layer components expliqué

Pourquoi @layer ?

Place vos styles dans la couche "components" de Tailwind

Permet de contrôler l'ordre de spécificité

Les 3 couches

base - reset CSS

components - vos classes

utilities - classes utilitaires

/* Tailwind v4 - dans votre fichier CSS */

@layer components {

.btn-primary { @apply ... }

.input-base { @apply ... }

}

Quand utiliser @apply ?

Cas valides

button - boutons répétés partout
input - champs de formulaire
card - composants très fréquents

À éviter

text-bold - utilisez font-bold
flex-center - utilisez flex items-center justify-center
container-custom - restez en utilities

Règle d'or : @apply uniquement pour les composants TRÈS répétés

Pourquoi ne pas abuser de @apply ?

Abuser de @apply = revenir au CSS classique

  • On réinvente BEM
  • Perte de la lisibilité immédiate
  • Allers-retours entre HTML et CSS
  • Plus difficile de personnaliser un cas unique

La philosophie Tailwind

  • Styles visibles directement dans le HTML
  • Pas de contexte à mémoriser
  • Personnalisation facile par exception
  • Refactoring local, pas global

En React, on extrait des composants, pas des classes CSS

Alternative en React : Extraire un composant

Au lieu de @apply, créez un composant réutilisable

function

Button

({ children, variant = 'primary' }) {

const variants = {

primary: 'bg-blue-500 hover:bg-blue-700 text-white',

secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-800',

};

return (

<button className={`

${variants[variant]} font-bold py-2 px-4 rounded

`}>

{children}

</button>

);

}

Plus flexible, plus maintenable, plus "React"

Module 2

Personnaliser tailwind.config

LA force de Tailwind pour les projets d'équipe

Tailwind v4 : Configuration CSS-first

Plus de tailwind.config.js - tout dans le CSS !

@import

"tailwindcss";

@theme {

--color-brand: #3b82f6;

--font-display: "Inter", sans-serif;

--spacing-18: 4.5rem;

}

v3 (JavaScript)

module.exports = { theme: { ... } }

v4 (CSS)

@theme { --color-*: ... }

Ajouter des couleurs custom

Suivre l'échelle 50-950 de Tailwind

@theme {

/* Couleur brand complète */

--color-brand-50: oklch(0.97 0.01 250);

--color-brand-100: oklch(0.94 0.02 250);

--color-brand-200: oklch(0.88 0.04 250);

...

--color-brand-900: oklch(0.35 0.10 250);

--color-brand-950: oklch(0.20 0.08 250);

}

Utilisation : bg-brand-500, text-brand-700

L'échelle 50-950 assure la cohérence avec les couleurs natives

Fonts et spacing personnalisés

Font families

@theme {

--font-display: "Inter", sans-serif;

--font-mono: "JetBrains Mono", monospace;

}

Usage: font-display

Spacing custom

@theme {

--spacing-18: 4.5rem; /* 72px */

--spacing-128: 32rem;

}

Usage: p-18, m-128

Piège : extend vs écraser

En v3, cette distinction était cruciale. En v4, c'est plus simple !

v3 - Écraser (dangereux)

module.exports = {

theme: {

colors: { blue: '#3b82f6' }

// Remplace TOUTES les couleurs!

}

}

v3 - extend (correct)

module.exports = {

theme: {

extend: {

colors: { brand: '...' }

}

}

}

v4 : @theme ajoute automatiquement, pas besoin de extend !

Exemple complet : Design system

@import

"tailwindcss";

@theme {

/* Brand colors */

--color-primary-500: oklch(0.6 0.2 250);

--color-primary-700: oklch(0.45 0.18 250);

/* Typography */

--font-sans: "Inter", system-ui, sans-serif;

--font-mono: "JetBrains Mono", monospace;

/* Custom spacing */

--spacing-section: 6rem;

/* Animations */

--animate-fade-in: fade-in 0.5s ease-out;

}

Un fichier, toutes vos personnalisations

Module 3

Design Tokens

Un système de design cohérent avec Tailwind

Qu'est-ce qu'un design token ?

Une valeur nommée qui représente une décision de design

--color-primary

#3b82f6

--spacing-md

1rem (16px)

--radius-lg

0.5rem

Les tokens créent un langage commun entre designers et développeurs

Design tokens avec Tailwind v4

Le @theme block est votre source de vérité

@theme {

/* Couleurs sémantiques */

--color-bg-primary: var(--color-slate-50);

--color-text-primary: var(--color-slate-900);

--color-accent: var(--color-brand-500);

/* Spacing tokens */

--space-xs: 0.25rem;

--space-sm: 0.5rem;

--space-md: 1rem;

--space-lg: 2rem;

}

Usage: bg-bg-primary, text-text-primary

Avantages pour l'équipe

Cohérence visuelle

Même couleur "primary" partout

Maintenance facile

Changer une valeur = tout le site mis à jour

Documentation vivante

Le code EST la documentation

Collaboration design/dev

Figma tokens = CSS tokens

Outils comme Style Dictionary ou Tokens Studio synchronisent Figma et code

Module 4

Animations Custom

Built-in et animations personnalisées

Animations intégrées

animate-spin

Pour les loaders

animate-pulse

Pour les états de chargement

animate-bounce

Pour attirer l'attention

animate-ping

Pour les notifications

Créer une animation custom

Définir @keyframes et l'utiliser dans @theme

@keyframes

fade-in

{

from { opacity: 0; transform: translateY(10px); }

to { opacity: 1; transform: translateY(0); }

}

@theme {

--animate-fade-in: fade-in 0.5s ease-out;

}

<div class="animate-fade-in">

Ce contenu apparaît en douceur

</div>

Contrôler les animations

Duration

duration-150

duration-300

duration-500

duration-1000

Timing

ease-linear

ease-in

ease-out

ease-in-out

Delay

delay-150

delay-300

delay-500

Iteration

animate-once

animate-twice

animate-infinite

<div class="animate-bounce duration-1000 ease-in-out animate-infinite">

Exemple : Animation de feedback

@keyframes

shake

{

0%, 100% { transform: translateX(0); }

25% { transform: translateX(-5px); }

75% { transform: translateX(5px); }

}

@theme {

--animate-shake: shake 0.3s ease-in-out;

}

// Utilisation pour un input invalide

<input class="border-red-500 animate-shake" />

Feedback visuel instantané pour l'utilisateur

Module 5

Introduction à Radix UI

Composants headless pour l'accessibilité

Qu'est-ce qu'un composant headless ?

Comportement + Accessibilité, SANS style

Radix UI fournit

  • Comportement (open/close)
  • Accessibilité (ARIA)
  • Keyboard navigation
  • Focus management

Vous fournissez

  • Le style (Tailwind)
  • L'animation
  • Le layout
  • L'identité visuelle

Combinaison parfaite : Radix = fonctionnalité, Tailwind = style

Exemple : Dialog Radix + Tailwind

import

{ Dialog } from '@radix-ui/react-dialog';

<Dialog.Root>

<Dialog.Trigger className="btn-primary">

Ouvrir

</Dialog.Trigger>

<Dialog.Portal>

<Dialog.Overlay className="bg-black/50 fixed inset-0" />

<Dialog.Content className="bg-white p-6 rounded-lg shadow-xl fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">

<Dialog.Title className="text-xl font-bold">Titre</Dialog.Title>

<p className="text-slate-600 mt-2">Contenu du dialog</p>

</Dialog.Content>

</Dialog.Portal>

</Dialog.Root>

Radix gère l'accessibilité, vous contrôlez 100% du visuel

Composants Radix disponibles

Dialog

Modales

Dropdown

Menus déroulants

Tabs

Onglets

Tooltip

Infobulles

Popover

Popups

Select

Listes déroulantes

Accordion

Accordéons

Switch

Toggle

Slider

Curseurs

Tous accessibles par défaut, prêts à être stylés avec Tailwind

Pièges courants à éviter

Utiliser @apply pour TOUT

Ça revient à écrire du CSS classique

Solution : @apply uniquement pour composants très répétés

Couleurs custom sans échelle 50-950

Impossible d'utiliser bg-brand-100 ou text-brand-700

Solution : Définir l'échelle complète ou utiliser les couleurs natives

Confondre extend et écraser (v3)

Perdre toutes les valeurs par défaut

Solution : En v4, @theme ajoute automatiquement

Installer Radix sans comprendre le concept

Attendre des styles prêts à l'emploi

Solution : Radix = comportement, vous = style

À retenir !

@apply

Extraction CSS

Pour composants répétés

@theme

Personnalisation v4

Couleurs, fonts, spacing

Design tokens

Système cohérent

Langage commun

Radix UI

Headless components

Accessibilité native

Préview React : on extraira des composants, pas des classes CSS

Questions ?

Tailwind avancé maîtrisé !

Prochaine étape : Pratiquer avec un vrai projet