Skip to content
8 min readSisyphos UI Contributors

Choosing a component library in 2026: the questions that actually matter

opinionarchitectureaccessibility

Picking a component library feels like a week-one decision, but you pay for it in year two. By then it is under every screen you have shipped, your team has internalized its idioms, and replacing it costs a quarter. So the evaluation deserves better than “the demo looked nice and the GitHub stars were high.” Having spent the last stretch building a component library — and, before that, years living with other people's choices — here are the questions we think actually separate libraries, roughly in order of how expensive the wrong answer is.

1. How do they prove accessibility — not claim it?

Every library's homepage says “accessible.” The word is free. Evidence is not, so go look for it:

  • Open the repo and search the test suite for role=, aria-checked, aria-expanded. A library that asserts keyboard and ARIA behavior in tests treats accessibility as a contract. A library with only visual snapshot tests treats it as a hope.
  • Take their dialog, unplug your mouse, and try to escape it. Focus trapped inside? Escape closes it? Focus returns to the trigger afterwards? Those three checks fail a surprising share of “accessible” libraries.
  • Check whether components force labels. A switch or icon button that renders happily with no accessible name is a component that will ship unlabeled a hundred times in your codebase. The better designs make you pass an aria-label or associate visible text.

This is the top of the list because accessibility debt is the hardest kind to retrofit: it is smeared across every screen, and by the time an audit or a lawsuit surfaces it, the fixes are application-wide.

2. What is the theming mechanism — and its runtime cost?

There are three architectures in the wild, and they fail differently:

  • Build-time theming (Sass variables, Tailwind presets). Fast at runtime, but the theme is frozen at compile time. Multi-tenant white-labeling means building N bundles or fighting the toolchain.
  • Runtime CSS-in-JS. Infinitely flexible, but you pay in serialization and style-recalculation work on the client, and it complicates server components and streaming SSR — the direction the React ecosystem has been moving for years.
  • CSS custom properties. The middle path: static stylesheets whose values are variables. Changing a theme is a handful of setProperty calls — no re-render, no runtime style engine, and it works identically in any framework.

The test we recommend: can you do this, at runtime, without a rebuild or a re-render?

the-white-label-test.tsts
// Load a tenant's brand at login, apply it instantly.
applyTheme({
  colors: { primary: tenant.brandColor },
  borderRadius: { md: tenant.rounded ? 12 : 4 },
});

If your roadmap contains the words “white-label,” “user themes,” or “dark mode,” this question outranks almost everything else. If it doesn't, build-time theming is genuinely fine — pick the simplest thing.

3. What does importing one component actually cost?

Ignore the marketing page number; measure the marginal cost. Create a scratch Vite app, import a single button, and build:

terminalbash
npm create vite@latest probe -- --template react-ts
cd probe && npm i && npm i <the-library>
# import ONE component in App.tsx, then:
npm run build   # read the gzip numbers, JS and CSS separately

Three things to look for in the output:

  • Does tree-shaking actually work? ESM barrels with no side effects shake well; libraries built around a runtime registry or CSS-in-JS engine often drag a fixed baseline in no matter what you import.
  • How does CSS arrive? One static stylesheet is cacheable and predictable. Injected style tags grow with usage and defeat CDN caching.
  • What are the peer dependencies? A date-picker that brings its own date library, an animation dependency you already have a different version of — the second copy of anything is pure waste.

4. What happens when your framework isn't forever?

Products outlive stacks. The acquisition that hands you an Angular codebase, the new team that insists on Vue, the rewrite you swore would never happen — the component layer is where those events get expensive. There are two honest hedges. Web-component libraries run anywhere, at the cost of rougher SSR and form integration. Multi-framework libraries with native bindings per framework keep the idioms (hooks in React, v-model in Vue, signals and ControlValueAccessor in Angular) while sharing a design contract underneath.

The follow-up question matters more than the checkbox, though: is the second framework a first-class citizen or a port? Check whether the bindings share a release cadence and — the real tell — whether the test suite is mirrored across frameworks or only the flagship gets behavioral tests. A binding without its own tests is a port, whatever the README says.

5. Can a coding agent use it correctly?

This question did not make evaluation lists two years ago. It belongs on yours now, because a meaningful share of your team's UI code will be written by Claude Code, Cursor, or Copilot, and those agents are only as good as the library's machine-readable surface. Concretely, check for:

  • An MCP server — ideally hosted, so the docs the agent reads are the docs that are live, not a snapshot frozen in an npm package.
  • Markdown docs endpoints or an llms.txt— HTML-only docs waste most of an agent's context window on navigation chrome.
  • A skills or rules filethat states the library's conventions, especially the negative ones (“there is no ThemeProvider”) that models will otherwise hallucinate from ecosystem averages.

A quick empirical test beats the checklist: ask your agent of choice to build a form with the library, then compile the result. Hallucinated props and phantom imports show you exactly how much correction tax you will pay per feature.

6. Who maintains it, and under what license?

Read the actual license, not the badge — “open source” sometimes means MIT components with the useful parts behind a paid tier, and pricing models change after you are locked in. Then look at the humans: how many people have merged code recently? What is the median age of open bugs? A library with one maintainer is a library one burnout away from becoming your team's responsibility. None of this predicts the future, but it prices the risk.

The honest map, including where we don't fit

Different answers to these questions point at genuinely different tools, and pretending one library wins every scenario is how vendors lose your trust. Our actual map:

  • Copy-paste collections (the shadcn/ui model) are the right call when you want to own and mutate every line and can accept that updates become manual merges. You are adopting source, not a dependency — that is a feature and a cost.
  • Headless primitives (Radix, React Aria, and kin) win when your design team wants total visual control and you have the budget to build the styled layer yourself.
  • Full design systems— Sisyphos UI's category — win when you want accessible behavior and a coherent visual language on day one, with theming as configuration rather than construction.

And to be concrete about our own limits: Sisyphos UI is a young project. If you need React Native, we have nothing for you. If your product lives and dies by a virtualized, pivot-table-grade data grid, dedicated grid vendors do that better than our Table aims to. If you need a decade of enterprise track record, we are not it yet — 33 components, three frameworks, and a mirrored 841-test suite is what we can show today, and you should weigh that exactly as skeptically as this article told you to weigh everyone else.

Whatever you pick, run the audit above on it first. Two afternoons of due diligence is the cheapest insurance in frontend engineering.