Tailwind CSS et shadcn/ui
Des boutons, des cartes et des formulaires de qualité professionnelle, dont vous possédez le code.

Objectifs de la séance
- comprendre le principe de Tailwind CSS (des classes utilitaires) ;
- comprendre l'approche de shadcn/ui : des composants copiés dans votre projet ;
- installer Tailwind et configurer l'alias
@/; - initialiser shadcn/ui et ajouter des composants ;
- utiliser
Button,Card,Input,LabeletAlert; - migrer l'application sans casser les tests.
Petite vérification
Avant de commencer, vérifiez si vous savez...
- lancer
npm run verifieret lire les trois étapes qui s'exécutent - chercher dans
dist/assets/le textene-doit-jamais-apparaitreet dire pourquoi il est absent - dire pourquoi une variable
VITE_ne doit jamais contenir de mot de passe
📌 Réponse attendue
Notions théoriques
Tailwind CSS : le style par classes utilitaires
Jusqu'ici, vous écriviez des règles dans index.css (.carte { padding: 16px; ... }) puis vous appliquiez la classe. Avec Tailwind CSS, on applique directement de petites classes qui font chacune une seule chose :
<h1 className="text-3xl font-bold tracking-tight">Quiz Cyber</h1>
<div className="mx-auto max-w-xl space-y-6 p-6">...</div>
| Classe | Effet |
|---|---|
text-3xl | grande taille de texte |
font-bold | texte en gras |
p-6 | espace intérieur (padding) |
mx-auto | centrage horizontal |
max-w-xl | largeur maximale |
space-y-6 | espace vertical entre les enfants |
text-muted-foreground | couleur de texte atténuée (fournie par shadcn/ui) |
Tailwind ne garde dans le fichier final que les classes réellement utilisées : le CSS reste léger.
shadcn/ui : des composants que vous possédez
shadcn/ui n'est pas une bibliothèque qu'on installe et qu'on importe comme les autres. C'est une collection de composants que l'outil en ligne de commande copie dans votre projet, dans le dossier src/components/ui/. Vous obtenez du vrai code, que vous pouvez lire et modifier.
| Bibliothèque classique | shadcn/ui |
|---|---|
Composants cachés dans node_modules/ | Composants copiés dans votre src/ |
| Personnalisation limitée aux options prévues | Modification libre du code |
| Mise à jour imposée | Vous décidez quand mettre à jour |
Les composants s'appuient sur Tailwind pour le style et sur une bibliothèque de composants accessibles (gestion du clavier, des lecteurs d'écran...) pour le comportement.
La fonction cn et les variantes
Deux outils reviennent dans tous les composants générés :
cn(...)(fichiersrc/lib/utils.ts) assemble des classes en gérant les conflits :cn("p-2", condition && "p-4");- les variantes : un
Buttonacceptevariant="outline","secondary","ghost","destructive","link"etsize="sm","lg"...
<Button>Commencer</Button>
<Button variant="outline">Règles du jeu</Button>
<Button variant="destructive" size="sm">Supprimer</Button>
Installer Tailwind CSS avec Vite
npm install tailwindcss @tailwindcss/vite
- dans
vite.config.ts, on ajoute le plugintailwindcss()et un alias@qui désigne le dossiersrc; - dans
src/index.css, la première ligne active Tailwind :@import "tailwindcss";.
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { fileURLToPath } from "node:url";
import { defineConfig } from "vitest/config";
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
test: {
environment: "jsdom",
setupFiles: "./src/setupTests.ts",
},
});
TypeScript doit connaître le même alias. On l'ajoute dans deux fichiers : tsconfig.json et tsconfig.app.json.
{
"files": [],
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }],
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}
Dans tsconfig.app.json, ajoutez la même section "paths" à l'intérieur de compilerOptions (par exemple après "noEmit": true,).
L'alias permet d'écrire import { Button } from "@/components/ui/button" au lieu de "../../components/ui/button".
Initialiser shadcn/ui
npx shadcn@latest init
L'outil pose quelques questions (acceptez les choix par défaut) puis :
- crée
components.json(sa configuration) ; - installe les dépendances nécessaires ;
- ajoute à
src/index.cssles variables de couleurs (--primary,--background...) ; - crée
src/lib/utils.ts(la fonctioncn) et un premier composantbutton.tsx.
Pour ajouter d'autres composants :
npx shadcn@latest add card input label alert
Une commande qui copie du code dans votre projet modifie vos fichiers. Faites toujours un commit Git avant (git status doit être propre), puis regardez avec git diff ce qui a changé. C'est la meilleure façon de comprendre ce que fait l'outil.
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Votre mission : installer Tailwind et shadcn/ui, puis remplacer tout le style maison du quiz. Commencez par un commit Git de l'état actuel.
Étape 1 — Installer Tailwind CSS
Installez les paquets. Remplacez ensuite tout le contenu de src/index.css par la seule ligne qui active Tailwind (les anciennes règles .carte, button... ne serviront plus).
Mélanger de vieilles règles globales (button { ... }) avec des composants shadcn/ui produirait des conflits visuels difficiles à comprendre. On supprime l'ancien style avant de migrer.
Étape 2 — Configurer Vite et TypeScript
Modifiez vite.config.ts, tsconfig.json et tsconfig.app.json (voir « Notions théoriques »). Complétez l'alias.
L'alias doit être déclaré pour Vite (qui assemble le code) et pour TypeScript (qui le vérifie). Si l'un des deux manque, soit l'application plante, soit l'éditeur souligne les imports en rouge.
Étape 3 — Initialiser shadcn/ui et ajouter les composants
Parcourez button.tsx : vous y reconnaissez les props typées, la destructuration, className et la fonction cn. Il n'y a rien de magique. Si npm run lint signale un avertissement sur un fichier de components/ui/, c'est un détail du code généré (il concerne le rechargement à chaud), sans conséquence ici.
Étape 4 — La mise en page et l'en-tête
Supprimez les composants devenus inutiles (Carte.tsx et CarteQuestion.tsx). Dans App.tsx, entourez l'application d'un conteneur centré ; dans EnTete.tsx, remplacez les anciennes classes.
Le conteneur centré se trouve dans App, une seule fois : les pages n'ont plus à se soucier de la largeur de l'écran.
Étape 5 — Le formulaire avec Card, Label, Input et Alert
Réécrivez FormulaireDemarrage.tsx avec les composants shadcn/ui. La logique (états, validation) ne change pas.
Le composant Alert porte déjà role="alert" : les lecteurs d'écran annoncent le message, et le test getByRole("alert") du tutoriel 5 continue de fonctionner sans modification.
Étape 6 — Les réponses, la partie et le résultat
Réécrivez Partie.tsx, Resultat.tsx et les messages d'erreur des pages. Complétez les classes qui colorent la correction.
Un lien de navigation reste un Link (une vraie adresse, utilisable avec le clavier et le clic droit) : on lui applique simplement l'apparence d'un bouton avec buttonVariants(). Un <Button> qui ferait navigate() perdrait ces avantages.
📌 Une solution
Ce qu'il faut retenir
| Notion | Résumé |
|---|---|
| Tailwind CSS | Style par petites classes utilitaires (p-6, font-bold), appliquées avec className. |
| shadcn/ui | Composants copiés dans src/components/ui/ : du code que vous possédez et pouvez modifier. |
cn et variantes | cn assemble les classes ; variant et size choisissent l'apparence d'un composant. |
Alias @/ | À déclarer pour Vite et pour TypeScript. |
| Avant de lancer l'outil | Commit Git, puis git diff pour comprendre ce qui a changé. |
| Migration | Garder label, rôles et textes : les tests continuent de passer. |
Aperçu de la prochaine séance
Votre interface est soignée. Dans la dernière séance, vous allez utiliser le composant Dialog pour afficher une fenêtre « Règles du jeu », comprendre ce qu'une bibliothèque de composants accessibles fait à votre place (focus, clavier, lecteurs d'écran), et la tester.