Programming
ProgrammingIntermediate

shadcn/ui vs MUI vs Mantine: I Built the Same Screen Five Ways and Measured It

shadcn/ui vs MUI vs Mantine on a real benchmark: the same React screen built five ways, gzip bundle sizes, npm packages shipped, the code you end up owning, what changed when shadcn made Base UI its default instead of Radix, what MUI 9 and Mantine 9 changed, the traps I hit, and which library to pick.

Cover image: shadcn/ui vs MUI vs Mantine: I Built the Same Screen Five Ways and Measured It
Contents

In July, shadcn/ui changed its default. New projects no longer start on Radix — they start on Base UI, a library “from the creators of Radix, Material UI, and Floating UI” whose repository lives in MUI’s own GitHub organisation. So the most-searched React UI kit now runs, by default, on an engine built by the people behind Material UI.

That made the usual “shadcn vs MUI vs Mantine” question more interesting, and most comparisons I found still describe the old setup. So I built the same screen five ways — shadcn on Base UI, Radix and React Aria, plus MUI 9 and Mantine 9 — measured what each one ships, and wrote down every trap I hit on the way.

shadcn/ui vs MUI vs Mantine: one screen, five setups, real bundle numbers — and shadcn’s switch from Radix to Base UI

shadcn/ui vs MUI vs Mantine at a Glance

Versions, downloads and stars as of October 7, 2026, from npm, GitHub and each project’s docs. Weekly downloads cover September 28 to October 4.

shadcn/ui vs MUI vs Mantine at a Glance
shadcn/ui MUI (Material UI) Mantine
What you install A CLI; component source is copied into src/components/ui @mui/material + @emotion/react + @emotion/styled @mantine/core + @mantine/hooks
Current version CLI 4.21.3 9.4.0 9.7.1
Last major — (no versioned component package) v9, announced April 8, 2026 (v8 was skipped) 9.0 on March 31, 2026
Behaviour underneath Base UI (default), Radix or React Aria MUI’s own components Mantine’s own, with Floating UI
Styling Tailwind CSS v4 classes in your copy Emotion (CSS-in-JS) A CSS file, also split per component
Look out of the box Neutral; eight styles, Nova by default Material Design Mantine’s own neutral style
License MIT MIT core; MUI X Pro and Premium are commercial MIT
GitHub stars 125.2k 99.1k 31.8k
npm weekly downloads 13.4M (the CLI) 12.5M 3.3M
My benchmark, gzip 126.8–154.4 KB 140.2 KB 163.2 KB

One caveat on the downloads: the shadcn package is the CLI, not the components. Your app never depends on it at runtime, so its number counts CLI runs — the primitives tell the usage story better: @base-ui/react had 19.3 million weekly downloads and radix-ui 19.1 million.

What Is shadcn/ui (and Why It Isn’t a Library)

Most component libraries work the same way: install a package, import Button, configure a theme. shadcn/ui doesn’t. Its introduction says it plainly: “This is not a component library. It is how you build your component library.”

When you run npx shadcn add dialog, the CLI writes dialog.tsx into your repo. From that moment it is your code:

  • You edit it directly. Need a different close button? Change the file. No theme override, no wrapper, no !important.
  • Nobody upgrades it for you. A bug fixed upstream stays in your copy until you pull it in. Registries help teams share their own versions — public GitHub repositories since June, private ones since August — but the trade-off remains.
  • Coding agents can read it. shadcn markets this explicitly as “AI-Ready”: the source is in your repo, so an agent sees exactly what it is changing.

How much code do you take on? For the seven components in my benchmark, the CLI wrote 558 lines on Base UI, 581 on Radix and 925 on React Aria, which also pulled in an input group and a textarea as dependencies.

Two models: shadcn copies component source into your repo on top of Base UI, Radix or React Aria and Tailwind; MUI and Mantine stay in node_modules and are customised through theme, props and slots
Ownership is the real difference — not the look.

MUI and Mantine are the opposite model. Components stay in node_modules, you customise them through the theme, props and slots, and fixes arrive with npm update — together with any breaking changes.

“shadcn vs MUI” is not really a styling question. It’s a question of who owns the component code: you, or a vendor that ships updates you have to absorb.

The Benchmark: the Same Screen in Five Setups

