Aller au contenu principal

Tailwind CSS et shadcn/ui

Des boutons, des cartes et des formulaires de qualité professionnelle, dont vous possédez le code.

shadcn/ui

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, Label et Alert ;
  • migrer l'application sans casser les tests.

Petite vérification​

Avant de commencer, vérifiez si vous savez...

  1. lancer npm run verifier et lire les trois étapes qui s'exécutent
  2. chercher dans dist/assets/ le texte ne-doit-jamais-apparaitre et dire pourquoi il est absent
  3. 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>
ClasseEffet
text-3xlgrande taille de texte
font-boldtexte en gras
p-6espace intérieur (padding)
mx-autocentrage horizontal
max-w-xllargeur maximale
space-y-6espace vertical entre les enfants
text-muted-foregroundcouleur 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 classiqueshadcn/ui
Composants cachés dans node_modules/Composants copiés dans votre src/
Personnalisation limitée aux options prévuesModification libre du code
Mise à jour imposéeVous 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(...) (fichier src/lib/utils.ts) assemble des classes en gérant les conflits : cn("p-2", condition && "p-4") ;
  • les variantes : un Button accepte variant="outline", "secondary", "ghost", "destructive", "link" et size="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
  1. dans vite.config.ts, on ajoute le plugin tailwindcss() et un alias @ qui désigne le dossier src ;
  2. dans src/index.css, la première ligne active Tailwind : @import "tailwindcss";.
vite.config.ts
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.

tsconfig.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.css les variables de couleurs (--primary, --background...) ;
  • crée src/lib/utils.ts (la fonction cn) et un premier composant button.tsx.

Pour ajouter d'autres composants :

npx shadcn@latest add card input label alert
Lire avant de lancer

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​


Que signifie la classe Tailwind p-6 ?


Où shadcn/ui place-t-il le code des composants ?


À quoi sert la fonction cn ?


Comment affiche-t-on un bouton au contour seulement avec shadcn/ui ?


Pourquoi faire un commit Git avant npx shadcn@latest add ?


Que permet l'alias @ configuré dans vite.config.ts et tsconfig ?



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).


Bonne pratique - Repartir d'un CSS propre

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.


Bonne pratique - Un alias, deux configurations

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​


Bonne pratique - Lire le code généré

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.


Bonne pratique - La mise en page dans un seul composant

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.


Bonne pratique - Le composant Alert annonce l'erreur

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.


Bonne pratique - Un lien qui ressemble à un bouton

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​

NotionRésumé
Tailwind CSSStyle par petites classes utilitaires (p-6, font-bold), appliquées avec className.
shadcn/uiComposants copiés dans src/components/ui/ : du code que vous possédez et pouvez modifier.
cn et variantescn assemble les classes ; variant et size choisissent l'apparence d'un composant.
Alias @/À déclarer pour Vite et pour TypeScript.
Avant de lancer l'outilCommit Git, puis git diff pour comprendre ce qui a changé.
MigrationGarder 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.