Intégrer un Design System avec Reactjs, Nextjs, TailwindCSS et CVA
Un Design System se doit d’être robuste, il constitue le coeur d’une application. Il est indispensable et représente les fondations du projet.
Dans cet article, nous allons voir comment intégrer proprement un Design System en faisant face aux problématiques classiques qu’on peut rencontrer en utilisant des outils modernes.
Découvrons donc CVA (Class Variance Authority), qui va nous permettre de construire ces bases, dans une stack classique mais moderne : NextJs, avec Typescript et TailwindCSS.
Pourquoi CVA ?
Nous allons utiliser l’exemple des boutons, composant indispensable du Design System, qui présente parfois une certaine complexité.
Intégration d'un bouton dans un Design System
Pour créer un bouton facilement réutilisable, il faut prendre en compte ses différents variants, comme par exemple :
- Ses différents intents : primary secondary ghost
- Ses différentes tailles : sm md lg
Création du composant
Intégrer un bouton avec notre stack, sans CVA, nous oblige à créer différents objets, contenant des class tailwind, que nous utilisons selon les props. De plus, nous faisons appel à tailwind-merge pour gérer les class dynamiques.
Bien que nous ayons un composant aux apparences solides, il présente plusieurs problèmes.
Par exemple, si je souhaite utiliser mon bouton pour afficher des icons, je veux qu’il soit rond peu importe sa taille. Ça devient rapidement verbeux et compliqué.
Pour résumer :
- il faut manuellement ajouter des props pour chacun de nos objets.
- il faut manuellement ajouter les types qui correspondent.
- il faut gérer certains cas plus complexes manuellement (comme les icons).
- les composants n’ont aucune cohérence, on déclare les variants différemment à chaque fois.
C’est là qu’entre en jeu CVA.
CVA (Class Variance Authority), c'est quoi ?
CVA est une librairie créée spécifiquement pour nous faciliter la tâche lorsque l’on intègre des composants de notre Design System.
“ Creating variants with the "traditional" CSS approach can become an arduous task; manually matching classes to props and manually adding types. ”
Plus de redondance, une meilleure cohérence entre nos composants, une meilleure lisibilité de l’intégration et des variants différents. CVA apporte une robustesse qui devient indispensable à la création de nos composants.
Création d’un composant avec CVA
Reprenons l’exemple de notre bouton. Nous souhaitons un bouton avec 3 intents, 3 tailles différentes, qui puisse facilement être utilisé sous forme de bouton d’icon ou de bouton traditionnel.
Après avoir installé la librairie et lu la documentation, commençons l’intégration.
D’abord les intents et les tailles
Mon composant est facilement lisible et modifiable. Il est totalement typé et en suivant la documentation de CVA, je bénéficie de l’auto-complétion de TailwindCSS en ajoutant du style dans mes objets.
Je souhaite maintenant utiliser mon composant avec des icons, sans texte, qui sera rond peu importe la taille.
Avec des icons
En quelques lignes je peux modifier le comportement de mon composant pour facilement changer ses propriétés lorsque certaines conditions sont réunies.
Ici, j’ai ajouté un nouveau variant à mon composant :
Et j'ai défini que lorsque :
Alors, j’ajoute une nouvelle class :
Avec cette simple ligne, j’ai une logique toute faite, typée et explicite pour modifier le style de mon composant. Je peux faire plein de combinaisons, et intégrer n’importe quel type de design system très facilement.
Conclusion
CVA est une librairie très récente et encore peu connue. Avec l’émergence de NextJS qui devient aujourd’hui incontournable et TailwindCSS étant proposé par défaut dans chaque projet, on rencontre très souvent les problématiques auxquelles CVA répond.
CVA apporte des solutions qui semblent évidentes mais qui n’existaient pas auparavant. Il est possible de l'utiliser avec TailwindCSS mais également avec des modules CSS classiques.
Pour aller plus loin : il est important de documenter ses composants au sein du Design System, par exemple avec StorybookJs. Il est également possible de créer un package spécifique pour son Design System afin de l’utiliser dans différents projets.