HeroUI, a React component library
HeroUI is a library of ready made React components that spent its first years under the name NextUI. It changed more than the name: version three also changed the foundations it stands on. If you landed on an older tutorial, it almost certainly describes something that no longer works today.
Where the rename came from
The project started as NextUI and gathered most of its popularity under that name. The name turned out to be a problem, though, because people routinely took it for the official Next.js component library, which it never was. It works with Next.js exactly as well as with any other way of running React, and the association the name suggested was a pure misunderstanding.
Hence the change to HeroUI. The old @nextui-org/react package stopped at version 2.6.11, released in January 2025, and receives no further fixes. All development moved to @heroui/react, so if your project still carries the old package identifier, that is not a matter of taste but a lack of access to everything built since.
The heroui-inc/heroui repository now has over thirty thousand stars, and the library itself is entirely free, with no paid tier and no restrictions on commercial use. The license name, however, carries an ambiguity worth knowing before a dependency audit. The license file in the repository and the package metadata in the npm registry both declare MIT, yet the published version three package carries the Apache 2.0 text inside it. Second line packages carry MIT inside, consistent with everything else. GitHub's own interface also reports Apache 2.0, so the only place showing the actual state is the content of the downloaded package. Both licenses are permissive and neither blocks commercial use, so the difference stings mainly where someone compiles a list of dependency licenses and expects a single answer.
What version three actually changed
This is the most important part of this text, because the difference between two and three is not cosmetic. Dependencies, requirements, and the configuration approach all changed, and most of the material circulating online still describes the state before that shift.
Version two was a collection of several dozen separate packages. The umbrella @heroui/react pulled in @heroui/button, @heroui/card, @heroui/modal, and so on, and each could be installed individually to shrink the output bundle. The last release of that line carries the number 2.8.10 and dates from March 2026.
Version three collapsed all of it into a single package. Today's @heroui/react has only a handful of dependencies: its own styles package, a class variants library, one avatar primitive, and a few small things. The individual component packages stayed where they were, frozen on versions from the second line. An instruction saying "install just @heroui/button" will therefore pull year old code into your project, even though the package still exists in the registry and installs without the slightest complaint.
The demands on the surrounding environment also changed, and substantially. Version three declares React at nineteen or above, Tailwind CSS at four or above, and React Aria Components. Version two was content with React eighteen and Tailwind three. That is not a gap you cross by bumping one line in your dependency file.
The most surprising change is the disappearance of the animation library. Version two required Framer Motion as a peer dependency, and practically every tutorial starts by installing it alongside HeroUI. Version three does not list it among its requirements at all. An install command copied from an older article will therefore add a sizeable library that nothing reaches for.
What it is built on
It pays to understand what sits underneath, because that explains both the library's strengths and its limits.
The behaviour layer comes from React Aria Components, a set produced by the team designing interface systems at Adobe. That is the part handling keyboard interaction, focus management, screen reader messaging, and correct behaviour across different input methods. Writing that yourself and bringing it into line with accessibility guidelines is months of work, so leaning on a finished layer is the single biggest value here.
The visual layer is Tailwind. Styles are expressed through class variants rather than stylesheets bound to components, which reduces overriding an appearance to adding classes at the point of use. If your project already relies on Tailwind CSS, the library slots in without a separate styling system and without a second set of variables to maintain.
That construction also explains where HeroUI sits on the map of libraries. It is not a set of bare primitives without appearance, like Radix UI or Headless UI, because you get a finished, considered look. Nor is it a collection of files copied into your repository, like shadcn/ui, because you install a dependency and update it like any other. That choice cuts both ways: updates arrive on their own, but changing something the library did not anticipate calls for a workaround rather than an edit to a file.
Comparison with the alternatives
Three criteria are enough to line these libraries up: how the code is delivered, where the appearance comes from, and where the behaviour comes from.
| Library | Delivery | Default appearance | Behaviour layer | License |
|---|---|---|---|---|
| HeroUI | Dependency from the npm registry | Finished, coherent | React Aria Components | MIT declared, Apache 2.0 inside the v3 package |
| shadcn/ui | Files copied into your repository | Finished, editable in place | External primitives | MIT |
| Radix UI | Dependency from the npm registry | None, you style it | Own, built in | MIT |
| Headless UI | Dependency from the npm registry | None, you style it | Own, built in | MIT |
| Mantine | Dependency from the npm registry | Finished, coherent | Own, built in | MIT |
The conclusion from that table is simpler than it looks. If you want a finished appearance and updates that arrive on their own, HeroUI and Mantine remain, and the choice between them comes down to whether you style with Tailwind or prefer a separate styling system. If you want a finished appearance but the ability to open any file, you pick shadcn/ui and accept that updates are a manual job. If you have your own design system, you take primitives and avoid paying for a layer you would override anyway.
What migrating from version two looks like
If you decide to move, order matters, because trying to do everything at once usually ends in errors you cannot attribute to any particular change.
Start with React. Raising it to nineteen is independent of this library and worth separating, so that any trouble with other dependencies surfaces on its own. Only then take on Tailwind, since moving from three to four changes how the whole project is configured rather than just the components.
Once both foundations are in place, swap the package and remove from your dependencies everything that existed solely for the old version: individual component packages, the theme package, and the animation library. That step is usually more pleasant than it sounds, because a dozen or so entries disappear from the dependency file.
Finally, review the places where you overrode appearance through theme configuration. That is the part which will not carry itself across and needs rewriting for the new configuration approach. Overrides done with classes at the point of use survive the migration unchanged, so the more you worked that way, the less work remains.
Installation and first run
In version three, installation is a single command.
npm install @heroui/reactBefore you run it, check three things, because each of them can stop the project at build time. React must be at version nineteen or newer. Tailwind CSS must be at version four or newer. React Aria Components must be available too, since the library declares it as a peer dependency, so your package manager will report it missing if it is not there.
Checking versions is quicker than reading the dependency file.
npm ls react tailwindcss react-aria-componentsIf the project sits on React eighteen or Tailwind three, you have two routes. The first is raising both and moving to version three. The second is staying on version two, pinned explicitly in the dependency file, knowing that this line had its last release in March 2026 and that new components will not appear in it.
{
"dependencies": {
"@heroui/react": "^2.8.10"
}
}On a new project the decision barely exists, since everything above starts from current versions anyway. The problem only concerns code that already runs and had its dependencies settled long ago.
Theme configuration
Here too a change worth noting occurred, following directly from the move to Tailwind at version four.
In version two the theme was configured in the Tailwind configuration file, through a plugin listed in the plugins array, with colours described as a JavaScript object. Tailwind four moved configuration into the stylesheet, so the centre of gravity shifted here as well, from the configuration file to a CSS file. A separate styles package supplies the base layer, the variants, and the themes as ready stylesheets to import.
The practical conclusion is that a configuration example found in an older tutorial, with a plugin in the configuration file and a colour object, simply will not work in version three. Check the current form in the documentation, since this particular thing changed between releases more often than anything else.
The override mechanism itself stayed the same and is one of the library's better traits. Components accept Tailwind classes at the point of use and merge them with their own, resolving conflicts in favour of yours. You therefore do not fight selector specificity or reach for an exclamation mark in styles just to change one bit of spacing.
In its simplest form that looks like an ordinary prop carrying classes.
<Button className="bg-purple-500 hover:bg-purple-600">
Save
</Button>The second form is more interesting: instead of a string you pass a function receiving the component's state. That lets you describe the appearance for a pressed or hovered state without reaching for your own React state.
<Button
className={({ isPressed }) =>
isPressed ? 'bg-blue-600' : 'bg-blue-500'
}
>
Send
</Button>Learn that second variant before you start wrapping components in state of your own. A fair amount of the code written around such libraries exists only because its author did not know the internal state was available at the point of styling.
When it is worth it and when it is not
It is worth it if the project runs on Tailwind and you want a finished, coherent look without building a design system yourself. That is the most common sensible scenario. You get a full set of components that look like one whole, and you save weeks of work on things a user notices only when they are broken.
It is worth it too if accessibility is a requirement rather than a statement of intent. The behaviour layer from React Aria handles keyboard and screen reader support at a level you will not reach on your own within a reasonable effort. In public sector procurement and products for larger organisations, that can be the deciding argument.
It is not worth it if you already have a design system with settled components. Then a finished appearance is an obstacle rather than an advantage, and bare primitives without styling serve you better, since you avoid paying for a layer you would override entirely.
Nor is it worth it if the project cannot move to React nineteen and Tailwind four. Installing version two in that situation works, but ties you to a line no longer under development, and sooner or later you face the same migration anyway, with more code to carry across.
The last case is less obvious. If you need two or three components, the whole library is excessive. Individual packages used to help here, but version three does not have them, so with a need that narrow it is more sensible to take a single primitive or copy a finished component into your repository.
Common mistakes
The first is installing Framer Motion alongside the library because an older tutorial says so. In version three it is a redundant dependency, adding code to the output bundle that nothing reaches for.
The second is reaching for individual component packages. They look current, since they exist in the registry and install without error, but they contain code from the second line, and mixing them with the version three umbrella package ends in two versions of the styles inside one project and an appearance nobody designed.
The third is porting the theme configuration from the Tailwind configuration file unchanged. After the move to Tailwind four that form of configuration is no longer recognised, and the result is a full set of components in default colours and the impression that the theme was ignored, because it was.
The fourth is leaving the old package identifier in the project. An entry with the @nextui-org prefix still installs and still works, so nothing draws attention to it, but it points at code frozen in early 2025.
The fifth is assuming that upgrading from two to three is a number change in the dependency file. Given that requirements for React and Tailwind changed and the styling layer moved to a different package, this is a migration that needs planning rather than a routine update along the way.
FAQ
Is HeroUI the same thing as NextUI?
Yes, the same project after a rename. The @nextui-org/react package was frozen at version 2.6.11 from January 2025, and development continues in @heroui/react.
Is the library free?
Yes, entirely, and there is no paid tier and no restriction on commercial use. The license name is quoted two ways, though: the repository file and the npm registry say MIT, while the text shipped inside the version three package is Apache 2.0. Both are permissive, so nothing changes for usage itself.
Can I use HeroUI without Tailwind?
No. Tailwind is the styling layer here rather than an option to switch on, and version three requires it at version four or above.
Does version three require React nineteen?
Yes, it declares React and React DOM at version nineteen or above. On React eighteen you are left with version two, which is no longer under development.
Do I need Framer Motion?
Not in version three. Version two required it, and that is where the claim in older material comes from.
How do I check which version my project has?
With npm ls @heroui/react. A number starting with two means the old line with separate component packages, three means the new one.
Source code and releases live in the HeroUI repository, and current version numbers sit in the npm registry.