To compare like with like, I built one screen in every setup: tabs, a “New project” dialog with a text field, a select and a checkbox, and two buttons — written the idiomatic way for each library.

  • Toolchain: Vite 8.3 production build, React 19, TypeScript, default settings. Sizes are gzip as reported by Vite.
  • shadcn: scaffolded with shadcn init -t vite -p nova and -b base, -b radix or -b aria, then shadcn add for the seven components. These builds include the template’s icon library (lucide-react) and theme provider; web fonts are separate files and not counted.
  • MUI: @mui/material 9.4 with Emotion. Mantine: @mantine/core 9.7.1 with the standard styles.css import from its getting-started guide.
  • Baseline: the same Vite app with only React renders 68.6 KB gzip. Every number below includes it.
  • Packages: I counted the distinct npm packages that ended up in the shipped JavaScript, using the build’s source maps.
The same “Create project” dialog built with shadcn/ui on Base UI, MUI 9 and Mantine 9, with gzip bundle sizes
Same screen, three libraries. shadcn on Radix and React Aria look identical to Base UI.
The Benchmark: the Same Screen in Five Setups
Setup JS gzip CSS gzip Total Over bare React npm packages in bundle Code you own
shadcn/ui + Radix 118.7 KB 8.1 KB 126.8 KB +58.2 KB 48 581 lines
MUI 9.4 140.2 KB — (runtime) 140.2 KB +71.7 KB 24 —
shadcn/ui + Base UI 136.3 KB 8.0 KB 144.3 KB +75.7 KB 14 558 lines
shadcn/ui + React Aria 145.4 KB 9.0 KB 154.4 KB +85.9 KB 12 925 lines
Mantine 9.7 127.3 KB 35.9 KB 163.2 KB +94.6 KB 18 —
Bundle size for the same screen, gzip: shadcn on Radix 126.8 KB, MUI 140.2 KB, shadcn on Base UI 144.3 KB, shadcn on React Aria 154.4 KB, Mantine 163.2 KB, with React accounting for 68.6 KB of each
The grey part is React. Everything the library adds sits on top.

What the numbers say:

  • Radix was the lightest, even though it ships the most packages. Radix publishes each component as its own independently versioned package — 48 packages ended up in this bundle — but each one is small.
  • Base UI cost 17.6 KB more than Radix for these seven components, with a much shorter dependency list. That is the price of the new default on this screen; with a different component mix it can go either way.
  • MUI ships no CSS file. Emotion generates styles in JavaScript at runtime, so its 140.2 KB is all JS — something to keep in mind for server rendering and strict Content Security Policies.
  • Mantine’s JavaScript is the second-smallest at 127.3 KB, but the full styles.css adds 35.9 KB gzip of CSS for every component, used or not.

And the most important line: the whole spread is 36 KB gzip. That’s real on a slow phone, but it’s smaller than a single hero image. Bundle size alone shouldn’t decide this — ownership, design language and the components you’d otherwise build yourself should.

shadcn Radix vs Base UI vs React Aria: Which Base to Pick

“shadcn vs radix” is the most common shadcn comparison people search for, and it’s slightly the wrong question. Radix is one of three bases shadcn can now sit on. Here is what changed in 2026, according to the shadcn changelog:

  • December 2025: npx shadcn create let you pick Radix or Base UI. Every component was rebuilt for Base UI with the same abstraction.
  • July 2026: Base UI becomes the default. The reasons shadcn gives: Base UI was stable at 1.6, past 6 million weekly downloads, and projects created on shadcn/create were already choosing it over Radix 2 to 1. It has since reached 1.8.0.
  • July 2026: React Aria becomes a third base (--base aria), available in all eight visual styles.

What did not change matters just as much: Radix is not deprecated. shadcn writes that every update and new component ships for both libraries unless a component only exists in Base UI, that it still runs Radix in production, and that you don’t need to migrate: “If your app works, keep shipping.”

shadcn Radix vs Base UI vs React Aria: Which Base to Pick
Base UI Radix React Aria
shadcn status Default since July Fully supported Third base since July
Init flag -b base -b radix --base aria
Built by Creators of Radix, Material UI, Floating UI WorkOS Adobe
Composition API render prop asChild React Aria Components (id, defaultSelectedKey)
My benchmark, gzip 144.3 KB 126.8 KB 154.4 KB
npm packages in bundle 14 48 12
Owned code, 7 components 558 lines 581 lines 925 lines

If you do migrate, shadcn deliberately didn’t ship a codemod — you’ve edited your copies, and a codemod would break exactly those. Instead there’s a skill for coding agents (pnpm dlx skills add shadcn/ui, then “migrate accordion to base-ui”). It works one component at a time, leaves one commit per component on a branch, and writes a report of behaviour changes to check by hand. shadcn’s own test: 60+ components, 36 on Radix, about 25 minutes at roughly 10,000 tokens per component.

The day-to-day API difference you’ll notice first is composition:

