The recent release of Radix Themes piqued my interest but I feel some questions aren’t answered:
How does this solution compare to other UI component libraries, and how difficult is it to customize? How does it differentiate itself in this crowded market of React component libraries?
Background
Radix Primitives is a library of accessible, unstyled React components, initially released in 2020. They can be adopted independently, and styled using any approach: CSS classes, Tailwind, CSS-in-JS, etc.
I recommend reading the Introduction page of their docs to understand what they’re about if you’re not familiar with headless component libraries.
But to summarize quickly, these collections of components implement common UI patterns found on the web, that aren’t provided by the HTML spec, but are well documented and understood by the web development community.
There’s a number of other headless component libraries in the React ecosystem.
There’s React Aria, which focuses on accessibility with hooks and components for the patterns mentioned above, or Headless UI, which prioritizes compatibility with Tailwind.
Other frameworks also have similar libraries.
How to use unstyled components
How does it work in practice? Let’s look at some code adapted from the Radix Primitives docs:
import * as React from 'react';
import * as Popover from '@radix-ui/react-popover';
import './styles.css';
const PopoverDemo = ({ triggerContent, popoverContent }) => (
<Popover.Root>
<Popover.Trigger className="PopoverTrigger">
{triggerContent}
</Popover.Trigger>
<Popover.Portal>
<Popover.Content className="PopoverContent">
{popoverContent}
<Popover.Arrow className="PopoverArrow" />
</Popover.Content>
</Popover.Portal>
</Popover.Root>
);
export default PopoverDemo;
It’s quite straightforward:
- Import the building blocks of the pattern you want to implement, which, in this case, are exported as a compound component.
- Create the structure using the component parts you imported.
- Add styles, either with
className
as shown above, or with your preferred CSS solution.
An unstyled component library such as Radix Primitives lets you abstract away the accessibility rabbit-hole and focus on the differentiating factor of your application, instead of reimplementing patterns that really should be part of the HTML spec.
Overall, Primitives are an excellent choice for developers looking to implement their own design system.
Radix Themes
Moving on to Themes, an interesting release built on top of Radix Primitives.
It’s a bit hard to define, and determine where it falls in the component library market.
I’d like to say it’s a theming library for Primitives, but it appears be more limited than that. I’d want to compare it favorably to Theme UI, but the latter is fully customizable, while Themes restrict you to the following tokens:
If you’re expected to accept the look and feel of the components provided, in order to simplify development of simple pages and prototypes, I fear we’ll again see an endless stream of recognizable designs à la TailwindUI. A bunch of landing pages looking exactly the same, with slight differences in color schemes.
What if you want to build a completely different UI, using the Themes components, would it make any sense or should you use Primitives directly? Here’s what one of the co-founders of Radix UI had to say about the distinction between themes and primitives:
Totally, this is the idea. Primitives are great if you want full control to build your own design system from scratch. But a lot of folks are looking for something that helps them get started faster, with great design choices already baked in.
— Stephen Haney (@sdothaney) August 9, 2023
And here’s what the announcement stated about styles:
Let’s talk about styles.
— Radix by WorkOS (@radix_ui) August 8, 2023
1️⃣ Is Radix Themes a styling solution? – No.
2️⃣ Are you expected to write styles? – Sometimes, more if you feel adventurous.
3️⃣ I want to use Radix Themes with my favourite CSS tech. Will it work? – Yes!
So it’s not a styling solution, but you should be able to modify the components to fit your requirements.
Radix Themes in practice
After playing around with Themes in a quickly scaffolded React app, here’s my conclusion: while styling is possible, I wouldn’t say all components make it easy.
For example, changing the border color of the Card
component requires either overwriting or disabling box-shadow
on an ::after
pseudo-element using !important
, then setting a border on its child div
rather than the component itself.
You’ll need to put in some effort and dig into the source code or devtools to understand where and how the built-in styles are applied.
So it’s definitely not a styling solution for Radix Primitives, which I would have loved to see. Instead, it’s a themeable component library, limited in its customization options.
Conclusion
For a custom design, better use Primitives directly, along with a token-based styling solution provided by another library.
If, on the other hand, you’re happy with the look and feel of Radix Themes, and you’re trying to build something quickly, understanding that moving to your own design system later would require a rewrite to Primitives, Radix Themes might be a good pick.
As with all pre-styled component libraries, you’re gaining speed now in exchange of a larger maintenance burden later, should you decide to give your project its own visual identity.
The key is in understanding those trade-offs.