Frontend / Guide
Headless, copy-in, or styled kit: pick the component source you can live with
A component library is a decision about who owns the markup, the design tokens and the accessibility work for the next several years. Library names change; the four ways of getting components do not. Decide the way first, and the name is usually obvious.
About 9 min read. Versions verified September 2026.
The verdict
For a product team on Tailwind, use shadcn/ui-style copy-in components on headless primitives - Radix or Base UI in React, Reka UI in Vue, Bits UI in Svelte - so the source lives in your repository and no upgrade can take a variant away from you. Take a styled kit such as Mantine or PrimeVue only for an internal tool where nobody will ever fight the design. Never start a new project on a runtime CSS-in-JS kit.
Four ways to get components
Every library on this page is one of these four, ordered by how much you own: headless primitives give you behavior and nothing else, copy-in gives you the source, a styled kit gives you a finished design you did not draw, and CSS-only gives you a stylesheet.
| Approach | What you install | Pick it when | Watch out for |
|---|---|---|---|
| Headless primitives | Unstyled, accessible behavior as a dependency: Radix, Base UI and React Aria Components for React; Ark UI for React, Vue and Solid; Reka UI for Vue; Bits UI for Svelte; Kobalte for Solid. | You have a design system of your own and want dialog, combobox and menu behavior done right without owning it. | Every pixel is your job. A primitive with no styling is a blank page for a team without a designer. |
| Copy-in source | A CLI that writes component files into your repository: shadcn/ui for React, shadcn-vue, shadcn-svelte, and Spartan for Angular. Each sits on a primitive from the row above plus Tailwind. | A product team on Tailwind that wants finished-looking components on day one and the freedom to edit them like any other file. | Upgrades are manual and the diff is yours. It assumes Tailwind. Copied components with local edits are a design system you now maintain. |
| Styled kit | A dependency with a complete visual design: MUI, Mantine, Chakra, Ant Design and HeroUI for React; PrimeVue, Vuetify and Nuxt UI for Vue; Angular Material and PrimeNG for Angular. | Internal tools, admin consoles and dashboards where a consistent look matters more than a distinctive one. | The theming ceiling. Past it you override the kit's tokens on every screen, and a major version can change those tokens under you. Bundle weight when you use four components. |
| CSS-only and web components | A stylesheet with no framework binding - daisyUI on Tailwind, Pico for classless HTML, Open Props for tokens - or custom elements such as Web Awesome, formerly Shoelace. | Content sites, server-rendered apps on Rails, Django, Laravel or htmx, and organizations running more than one framework. | CSS-only ships no behavior, so the combobox is still yours to write. Web components need care with server rendering, form participation and framework event binding. |
Gotcha: "headless" and "unstyled" are marketing words, not a guarantee. Radix, Base UI and React Aria ship real keyboard, focus and screen reader behavior. A kit that calls itself headless because it accepts a className is a styled kit with the styles removed.
React
React has the deepest field, which is why the four-way split matters most here. Three headless primitives, one copy-in layer and two styled kits cover nearly every real decision.
shadcn/ui
CLI 4.21 - the default for apps
The CLI copies component source into your repository, styled with Tailwind v4 and built on Radix or Base UI through the registry you choose at init. Right for most product teams; wrong for a team that will never touch the copied code. ui.shadcn.com
Radix Primitives
1.6 - one package since early 2026
Unstyled, accessible React components for the parts that are hard to get right: dialogs with focus trapping, menus with typeahead, comboboxes with correct ARIA wiring. Install the single radix-ui package and import what you need; the per-component packages are the legacy path. radix-ui.com
Base UI
1.8 - the MUI team's headless line
The Radix idea from the people who maintain Material UI, stable at 1.x since December 2025 and a supported shadcn registry target. The package is @base-ui/react; the older @base-ui-components/react is deprecated and frozen at a release candidate. base-ui.com
React Aria Components
1.21 - the deepest accessibility work
Adobe's component layer over the React Aria hooks: the most thorough keyboard, screen reader and internationalization behavior in React, including date pickers and number fields the others do not attempt. Pick it when accessibility is audited rather than assumed. react-spectrum.adobe.com
Mantine
9.6 - the styled kit without CSS-in-JS
A full kit - inputs, overlays, notifications, a data table, charts - styled with plain CSS modules and a PostCSS preset, so there is no runtime style injection to fight in the Next.js App Router. The best styled kit for React once you have decided not to own the components. mantine.dev
MUI
9.4 - Material, with strings attached
The largest React kit, and the MUI X data grid, date pickers and charts are why enterprise teams pick it. Styling still runs through Emotion, so the App Router needs the cache provider from @mui/material-nextjs and every styled component is a client component. Pick it when the data grid is the product. mui.com
Chakra UI 3.37 rebuilt itself on Ark UI at its third major, but still styles at runtime through Emotion, which puts it with MUI on the App Router question. Ant Design 6.6 is the densest kit here - pick it when the product is a data console and looking like every other Ant console is acceptable. HeroUI 3.2, formerly NextUI, is a styled kit on React Aria Components and Tailwind v4. Ark UI 5.39 is the headless option that also runs in Vue and Solid from the same Zag.js state machines - the pick when one design system has to cover more than one framework.
Vue
Vue's field is smaller and more settled. Two styled kits dominate internal tools, the official Nuxt kit covers Nuxt, and the copy-in model arrived through Reka UI.
PrimeVue
5.0 - styled or unstyled, your call
The most complete Vue kit, with a data table that is genuinely good. It ships styled components on a design-token architecture, an unstyled mode where the same components take Tailwind classes through pass-through props, and Volt, a copy-in Tailwind layer over the unstyled core. The right pick for an internal tool in Vue. primevue.dev
Nuxt UI
4.11 - Reka UI plus Tailwind v4
The official Nuxt kit, built on Reka UI primitives and Tailwind v4, with the formerly paid Pro components - dashboards, page sections, content layouts - folded into the free package at the fourth major. Pick it when you are on Nuxt and want a kit that matches the framework's conventions instead of one from a different world. ui.nuxt.com
Reka UI + shadcn-vue
2.10 and 2.8 - the copy-in model for Vue
Reka UI is the renamed Radix Vue: unstyled, accessible primitives with the same component list and mental model as Radix. shadcn-vue copies Tailwind-styled components onto it exactly as shadcn/ui does in React. Together they are the pick for a Vue product team that owns its design. reka-ui.com
Vuetify
4.2 - Material Design, all in
The oldest Vue kit and the most complete Material implementation outside Google. Everything is included and everything looks like Material, which is the appeal for an internal tool and the objection for a product. Pick it when the team has used it before and the design conversation is already over. vuetifyjs.com
Element Plus 2.14 is the Vue kit with the longest track record in large admin systems; treat it the way this page treats Ant Design. Naive UI 2.45 is the TypeScript-first kit with a clean default look and a built-in theme editor, worth a look for an admin tool that should not look like Material.
Svelte, Solid and Angular
Smaller ecosystems, same four-way split. Each has one headless primitive worth building on, one copy-in port of the shadcn pattern, and one or two styled kits.
Svelte
- Bits UI 2.19. Headless, accessible primitives built for Svelte 5 runes and the foundation under shadcn-svelte. The default primitive layer. bits-ui.com
- Melt UI 0.86. The original Svelte builder library, still pre-1.0. Its runes rewrite ships as the separate melt package, also pre-1.0, so prefer Bits UI for a new project. melt-ui.com
- shadcn-svelte 1.7. The copy-in port on Bits UI and Tailwind v4, at a stable 1.x. The pick for a Svelte product team. shadcn-svelte.com
- Skeleton 5.0. A Tailwind design system built on Zag.js with functional components for Svelte and React. The styled-kit option. skeleton.dev
Solid
- Kobalte 0.13. The headless toolkit for Solid, modeled on Radix and React Aria. Still pre-1.0, with a 2.0 line in alpha rather than shipped, so pin the version. kobalte.dev
- Ark UI 5.39. The same Zag.js components as the React and Vue packages, from @ark-ui/solid, and the more actively released of the two. ark-ui.com
- Styled kits. There is no Solid equivalent of Mantine. Copy in shadcn-style components on Kobalte or Ark UI and style them with Tailwind.
Angular
- Angular Material 22.1. The official Material kit on the Angular CDK, released in step with the framework. The CDK alone - overlays, drag and drop, virtual scroll - is worth installing even if you skip the Material styling. material.angular.dev
- PrimeNG 22.1. PrimeTek's Angular kit with the same styled and unstyled split, design tokens and strong data table as PrimeVue. The pick for an Angular internal tool that should not look like Material. primeng.org
- Spartan 1.4. The copy-in port for Angular: brain is the headless layer, helm the Tailwind-styled components the CLI copies in. The pick for an Angular product team on Tailwind. spartan.ng
Gotcha: in the smaller ecosystems, check the date of the last release before the feature list. A primitive that has not shipped since the framework's last big change - Svelte 5 runes, the Solid 2.0 release candidate, Angular's signal APIs - will cost you the upgrade it did not make.
Red flags before you install
Each of these shows up in the first month and costs a quarter to undo. Check for them in a spike branch first.
| Symptom | Cause and fix |
|---|---|
| Every screen carries an override block to make the kit match the design file | You are fighting a styled kit's design tokens. Either accept the kit's design and delete the overrides, or move to copy-in components on a headless primitive and draw the design once. There is no third option that stays maintainable. |
| Hydration errors, a client boundary around every component, or styles missing on first paint in a Server Components app | Runtime CSS-in-JS on React Server Components: the styles are generated during render, which the server component model does not allow. Prefer a kit styled with CSS Modules or Tailwind - Mantine, shadcn/ui, HeroUI - or confine the kit to client components behind its documented cache provider. |
| The README says accessible; Tab skips the dropdown and Escape does nothing | Accessibility claims never tested with a keyboard. Walk every component with Tab, Shift+Tab, the arrow keys and Escape, run axe on the rendered page, and read it once with VoiceOver or NVDA. The accessibility checklist has the full list. |
| The wrapper you installed pins its primitive a major version behind | A wrapper library that has not kept pace with Radix, Base UI or Bits UI will block your upgrade and inherit the old version's bugs. Use the primitive directly, or a copy-in port that tracks it, and treat a wrapper's dependency range as part of the review. |
| Four components in use and the kit dominates the bundle analysis | An all-in-one styled kit whose styling engine and theme load whether or not you use them. Read the bundle analyzer output before committing, and if four components is all you need, copy those four in from a headless primitive instead. |
| The company behind the library announced a paid tier and the free changelog went quiet | A single-company library pivoting to a commercial model. Copy-in source and MIT primitives are immune, because the code is already yours. For a dependency, prefer projects with more than one maintaining organization, and check the license of the extension packages you actually use. |
Our pick
Tailwind v4 and shadcn/ui for apps, plain CSS for content, one primitive family per team
The pick matches the CSS and UI layer: for an application, run Tailwind v4 with shadcn/ui components copied into your repository, on Radix or Base UI. For a content site, write plain CSS and skip the component library entirely - a blog does not need a combobox. A styled kit is right only for an internal tool where the design is not the product, and Mantine is the one to take in React because it brings no runtime CSS-in-JS.
One addition for teams that run more than one framework: pick a headless primitive family that exists in all of them and standardize on it. Ark UI ships the same components for React, Vue and Solid, and the shadcn ports - shadcn-vue on Reka UI, shadcn-svelte on Bits UI, Spartan on Angular - share one visual vocabulary with the React original. Either way the tokens, component names and accessibility behavior line up across codebases, and a designer signs off once.
Keep going
The styling half of this decision - Tailwind, CSS Modules or plain CSS - is on the CSS and UI layer, and Tailwind vs CSS Modules settles the utility-class argument on its own page. Once Tailwind wins, the Tailwind cheatsheet is the reference you will keep open.
Whatever you install, test it: the accessibility checklist is the keyboard and screen reader walk every component should pass before it ships, and the testing layer covers Storybook and visual regression for the components you now own. Still deciding which framework the components plug into? Start with how to choose a frontend framework.