// Radix base: asChild
<DialogTrigger asChild>
<Button>New project</Button>
</DialogTrigger>
// Base UI base: render prop
<DialogTrigger render={<Button />}>New project</DialogTrigger>

MUI 9: What Changed

MUI went straight from v7 to v9, announced on April 8, 2026, to put Material UI and MUI X on one shared major version again. The things that matter for this comparison:

  • New components and stricter accessibility. NumberField and Menubar are new. Tabs, menus and steppers moved to proper roving tabindex keyboard navigation, and the stepper now renders as an ordered list.
  • Deprecated APIs are gone. The old components/componentsProps and *Props props are replaced by slots and slotProps, and system props such as <Box mt={2}> must move into sx. MUI ships codemods for most of it — see the upgrade guide.
  • Higher browser floor: Chrome 117, Firefox 121 and Safari 17 are the new default targets.
  • Emotion stays — for now. MUI says it will explore independence from Emotion and better Tailwind integration for the next major.
  • MUI X got new pricing. Since April 8, Pro and Premium use per-application licensing, and telemetry for commercial components is on by default in development builds (off in production).

MUI’s real advantage isn’t the button. It’s MUI X: a Data Grid with server-side features, date and time pickers, charts, a tree view and, new in v9, Scheduler and Chat in alpha. If you’d otherwise spend weeks on a decent data grid, that alone can decide the comparison.

Mantine 9: The Batteries-Included Middle

Mantine sits between the two models: a full npm library like MUI, but with a neutral look and plain CSS instead of CSS-in-JS. Version 9.0 shipped on March 31, 2026; 9.7.1 came out on October 6.

  • React 19.2 or newer is required — @mantine/core 9 declares react ^19.2.0 as a peer dependency. If you’re stuck on React 18, Mantine 9 is off the table; MUI and Base UI still support React 17 and up.
  • Hooks come with it. @mantine/hooks (for example useDisclosure, which my benchmark dialog uses) covers a lot of what you’d otherwise pull from other packages.
  • CSS is a real file. That’s good for server rendering and caching. The default @mantine/core/styles.css import is also the largest single item in my benchmark — 35.9 KB gzip — because it contains every component’s styles.

Mantine also ships per-component stylesheets (@mantine/core/styles/Button.css and so on) to trim that CSS. Do it carefully — see trap 5 below.

Five Traps I Hit Setting These Up

All of these come from building the benchmark on October 7, 2026, with the versions above.

  1. shadcn init -b base produced a Radix project. With -t vite and no preset, the CLI wrote "style": "new-york" and installed radix-ui despite -b base. Adding a preset (-p nova) fixed it and gave "style": "base-nova". Check components.json after init.
  2. Base UI’s Select shows the raw value. With Radix, <SelectValue /> shows the selected item’s label (“Developer”). With Base UI it showed dev until I passed items to the root — the Base UI types document exactly that: when items is specified, Select.Value renders the label instead of the raw value.
  3. The React Aria template didn’t build out of the box. The generated label.tsx imports React without using it, and the Vite template’s strict TypeScript settings fail tsc -b with TS6133. Delete the import and it builds.
  4. The React Aria API is different, not just the engine. Tabs use id and defaultSelectedKey instead of value and defaultValue, and the dialog nests inside DialogTrigger. Moving between bases is a real migration, not a flag.
  5. Partial Mantine CSS fails silently. My first attempt at importing only the per-component stylesheets missed a few, and the tabs and buttons rendered completely unstyled — no error, no warning. If you split Mantine’s CSS, check every screen visually.

Which React UI Library Should You Pick?

Decision path: data-heavy apps go to MUI with MUI X, non-Tailwind batteries-included projects to Mantine, strict accessibility and i18n to shadcn on React Aria, working Radix apps stay on Radix, and new Tailwind projects start on shadcn with Base UI
Bundle size decides the least. Start with ownership and data components.
Which React UI Library Should You Pick?
Your situation Pick Why
Admin or analytics app with heavy tables, date pickers, charts MUI + MUI X Maintained data components you’d otherwise build; budget for Pro or Premium if you need advanced grid features
New Tailwind project, custom design system, coding agents writing UI shadcn/ui on Base UI You own the code; it’s shadcn’s recommended default
Existing shadcn app on Radix Stay on Radix Fully supported, smallest bundle in my test; migrate later with the skill if you want
No Tailwind, want one library with hooks and plain CSS Mantine Batteries included, neutral design — if you can be on React 19.2+
Accessibility and internationalisation are hard requirements shadcn/ui on React Aria Adobe’s primitives — accept the largest bundle and the most owned code
You need Material Design specifically MUI It’s the reference implementation

