Design System·COMPONENTS · REACT
Component Library Builder
Obtiens des composants React accessibles avec tous leurs états (hover, focus, loading, error), prêts pour Tailwind.
Télécharger SKILL.md
~/.claude/skills/component-library-builder/SKILL.mdInstallation en 30 secondes
mkdir -p ~/.claude/skills/component-library-builder
curl -o ~/.claude/skills/component-library-builder/SKILL.md \
https://xavierguiter.com/claude-skills/component-library-builder/SKILL.md
# relance Claude Code, le skill est prêtComponent Library Builder
Tu livres chaque composant de façon à ce que personne n'ait besoin de rouvrir le fichier : tous les états présents, toutes les props typées, aucune surprise.
Quand l'utiliser
- Tu as besoin d'un nouveau composant (Button, Input, Modal, Dropdown, Tabs, Toast, Combobox).
- Un composant existant n'a pas d'état loading, d'état erreur ou de navigation clavier.
- Tu veux extraire la logique d'un composant pour la réutiliser ailleurs.
- Tu montes une bibliothèque de composants pour un projet Next.js + Tailwind.
Ce que le skill produit
- Le composant en TypeScript, stylé avec Tailwind et les variables CSS du design system.
- Un hook headless (
useX) quand le composant a un état, un clavier ou un focus à gérer. - Une matrice variantes x états documentée et couverte dans Storybook.
- Des tests : rendu, clavier, accessibilité (
axe-core), comportements limites. - Un barrel export et une courte doc d'usage (props, à faire / à ne pas faire).
Méthode
- Définis le rôle du composant en une phrase et ses non-objectifs.
- Cherche le pattern WAI-ARIA correspondant (button, dialog, combobox, tabs, menu) et note le comportement clavier attendu.
- Écris l'API : props typées, valeurs par défaut, 3 variantes maximum,
classNameetrefacceptés. - Écris le hook headless (état, clavier, focus), puis le composant stylé qui le compose.
- Applique chaque état via les tokens, jamais avec des couleurs en dur.
- Écris les stories (une par variante, une par état) et les tests.
- Vérifie la checklist, puis livre avec un exemple d'usage.
Matrice d'états
default: rendu de repos.hover: changement léger de fond ou de bordure, jamais seul porteur d'information.focus-visible: anneau de 2 px, décalé de 2 px, contraste 3:1 contre le fond.active: retour visuel au clic (fond plus sombre ouscale(0.98)).disabled: attributdisablednatif, opacité autour de 0.5, pas de hover.loading: interaction bloquée,aria-busy="true", largeur conservée, spinner.error: borduredanger, message relié pararia-describedby,aria-invalid="true".
Conventions de code
- HTML sémantique d'abord (
button,label,dialog), ARIA seulement pour combler les manques. forwardRef(ourefen prop sous React 19) etclassNamefusionnée aveccn()(clsx + tailwind-merge).- Variantes gérées avec
cvaou un objet de classes typé, pas de conditions imbriquées. - Couleurs via variables :
bg-[var(--accent)]ou une clé Tailwind mappée sur la variable. - Composants interactifs marqués
"use client", le reste reste en composant serveur. - Transitions de 150 à 250 ms avec les courbes des tokens, coupées sous
prefers-reduced-motion. - Cibles tactiles de 44 x 44 px minimum. Bouton icône toujours avec
aria-label.
Structure de fichiers
components/ui/Button/
Button.tsx (composant stylé)
useButton.ts (logique headless, si état)
Button.stories.tsx (variantes x états)
Button.test.tsx (unitaires + a11y)
index.ts (barrel export)Checklist avant livraison
- Les 7 états sont implémentés et visibles dans Storybook.
- Navigation clavier complète : Tab, Enter, Space, Escape, flèches si pertinent.
- Focus visible sur
:focus-visible, jamais supprimé. - Modal et menu : focus piégé à l'ouverture, rendu à l'élément déclencheur à la fermeture.
- Test
axe-coresans violation sur le rendu par défaut. - Aucune couleur, taille ou durée en dur.
- Props typées, valeurs par défaut documentées,
refetclassNametransmis. - Rendu correct en clair et en sombre.
À éviter
- Un
divaveconClickà la place d'unbutton. outline: nonesans anneau de focus de remplacement.- Plus de 3 variantes, ou des props booléennes qui se contredisent (
primaryetghostà la fois). - Un état loading qui change la largeur du bouton et fait sauter la mise en page.
- Mettre des appels API ou de la logique métier dans un composant de la bibliothèque.
- Copier-coller un composant pour une variante au lieu de l'étendre.
Exemple
Spec de <Button> :
type ButtonProps = {
variant?: "primary" | "secondary" | "ghost"; // défaut "primary"
size?: "sm" | "md" | "lg"; // 32, 40, 48 px de haut
loading?: boolean; // aria-busy, spinner, largeur conservée
disabled?: boolean;
leftIcon?: React.ReactNode;
className?: string;
} & React.ButtonHTMLAttributes<HTMLButtonElement>;Test clé : loading rend le bouton non cliquable, aria-busy="true", et sa largeur ne change pas.
Prompts de démarrage
- "Construis un Combobox : options asynchrones, navigation clavier, conforme WAI-ARIA."
- "Ajoute un état loading à
<Button>avec spinner et largeur conservée." - "Extrais la logique de
<Modal>dans un hookuseModal()réutilisable, avec focus trap." - "Crée un composant Input avec label, message d'aide, état erreur et variante avec icône."
- "Audite les composants de components/ui : liste les états manquants et les problèmes d'accessibilité."
Skill suivant