La complexité excessive des boutons radio de Shadcn
(paulmakeswebsites.com)- Bien que les boutons radio intégrés nativement aux navigateurs web soient de simples éléments HTML, la bibliothèque UI Shadcn les reconstruit en plusieurs couches de composants React
- Les composants
<RadioGroup>et<RadioGroupItem>de Shadcn encapsulent à nouveau des composants de Radix UI, tout en utilisant des icônes lucide-react et des dizaines de classes Tailwind - Radix s’appuie sur des attributs ARIA pour l’accessibilité et la personnalisation, mais réutilise en pratique des éléments bouton au lieu de l’élément natif
<input type="radio"> - Alors qu’un style identique peut être obtenu avec du simple CSS, cette structure ajoute des centaines de lignes de code et plusieurs dépendances, créant une complexité inutile
- En ne réutilisant pas les éléments HTML natifs, cette approche accroît la dégradation des performances et la charge de maintenance, tout en nuisant à la simplicité du développement web
Analyse de la structure des boutons radio de Shadcn
- Shadcn implémente les boutons radio via deux composants,
<RadioGroup>et<RadioGroupItem>- Chaque composant encapsule des primitives importées depuis
@radix-ui/react-radio-groupet utilise CircleIcon delucide-react - L’ensemble comprend plus de 45 lignes de code, 3 imports externes et un style défini avec plus de 30 classes Tailwind
- Chaque composant encapsule des primitives importées depuis
- La structure charge une bibliothèque d’icônes SVG pour afficher un simple indicateur circulaire
- Une fonction qui pourrait être remplacée par
border-radiusen CSS ou un élément<circle>
- Une fonction qui pourrait être remplacée par
Le rôle de Radix UI
- Radix, utilisé par Shadcn, est une bibliothèque de composants UI bas niveau centrée sur l’accessibilité et la personnalisation
- Son implémentation du groupe de boutons radio repose sur environ 215 lignes de code React et importe 7 fichiers
- Radix configure un comportement de bouton radio en ajoutant des attributs ARIA à des éléments
<button>- Pourtant, le premier principe de l’utilisation d’ARIA selon le W3C indique qu’il faut utiliser les éléments HTML natifs quand c’est possible
- Radix ne suit pas ce principe et réutilise des boutons à la place d’un
<input>
- Il n’ajoute un
<input type="radio">masqué qu’à l’intérieur d’un<form>, ce qui manque de cohérence
Une alternative simple possible avec CSS
- Les boutons radio HTML natifs peuvent être facilement stylisés avec
appearance: none,::before,:checked,border-radius, etc.- Le code d’exemple montre une personnalisation complète sans dépendances, sans JavaScript et sans attributs ARIA
- Le même rendu peut aussi être obtenu avec Tailwind
- L’idée selon laquelle « styliser des boutons radio est difficile » est un problème du passé ; aujourd’hui, le CSS pur offre un contrôle suffisant
Le problème de l’accumulation de complexité
- Utiliser Shadcn avec Radix oblige à comprendre deux bibliothèques et des centaines de lignes de code
- Pour un simple bouton radio, plusieurs kilo-octets de JavaScript sont chargés en plus
- L’utilisateur doit attendre le parsing et l’exécution du JS pour pouvoir simplement basculer un bouton
- Cette structure entraîne une hausse de la charge cognitive, une augmentation du risque de bugs et une dégradation des performances web
Retour à la simplicité
- Les navigateurs fournissent déjà des boutons radio, et une seule ligne comme
<input type="radio" name="beverage" value="coffee" />suffit - Les abstractions inutiles et l’empilement de bibliothèques nuisent à la simplicité et à l’efficacité originelles du développement web
- Même pour de petits éléments UI, une conception qui réutilise les fonctionnalités natives est plus avantageuse à la fois pour la maintenance et pour les performances
4 commentaires
Quand on voit le composant bouton de react aria, on manque de tomber dans les pommes lol
Comme je travaille dans le frontend, c’est un problème auquel je suis confronté depuis longtemps, et, comment dire, c’est vraiment un problème difficile à résoudre. L’implémentation continue d’évoluer selon les époques, mais le fait de ne pas le résoudre avec
input typereste le même, quelle que soit l’époque...Essayer d’imiter le comportement des boutons radio et des cases à cocher du navigateur web en réimplémentant séparément les spécifications liées à l’accessibilité, franchement, je me demande bien à quoi ça rime... Je ne sais pas... Comme le dit l’article, il existe maintenant des alternatives en CSS, donc voir qu’on s’obstine malgré tout à vouloir l’implémenter en composant, c’en est presque drôle.
Ennuyeux et pédant :
Réglé en un instant, facile à retenir longtemps :
Commentaires sur Hacker News
Je ne fais pas souvent du frontend, mais dès le moment où React est devenu dominant, on voyait déjà venir une montée de la complexité
Les autres couches d’abstraction ont tendance à simplifier, mais React produit une abstraction bien plus complexe que les technologies sur lesquelles il repose
J’ai l’impression que des développeurs qui ne connaissent que React empilent des couches toujours plus hautes, ce qui aboutit à des conceptions excessives
Par exemple, Shadcn ou Radix sont des bibliothèques UI réservées à React, mais à lire leur marketing, on pourrait croire à des bibliothèques UI généralistes
À grande échelle, j’ai fini soit par construire mon propre framework, soit par être frustré par les frameworks existants, et React règle en partie ce problème
Plus que React lui-même, c’est l’excès de complexité de son écosystème qui pose problème. Si on maîtrise bien React, cela reste agréable à utiliser
Ils cherchent juste à contourner le CSS avec des outils comme Tailwind. J’utilise React pour gérer l’état, mais je préfère faire le style directement en CSS
Le plus difficile, c’est de convaincre les membres de l’équipe d’apprendre le CSS
J’évite ces frameworks « modernes » et je préfère autant que possible les technologies de base
React ne fournit que des « boîtes », et c’est au développeur de décider quoi y mettre. C’est là sa vraie force
Cet exemple de bouton radio est à la fois drôle et frappant
Le résultat final est indiscernable d’un simple bouton radio CSS natif, donc on peut se demander pourquoi le rendre aussi complexe
Je me demande s’il existe des exemples de grands sites construits sans cette complexité inutile
Il y avait plus de code qu’aujourd’hui, mais l’interface donnait une impression de réactivité immédiate
Voir le code du projet Takeoff
Comme on dit, « personne ne s’est jamais fait virer pour avoir choisi React », donc c’est devenu l’option sûre
Les développeurs doivent se rappeler qu’ils peuvent toujours contester les exigences de design
Un développeur perdait 4 heures sur un simple problème de layout en React Native ; on lui a dit de demander s’il était possible de modifier légèrement le design, et le problème a été réglé en 10 minutes
Avec du CSS bien utilisé, on peut obtenir des résultats largement suffisants. Je serais curieux d’avoir les recommandations de ceux qui ont essayé cette approche
La plus grosse erreur de 2025 a été de choisir Shadcn
Voir Radix importé en permanence a été un premier signal d’alerte, puis le composant radio a été le deuxième
Le projet était déjà trop avancé pour faire marche arrière, donc j’ai bricolé avec Copilot, mais au final cette dépendance à l’IA ne m’a pas plu non plus
Mon POC précédent était bien plus simple et efficace. Un jour, j’aimerais tout refaire en HTML vanilla
Remix ou React Router 7 faisaient encore au moins l’effort de rester proches des standards du web
C’est avec Tailwind que je me suis dit « ça ne va pas », et si mes amis trouvent toujours ça bien après refactorisation, j’y reviendrai peut-être
React a déjà un style basé sur les props, donc il n’y a pas vraiment de raison d’empiler des blocs de classes CSS
Si l’objectif principal est l’accessibilité, Radix UI suffit largement
Le problème, c’est que les éléments
<input>du navigateur, en particulier radio et select, sont difficiles à personnaliserLes boutons radio natifs ont une mauvaise ergonomie sur mobile
J’aimerais comprendre plus précisément quels problèmes il y avait sur mobile
<label>et en ajoutant du padding, cela reste tout à fait utilisable sur mobileLa plupart des projets commencent avec de bonnes intentions, puis finissent un jour remplis d’un code de bouton radio sur 200 lignes et de 7 imports
C’est ainsi que commence la dégradation du code (code rot)
J’ai récemment testé daisyUI et j’aime plutôt bien
Comme c’est basé sur du pur CSS, cela exploite bien les nouvelles fonctionnalités du navigateur (comme
dialog)Par exemple, le Drawer ne piège pas le focus, et l’Accordion abuse des boutons radio comme substitut au JS
C’est pour cela que des bibliothèques comme Radix finissent inévitablement par devenir complexes
Je suis d’accord avec l’idée générale du billet, mais je me demande si, pour reproduire à l’identique dans tous les navigateurs le style exact qu’un designer a créé dans Figma, le CSS vanilla suffit vraiment
Peut-on recréer complètement quelque chose comme la démo de Radix ?
Voir cet exemple CodePen
Il suffit d’extraire le CSS et de l’attacher à un simple composant React
Est-ce que cela vaut vraiment la peine d’ajouter des dizaines de ko de code et une charge de maintenance juste pour éviter de légères différences visuelles ?
Comme le disait Nam June Paik : « si c’est trop parfait, Dieu se met en colère »
Le vrai coût, ce n’est pas le code, mais le temps d’onboarding
Pour qu’un nouveau développeur comprenne un bouton radio Radix de 47 lignes, il faut des semaines
En version vanilla, on peut le faire en une journée et l’expliquer en 20 minutes
Bien sûr, pour des produits comme Figma ou Linear, où l’accessibilité et la navigation au clavier sont essentielles, cette complexité se justifie
Beaucoup de commentaires critiquent Shadcn, mais pour ma part je trouve au contraire qu’il encourage bien la structure des composants et la réutilisabilité
Le principe central de Shadcn, c’est de dire : « possédez vos composants et modifiez-les vous-même »
C’est une approche fondamentalement différente de celle des bibliothèques UI traditionnelles