La question revient dans chaque projet React : utiliser une librairie npm installée, ou copier-coller des composants directement dans le code source ? La réponse dépend moins de la technologie que de qui va maintenir le code dans six mois. Ce guide détaille les deux approches, leurs compromis réels, et les critères concrets pour choisir.
Ce que recouvre le terme "react component library"
Une react component library désigne un ensemble de composants d'interface réutilisables. Mais deux modèles de distribution coexistent, et ils impliquent des choix architecturaux très différents.
Le premier modèle est celui de la dépendance npm : MUI, Radix UI, Ant Design. On installe le package, on importe les composants, et les mises à jour arrivent via npm update. Le code source des composants n'est jamais dans votre dépôt.
Le second modèle, popularisé par shadcn/ui puis repris par des outils comme Incubator, consiste à copier le code source directement dans votre projet. Le composant vit dans src/components/, vous en êtes propriétaire, et vous le modifiez sans PR ni fork.
Dépendance npm : avantages et limites réelles
Ce qui fonctionne bien : la cohérence à grande échelle. MUI ou Ant Design conviennent parfaitement à une équipe de 20 développeurs qui veut des conventions partagées sans débat. Les composants sont testés, documentés, accessibles (ARIA) par défaut, et maintenus par des équipes dédiées.
Ce qui coince : le theming profond. Personnaliser un composant MUI au-delà de la palette de couleurs implique d'apprendre l'API sx, les slots, les styled overrides. Quand le design exige quelque chose d'atypique, on finit souvent à contourner la librairie plutôt qu'à l'utiliser.
La taille du bundle est l'autre point de friction. MUI core pèse environ 80 ko minifié gzippé avant tree-shaking. Pour une landing page ou un site marketing, c'est souvent excessif.
Copy-paste : propriété du code et liberté de modification
Le principe est simple : vous récupérez le TSX, le CSS, les types, et vous les intégrez dans votre structure de fichiers. Aucune dépendance supplémentaire dans package.json (sauf des utilitaires légers comme clsx ou framer-motion que vous utilisiez déjà).
Les vrais bénéfices :
- Modification directe sans fork ni PR
- Aucun risque de breaking change lors d'une mise à jour de dépendance
- Bundle optimisé : seul le code que vous gardez est embarqué
- Compréhension complète de ce qui tourne en production
Le coût : vous portez la maintenance. Si une faille de sécurité touche un pattern que vous avez copié il y a dix-huit mois, c'est à vous de patcher. Pour les équipes sans capacité front-end dédiée, ce coût est réel.
Le catalogue Incubator suit ce modèle : plus de 900 sections React (hero, pricing, testimonials, changelog, etc.) construites avec Tailwind v4 et Framer Motion, toutes copiables directement.
Theming : tokens CSS contre props de configuration
Les librairies npm exposent généralement leur theming via un provider ou des props :
// MUI
<ThemeProvider theme={createTheme({ palette: { primary: { main: "#818cf8" } } })}>
Le modèle copy-paste utilise plutôt des CSS custom properties définis globalement :
:root {
--color-accent: #818cf8;
--radius-md: 0.5rem;
}
Le second modèle est plus direct à déboguer et ne dépend d'aucune API propriétaire. Changer le radius de tous les composants revient à modifier une valeur dans un fichier CSS. Les composants Incubator utilisent exclusivement des tokens CSS (var(--color-background), var(--color-foreground)) jamais de couleurs codées en dur.
Pour voir comment le theming se traduit visuellement, les collections dark et minimal montrent les mêmes composants sous différents presets.
Accessibilité : état de l'art par type de librairie
C'est l'argument le plus solide en faveur des librairies npm établies. Radix UI, Headless UI et Ariakit fournissent des primitives ARIA correctes par défaut pour les patterns complexes : combobox, dialog, menu déroulant. Implémenter un menu accessible from scratch demande entre 200 et 400 lignes de code pour gérer les rôles, le focus trap, les raccourcis clavier.
Pour les sections marketing (hero, pricing, testimonials, stats), la problématique est différente. Ces composants n'ont pas d'état interactif complexe. Un titre <h1>, une liste de features, un bouton CTA : l'accessibilité se résume à la sémantique HTML correcte et aux contrastes de couleur, deux points gérables avec n'importe quelle approche.
La règle pratique : utilisez des primitives Radix/Headless pour les patterns UI complexes (modals, dropdowns), copiez les sections marketing.
Comparaison directe avec les alternatives principales
| Critère | MUI / Ant Design | shadcn/ui | Incubator | |---|---|---|---| | Propriété du code | Non | Oui | Oui | | Design prêt à l'emploi | Générique | Minimal | 7 presets visuels | | Animations | Limitées | Non | Framer Motion natif | | Sections marketing | Peu | Non | 900+ | | Theming | API propriétaire | Tailwind config | CSS tokens |
Incubator se positionne différemment de shadcn/ui (qui cible les composants UI atomiques) et de MUI (qui cible les applications). Son focus est les sections de landing page et de sites marketing, avec des effets visuels prêts à l'emploi : scroll animations, hover effects.
Pour une comparaison détaillée avec shadcn/ui, voir Incubator vs shadcn/ui. Avec Tailwind UI (payant, statique) : Incubator vs Tailwind UI.
Comment choisir selon votre contexte
Application SaaS avec beaucoup de UI fonctionnel (formulaires, tableaux, dashboards) : une librairie npm comme Radix UI ou MUI fait sens. La richesse des primitives interactives justifie la dépendance.
Landing page, site marketing, portfolio : l'approche copy-paste est presque toujours préférable. Vous n'avez pas besoin de 300 composants, vous en utilisez 15. Maîtriser chaque ligne vous donne la flexibilité pour les animations et les effets visuels que les maquettes demandent.
Prototype ou MVP rapide : peu importe, choisissez ce que votre équipe connaît déjà.
Design très custom (identité de marque forte) : copy-paste obligatoire. Lutter contre le theming d'une librairie npm pour un design atypique coûte plus cher que d'écrire les composants soi-même.
Un exemple concret de section custom prête à copier : hero-cursor-mask, un hero interactif qui suit le curseur, difficile à implémenter proprement avec une librairie npm standard.
Ce qui est souvent sous-estimé : la maintenance à long terme
Les projets qui choisissent une librairie npm pour "aller plus vite" se retrouvent parfois bloqués sur une version majeure parce que la migration est trop coûteuse. MUI v4 vers v5 a demandé plusieurs semaines à des équipes entières. Emotion vers styled-components, puis inverse, puis CSS-in-JS vers Tailwind : les migrations de librairies UI sont chronophages.
Avec l'approche copy-paste, chaque composant est indépendant. Mettre à jour un composant ne casse pas les autres. La dette technique est localisée, pas systémique.
Conclusion pratique
Il n'y a pas de réponse universelle. Une librairie npm installée convient aux applications avec des patterns UI complexes et une équipe qui veut des conventions partagées. L'approche copy-paste convient aux sites marketing, aux projets avec des contraintes de design fortes, et à quiconque veut garder le contrôle total de son code en production.
Le catalogue Incubator couvre le second cas : des sections visuellement travaillées, animées, copiables directement dans n'importe quel projet React avec Tailwind. Pas une dépendance de plus dans votre package.json.