What About Chakra, DaisyUI, HeroUI and Headless UI?

They’re real options, just smaller in the current conversation. Weekly npm downloads for September 28 to October 4:

  • Headless UI (8.8M) — Tailwind Labs’ unstyled components. Closer to Radix or Base UI than to shadcn: you still write all the styling.
  • Chakra UI (2.0M) — a styled library with style props; similar in spirit to Mantine.
  • Ark UI (1.2M) — headless components from the Chakra team.
  • DaisyUI (1.2M) — a Tailwind plugin of CSS class names, no React components at all.
  • HeroUI (0.8M) — formerly NextUI, a styled Tailwind-based library.

If you’re already comparing build tooling, my Biome benchmark, the es-toolkit vs lodash test and the Jest to Vitest migration guide use the same measure-it-yourself approach.

The Bottom Line

The three libraries are closer in size than their fans suggest — 36 KB gzip separates the lightest and heaviest setup in my test. What separates them is ownership. shadcn/ui hands you the code and, since July, puts it on Base UI by default; MUI and Mantine keep the code and hand you updates.

If your app lives on data grids, pick MUI. If you want one tidy library without Tailwind, pick Mantine. For a new Tailwind project, start with shadcn on Base UI — and if you already have shadcn on Radix and it works, take shadcn’s own advice and keep shipping.

Topics
shadcn-uimuimantinebase-uiradix-uireact-ariareact-ui-library

Frequently asked questions

What is shadcn/ui?

shadcn/ui is a set of React components plus a CLI that copies their source code into your project instead of installing them as a dependency. The components are styled with Tailwind CSS and built on a headless primitive library — Base UI by default since July 2026, with Radix and React Aria as alternatives. Its own docs say it is not a component library but how you build your component library.

Is shadcn/ui better than MUI?

It depends on what you need. shadcn/ui gives you neutral-looking components whose code you own and edit, which suits Tailwind projects and custom design systems. MUI gives you Material Design components maintained by a vendor plus advanced MUI X components such as the Data Grid, date pickers and charts, which suits data-heavy admin apps. In my benchmark the two shipped similar bundles: 144.3 KB gzip for shadcn on Base UI and 140.2 KB for MUI 9.

What is the difference between shadcn and Radix?

Radix is a headless primitive library: it handles behaviour, focus management and accessibility but ships no styles. shadcn/ui wraps primitives like Radix in styled, copy-pasted components and adds a CLI and a registry for distributing them. Since July 2026, new shadcn projects use Base UI instead of Radix by default; Radix is still fully supported with the -b radix flag.

Does shadcn still use Radix UI?

Yes, if you choose it. In July 2026 shadcn made Base UI the default for new projects, but every component and update still ships for Radix as well, unless a component only exists in Base UI. Run shadcn init with -b radix to get Radix. shadcn says existing Radix apps do not need to migrate.

Should I use Base UI, Radix or React Aria with shadcn?

For a new project, Base UI is shadcn's recommended default. For an existing Radix app that works, stay on Radix — it was also the smallest bundle in my test. Choose React Aria, Adobe's library, when accessibility and internationalisation are hard requirements; in my test it produced the largest bundle and the most owned code: 925 lines for seven components.

Is Mantine better than MUI?

Mantine and MUI are both full npm component libraries. Mantine has a neutral design, ships a hooks package and styles components with a plain CSS file, and its version 9 requires React 19.2 or newer. MUI implements Material Design, uses Emotion for styling, supports React 17 to 19, and has MUI X for data grids, date pickers and charts, whose advanced tiers are commercial. Pick Mantine for a lighter, batteries-included setup and MUI for enterprise data components.

Can I use shadcn/ui without Tailwind CSS?

Not as shipped. shadcn components are written with Tailwind utility classes, and the CLI sets Tailwind up when you run init. You could rewrite the styles by hand because you own the code, but at that point you are mostly using the underlying primitive library — Base UI, Radix or React Aria — directly.

Which React UI library has the smallest bundle?

In my benchmark of the same screen built with each library and a Vite 8 production build, shadcn on Radix was smallest at 126.8 KB gzip including React, followed by MUI 9 at 140.2 KB, shadcn on Base UI at 144.3 KB, shadcn on React Aria at 154.4 KB and Mantine 9 with its full stylesheet at 163.2 KB. React alone accounted for 68.6 KB of each.

From the community

Discussion on the Fediverse

Replies from Mastodon and Bluesky — straight from the open web, no tracking.

Loading replies …

ENDE