Radix Primitives: an unstyled React component library for accessible design systems
Radix Primitives is an open-source UI component library for building high-quality, accessible design systems and web apps. Maintained by @workos.
At a glance
- What is it?
- Radix Primitives is a low-level React component library focused on accessibility and customization, maintained by WorkOS. It is the base layer you style yourself, not a finished component kit, and its documentation lives on radix-ui.com rather than in the README.
- Who is it for?
- Adopt Radix Primitives if you are building a design system in React and want accessible behaviour handled below your styling layer; skip it if you want ready-made visuals or a non-React stack. Before committing, read the per-component docs at radix-ui.com/primitives/docs, since the README does not describe props or styling APIs, and check the releases page for the changelog because no release notes are bundled in the repository.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 53 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Radix Primitives actually solves
Most React component libraries make you choose between two bad options. You either accept someone else's visual design and fight it with overrides, or you build every dropdown, dialog and tooltip from scratch, including the parts nobody enjoys writing: focus trapping, keyboard navigation, ARIA attributes, and the edge cases where a screen reader announces something wrong.
Radix Primitives targets the second half of that problem. The README describes it as "a low-level UI component library with a focus on accessibility, customization and developer experience", and says the components can be used "either as the base layer of your design system, or adopt them incrementally". That word incremental matters. You are not adopting a framework or a theme. You install a package for one component, wire it up, and move on.
The audience is narrow and specific: engineers building an internal design system who already have opinions about how buttons and inputs should look, and who do not want to reimplement WAI-ARIA authoring practices for a context menu. If you are shipping a marketing site with three pages, this is more machinery than you need.
How the monorepo is organised and where the behaviour lives
The repository is a pnpm workspace, not a single package. The root package.json is marked "private": true and named "primitives" at version 0.1.0, which tells you the root is a build and test orchestrator rather than something you publish. The actual components live under packages/, and the build script filters on that path specifically: pnpm -r --parallel --filter "./packages/**/*" run build.
Around that core sit several supporting workspaces. apps/ holds runnable applications, including a Storybook instance and something the scripts call @repo/ssr-testing, which suggests server-rendering is exercised as a first-class case rather than assumed to work. e2e/ and playwright.config.ts cover browser testing, and the test:ci script chains unit tests, a Playwright browser install and the end-to-end run in one command. There is also an internal/ directory and a patches/ directory, the latter implying the project carries patches against some dependency.
This layout is worth understanding before you file an issue. A bug in a component is a change under packages/, and the release process is documented separately in release-process.md with changesets driving versioning through bump:stable and release:stable. The README itself says nothing about architecture; it points to radix-ui.com for documentation.
Installing the workspace and running the first component locally
The README's installation section is aimed at contributors rather than consumers. It tells you to install pnpm globally first, then install the dependencies. Note that the README does not give a consumer install command for individual component packages; for that you are directed to radix-ui.com/primitives/docs.
To work on the library itself, the README gives these two commands in order. The first installs the pnpm package manager globally. The second installs every workspace dependency from pnpm-lock.yaml. Neither is a consumer install; both assume you cloned the repository.
npm install -g pnpmpnpm installAfter the dependencies are in place, the root package.json exposes a dev script. It is an alias for the Storybook command, which runs the @repo/storybook workspace on port 9009 with the browser launch suppressed:
pnpm devThe port 9009 is fixed in the script, so if something else holds that port the command fails rather than picking another one. Once it is running, Storybook is where you see each primitive in isolation and where the accessibility checks are wired in: @axe-core/playwright is listed among the dev dependencies, and the end-to-end suite runs through Playwright against chromium, installed by e2e:install.
For a full verification pass, test:ci runs vitest, then playwright install --with-deps chromium, then the Playwright suite. That chain is the closest thing to an official definition of "this build is good".
What the README does not tell you
The README is thin, and it is worth being blunt about that. It contains no component list, no prop tables, no styling guidance, and no API examples. Everything a consumer needs sits behind a link to radix-ui.com/primitives/docs. If you are evaluating the library from the repository alone, you will not learn what a Dialog accepts or how composition works.
The same applies to versioning. The README points to a releases page for the changelog, and the repository carries no release entries in what is published here. The root package.json pins version 0.1.0, but that is the private workspace root, not the published component versions, so it tells you nothing about what is on npm. There is a .changeset/ directory and a bump:check script that runs changeset status --since=main, which is the mechanism the maintainers use to track pending version bumps, but that is a contributor workflow rather than a consumer-facing changelog.
The practical consequence: treat the documentation site as the source of truth and treat the repository as the build system. Do not assume the README will be updated when component APIs change.
Where Radix Primitives is the wrong choice
The library is unstyled by design, and that is a real cost, not a neutral fact. If your team does not have a designer or an existing token system, you will spend the first weeks deciding what a focus ring looks like rather than shipping features. A styled library gives you a starting appearance; this one gives you behaviour and leaves the rest empty.
It is also React-specific. The topics list on the repository includes react and component-library, and the workspace is TypeScript throughout, with a types/ directory at the root and a types:check script that runs typecheck across every package. There is no indication of a framework-agnostic or web-component build, so if you are on Vue, Svelte or plain DOM, this is not your library.
A third boundary is scope. The description calls it a component library for design systems, and the README calls it low-level. It is not a data grid, a charting library or a form-state manager. Reaching for it to solve application-level state problems will leave you disappointed, because that is not what the packages contain.
Finally, consider the maintenance signal honestly. The last push to the default branch was on 2026-08-08, and the repository is not archived. That is recent enough that the project is not dormant, but no release entries are published in the repository, so there is no way to state how frequently the published packages change.
How it differs from a styled component kit
The natural alternative for a React team is a component library that ships appearance and behaviour together, such as a themed kit you import and render with minimal configuration. The difference is not quality; it is where the boundary sits.
With a styled kit, the component owns its markup, its CSS and its accessibility behaviour, and you customise through props, theme objects or overrides. Upgrades can shift your visuals, because the library's styling decisions are part of your output. With Radix Primitives, the accessibility behaviour and the composition model are the product, and the visual layer is entirely yours. Upgrades should not change how anything looks, because the library never decided that in the first place.
That trade is only worth it if you have styling infrastructure to plug in. If you do not, the styled kit is the faster path and there is no shame in it. The README's own framing supports this: it positions the components as a base layer or an incremental adoption, which presumes you are bringing your own presentation.
Licence and what an upgrade actually involves
The repository is licensed under the MIT License, and both the README and the root package.json carry "license": "MIT", with the README adding "Copyright © 2022-present WorkOS". MIT is permissive: it allows commercial use, modification and redistribution provided the copyright notice and permission notice are retained. This is a description of the licence text, not legal advice; if your organisation has policies about attribution in distributed bundles, check them against the LICENSE file directly.
Upgrade cost is harder to estimate from the repository alone. The tooling suggests a structured release flow: changesets for version bumps, a bump:check script that reports pending changes against main, and separate stable and next release commands (release:stable and release:next, the latter publishing under the next tag). That is a well-defined pipeline, but it describes how the maintainers cut releases, not how disruptive an upgrade will be for you.
Because the components are unstyled, the surface area a version bump can break is smaller than in a themed kit: there is no CSS to drift. The risk concentrates in component composition and prop changes instead. The releases page linked from the README is where that would be visible, and the repository does not duplicate it.
Editorial conclusion
Adopt Radix Primitives if you are building a design system in React and want accessible behaviour handled below your styling layer; skip it if you want ready-made visuals or a non-React stack. Before committing, read the per-component docs at radix-ui.com/primitives/docs, since the README does not describe props or styling APIs, and check the releases page for the changelog because no release notes are bundled in the repository.
Frequently asked questions
What is Radix Primitives?
It is an open-source, low-level UI component library for building accessible design systems and web apps, written in TypeScript and licensed under MIT. The README describes it as usable either as the base layer of a design system or adopted incrementally.
How do I install Radix Primitives?
The README's installation section covers the repository itself: install pnpm globally with npm install -g pnpm, then run pnpm install for the dependencies. It does not give a consumer install command for individual component packages; that is directed to radix-ui.com/primitives/docs.
Does Radix Primitives come with styling?
No. The README calls it a low-level component library focused on accessibility, customization and developer experience, and positions it as a base layer rather than a finished visual kit. Any appearance you want is something you add yourself.
What React version or framework does Radix Primitives require?
The repository is TypeScript and React oriented, with react and component-library among its topics, but the README does not state a supported React version range. That detail would need to come from the documentation site.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/radix-ui-primitives)