{
  "title": "J'ai migré shadcn de Radix vers Base UI (personne me l'a demandé)",
  "excerpt": "shadcn est passé de Radix UI à Base UI par défaut en juillet 2026. Pourquoi j'ai migré tous mes projets un week-end entier alors que rien ne le justifiait — et si tu devrais le faire aussi.",
  "locale": "fr",
  "publishedAt": "2026-07-05T21:42:53.525Z",
  "updatedAt": "2026-07-05T21:42:53.560Z",
  "author": {
    "name": "Cédric TOURNIER",
    "username": "Amorem",
    "url": "https://mysaas.blog/fr/@Amorem"
  },
  "tags": [],
  "relatedSaas": [],
  "sources": [
    {
      "title": "shadcn/ui — Base UI as the Default",
      "url": "https://ui.shadcn.com/docs/changelog/2026-07-base-ui-default",
      "hostname": "ui.shadcn.com"
    },
    {
      "title": "Base UI",
      "url": "https://base-ui.com/",
      "hostname": "base-ui.com"
    },
    {
      "title": "Migrating from Radix UI to Base UI",
      "url": "https://basecn.dev/docs/get-started/migrating-from-radix-ui",
      "hostname": "basecn.dev"
    }
  ],
  "urls": {
    "html": "https://mysaas.blog/fr/@Amorem/j-ai-migre-shadcn-de-radix-vers-base-ui-personne-me-l-a-demande",
    "markdown": "https://mysaas.blog/fr/@Amorem/j-ai-migre-shadcn-de-radix-vers-base-ui-personne-me-l-a-demande/md",
    "json": "https://mysaas.blog/fr/@Amorem/j-ai-migre-shadcn-de-radix-vers-base-ui-personne-me-l-a-demande/json"
  },
  "wordCount": 603,
  "images": [
    {
      "url": "https://assets.mysaas.blog/posts/assets/2026-07-05/4dd1b313-9405-4f74-b4f4-afd43f1d39c5.png",
      "alt": null,
      "title": null,
      "width": null,
      "height": null
    },
    {
      "url": "https://assets.mysaas.blog/posts/assets/2026-07-05/4ded2ca3-4247-4509-9ba2-c111ae073372.png",
      "alt": "Diff asChild vers render prop",
      "title": "asChild → render",
      "width": 1200,
      "height": 440
    }
  ],
  "content": {
    "markdown": "Ce week-end, j'ai passé shadcn de Radix UI à Base UI sur à peu près tous mes projets. Rien ne cassait, tout tournait, et le gain de perf n'existe pas.\n\nBref, une migration que personne ne recommande. Je l'ai faite quand même. Voilà pourquoi.\n\n## En 2023 c'est Radix ou rien\n\nQuand shadcn/ui débarque en janvier 2023, il est bâti sur Radix.\n\nDes composants headless, accessibles, des APIs propres, éprouvés sur des millions d'apps, ... shadcn n'a pas vraiment *choisi* Radix, c'était juste le seul socle sérieux du marché.\n\nTu copiais des primitives non stylées, tu collais du Tailwind par-dessus, ça marchait. Pendant deux ans, aucune raison de se poser la question.\n\n## Les mêmes dev mais deux ans après\n\nPuis les mêmes gens qui ont fait Radix (Colm Tuite en tête), plus le type derrière Floating UI et l'équipe de MUI, sont partis construire Base UI.\n\nCe n'est pas un concurrent qui veut tuer Radix : c'est la même équipe qui refait le boulot une deuxième fois, avec deux ans de leçons dans les poches. Leur v1 sort fin 2025, stable, avec 35 composants.\n\n## Base UI par défaut\n\nLe détail qui change tout : depuis juillet 2026, Base UI est le **défaut** dans shadcn. Tu scaffoldes un nouveau projet, il part sur Base UI, plus sur Radix.\n\n## Ce qui change (spoiler : pas la perf)\n\nL'intérêt est ailleurs que dans les benchmarks. C'est littéral, ça se voit dans le code. Trois exemples.\n\nLe `asChild` de Radix devient un `render` prop. Moins de magie planquée dans un Slot, tu vois ce que tu rends :\n\n```\n// Radix\r\n\r\n  Ouvrir\r\n\r\n\r\n// Base UI\r\nOuvrir} />\n```\n\n![Diff asChild vers render prop](https://assets.mysaas.blog/posts/assets/2026-07-05/4ded2ca3-4247-4509-9ba2-c111ae073372.png)\n\nLe positionnement des popups ne se pilote plus par des props posées sur le `Content`, mais par un `Positioner` explicite qui enveloppe le `Popup` :\n\n```\n// Radix\r\n…\r\n\r\n// Base UI\r\n\r\n  …\r\n\n```\n\nEt côté dépendances, fini la constellation de `@radix-ui/react-*` : un seul package natif.\n\n```\n# Radix\r\nnpm i @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-popover\r\n\r\n# Base UI\r\nnpm i @base-ui/react\n```\n\nPlus verbeux par endroits, oui. Mais plus honnête sur ce qui se passe vraiment. Bonus : Base UI embarque des primitives que Radix n'a jamais eues — Select multiple, Combobox, Autocomplete, Drawer.\n\n## Le vrai argument : la case à cocher\n\nSoyons honnêtes : tout ce qui précède, c'est de la rationalisation a posteriori.\n\nLa vraie raison est psychologique. Il y a cette catégorie de gens qui, dans un jeu, ne peuvent pas lâcher la manette tant que la barre n'est pas à 100 %, tous les trophées débloqués, toutes les cases cochées. On appelle ça des complétionnistes. J'en suis.\n\nEt « recommandé, disponible, stable, défaut officiel », c'est exactement le genre de case que je ne peux pas laisser décochée. Ce n'est pas de la dette technique que je rembourse, c'est un 100 % que je débloque.\n\n## On migre ou pas ?\n\nshadcn le dit lui-même : le pire truc que tu puisses faire à une app en prod, c'est changer de lib de composants. Il a raison. Tu n'as **pas** à migrer — Radix reste mûr, testé, supporté, et rien ne pourrit si tu ne bouges pas.\n\nDonc le conseil raisonnable :\n\n- projet stable en prod → touche à rien\n- projets vivants, templates, side-projects → migre tant que c'est indolore et que l'écart d'API est encore petit\n- dans tous les cas, il existe un skill de migration officiel (Claude Code, Cursor) qui bosse composant par composant, un commit chacun, rollback = tu supprimes la branche. Compte 20 minutes.\n\nEnfin, tu fais comme tu veux hein. Mais pour moi la case est cochée.",
    "html": "<p>Ce week-end, j'ai passé shadcn de Radix UI à Base UI sur à peu près tous mes projets. Rien ne cassait, tout tournait, et le gain de perf n'existe pas.</p><p>Bref, une migration que personne ne recommande. Je l'ai faite quand même. Voilà pourquoi.</p><h2>En 2023 c'est Radix ou rien</h2><p>Quand shadcn/ui débarque en janvier 2023, il est bâti sur Radix.</p><p>Des composants headless, accessibles, des APIs propres, éprouvés sur des millions d'apps, ... shadcn n'a pas vraiment <em>choisi</em> Radix, c'était juste le seul socle sérieux du marché.</p><p>Tu copiais des primitives non stylées, tu collais du Tailwind par-dessus, ça marchait. Pendant deux ans, aucune raison de se poser la question.</p><h2>Les mêmes dev mais deux ans après</h2><p>Puis les mêmes gens qui ont fait Radix (Colm Tuite en tête), plus le type derrière Floating UI et l'équipe de MUI, sont partis construire Base UI.</p><p>Ce n'est pas un concurrent qui veut tuer Radix : c'est la même équipe qui refait le boulot une deuxième fois, avec deux ans de leçons dans les poches. Leur v1 sort fin 2025, stable, avec 35 composants.</p><h2>Base UI par défaut</h2><p>Le détail qui change tout : depuis juillet 2026, Base UI est le <strong>défaut</strong> dans shadcn. Tu scaffoldes un nouveau projet, il part sur Base UI, plus sur Radix.</p><h2>Ce qui change (spoiler : pas la perf)</h2><p>L'intérêt est ailleurs que dans les benchmarks. C'est littéral, ça se voit dans le code. Trois exemples.</p><p>Le <code class=\"rounded-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 font-mono text-sm\">asChild</code> de Radix devient un <code class=\"rounded-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 font-mono text-sm\">render</code> prop. Moins de magie planquée dans un Slot, tu vois ce que tu rends :</p><pre><code>// Radix\r\n&lt;Dialog.Trigger asChild&gt;\r\n  &lt;Button&gt;Ouvrir&lt;/Button&gt;\r\n&lt;/Dialog.Trigger&gt;\r\n\r\n// Base UI\r\n&lt;Dialog.Trigger render={&lt;Button&gt;Ouvrir&lt;/Button&gt;} /&gt;</code></pre><img src=\"https://assets.mysaas.blog/posts/assets/2026-07-05/4ded2ca3-4247-4509-9ba2-c111ae073372.png\" alt=\"Diff asChild vers render prop\" title=\"asChild → render\" width=\"1200\" height=\"440\" data-image-size=\"medium\" data-media-id=\"cmr85erl5000hrlllqnupeemf\" data-media-sync-group=\"e1e1a506-93a3-45bb-84a4-37857ca9f381\" /><p></p><p>Le positionnement des popups ne se pilote plus par des props posées sur le <code class=\"rounded-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 font-mono text-sm\">Content</code>, mais par un <code class=\"rounded-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 font-mono text-sm\">Positioner</code> explicite qui enveloppe le <code class=\"rounded-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 font-mono text-sm\">Popup</code> :</p><pre><code>// Radix\r\n&lt;DropdownMenu.Content side=\"left\" align=\"start\"&gt;…&lt;/DropdownMenu.Content&gt;\r\n\r\n// Base UI\r\n&lt;DropdownMenu.Positioner side=\"left\" align=\"start\"&gt;\r\n  &lt;DropdownMenu.Popup&gt;…&lt;/DropdownMenu.Popup&gt;\r\n&lt;/DropdownMenu.Positioner&gt;</code></pre><p>Et côté dépendances, fini la constellation de <code class=\"rounded-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 font-mono text-sm\">@radix-ui/react-*</code> : un seul package natif.</p><pre><code># Radix\r\nnpm i @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-popover\r\n\r\n# Base UI\r\nnpm i @base-ui/react</code></pre><p>Plus verbeux par endroits, oui. Mais plus honnête sur ce qui se passe vraiment. Bonus : Base UI embarque des primitives que Radix n'a jamais eues — Select multiple, Combobox, Autocomplete, Drawer.</p><h2>Le vrai argument : la case à cocher</h2><p>Soyons honnêtes : tout ce qui précède, c'est de la rationalisation a posteriori.</p><p>La vraie raison est psychologique. Il y a cette catégorie de gens qui, dans un jeu, ne peuvent pas lâcher la manette tant que la barre n'est pas à 100 %, tous les trophées débloqués, toutes les cases cochées. On appelle ça des complétionnistes. J'en suis.</p><p>Et « recommandé, disponible, stable, défaut officiel », c'est exactement le genre de case que je ne peux pas laisser décochée. Ce n'est pas de la dette technique que je rembourse, c'est un 100 % que je débloque.</p><h2>On migre ou pas ?</h2><p>shadcn le dit lui-même : le pire truc que tu puisses faire à une app en prod, c'est changer de lib de composants. Il a raison. Tu n'as <strong>pas</strong> à migrer — Radix reste mûr, testé, supporté, et rien ne pourrit si tu ne bouges pas.</p><p>Donc le conseil raisonnable :</p><ul class=\"list-disc list-outside ml-6 space-y-1\"><li><p>projet stable en prod → touche à rien</p></li><li><p>projets vivants, templates, side-projects → migre tant que c'est indolore et que l'écart d'API est encore petit</p></li><li><p>dans tous les cas, il existe un skill de migration officiel (Claude Code, Cursor) qui bosse composant par composant, un commit chacun, rollback = tu supprimes la branche. Compte 20 minutes.</p></li></ul><p>Enfin, tu fais comme tu veux hein. Mais pour moi la case est cochée.</p><p></p>",
    "text": "Ce week-end, j'ai passé shadcn de Radix UI à Base UI sur à peu près tous mes projets. Rien ne cassait, tout tournait, et le gain de perf n'existe pas. Bref, une migration que personne ne recommande. Je l'ai faite quand même. Voilà pourquoi. En 2023 c'est Radix ou rien Quand shadcn/ui débarque en janvier 2023, il est bâti sur Radix. Des composants headless, accessibles, des APIs propres, éprouvés sur des millions d'apps, ... shadcn n'a pas vraiment choisi Radix, c'était juste le seul socle sérieux du marché. Tu copiais des primitives non stylées, tu collais du Tailwind par-dessus, ça marchait. Pendant deux ans, aucune raison de se poser la question. Les mêmes dev mais deux ans après Puis les mêmes gens qui ont fait Radix (Colm Tuite en tête), plus le type derrière Floating UI et l'équipe de MUI, sont partis construire Base UI. Ce n'est pas un concurrent qui veut tuer Radix : c'est la même équipe qui refait le boulot une deuxième fois, avec deux ans de leçons dans les poches. Leur v1 sort fin 2025, stable, avec 35 composants. Base UI par défaut Le détail qui change tout : depuis juillet 2026, Base UI est le défaut dans shadcn. Tu scaffoldes un nouveau projet, il part sur Base UI, plus sur Radix. Ce qui change (spoiler : pas la perf) L'intérêt est ailleurs que dans les benchmarks. C'est littéral, ça se voit dans le code. Trois exemples. Le asChild de Radix devient un render prop. Moins de magie planquée dans un Slot, tu vois ce que tu rends : // Radix <Dialog.Trigger asChild> <Button>Ouvrir</Button> </Dialog.Trigger> // Base UI <Dialog.Trigger render={<Button>Ouvrir</Button>} /> Le positionnement des popups ne se pilote plus par des props posées sur le Content , mais par un Positioner explicite qui enveloppe le Popup : // Radix <DropdownMenu.Content side=\"left\" align=\"start\">…</DropdownMenu.Content> // Base UI <DropdownMenu.Positioner side=\"left\" align=\"start\"> <DropdownMenu.Popup>…</DropdownMenu.Popup> </DropdownMenu.Positioner> Et côté dépendances, fini la constellation de @radix-ui/react-* : un seul package natif. # Radix npm i @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-popover # Base UI npm i @base-ui/react Plus verbeux par endroits, oui. Mais plus honnête sur ce qui se passe vraiment. Bonus : Base UI embarque des primitives que Radix n'a jamais eues — Select multiple, Combobox, Autocomplete, Drawer. Le vrai argument : la case à cocher Soyons honnêtes : tout ce qui précède, c'est de la rationalisation a posteriori. La vraie raison est psychologique. Il y a cette catégorie de gens qui, dans un jeu, ne peuvent pas lâcher la manette tant que la barre n'est pas à 100 %, tous les trophées débloqués, toutes les cases cochées. On appelle ça des complétionnistes. J'en suis. Et « recommandé, disponible, stable, défaut officiel », c'est exactement le genre de case que je ne peux pas laisser décochée. Ce n'est pas de la dette technique que je rembourse, c'est un 100 % que je débloque. On migre ou pas ? shadcn le dit lui-même : le pire truc que tu puisses faire à une app en prod, c'est changer de lib de composants. Il a raison. Tu n'as pas à migrer — Radix reste mûr, testé, supporté, et rien ne pourrit si tu ne bouges pas. Donc le conseil raisonnable : projet stable en prod → touche à rien projets vivants, templates, side-projects → migre tant que c'est indolore et que l'écart d'API est encore petit dans tous les cas, il existe un skill de migration officiel (Claude Code, Cursor) qui bosse composant par composant, un commit chacun, rollback = tu supprimes la branche. Compte 20 minutes. Enfin, tu fais comme tu veux hein. Mais pour moi la case est cochée."
  }
}