Ark UI
The same headless components across React, Vue, Svelte and Solid
Ark UI implements its component logic as framework agnostic state machines and then ships thin bindings for React, Vue, Svelte and Solid. If you maintain interfaces in more than one framework, it is the only way to get identical behaviour in all of them.
One behaviour, several frameworks
Because the logic lives in state machines rather than in framework code, a dialog behaves the same in a Vue app as in a React app. For a design system serving several teams on different stacks, that is the whole argument.
The state machine model also makes the behaviour inspectable. Component state is explicit rather than scattered across effects, which makes unusual bugs much easier to reason about.
Where it costs you
The machine abstraction is another layer to learn, and the terminology does not match the rest of the React ecosystem. Developers who only ever ship React will find a React specific library more direct.
The catalogue is large but the community is smaller than Radix's, so unusual problems have fewer existing answers.
Reach for it when
- you ship the same design system to more than one framework
- you want component state to be explicit and inspectable
- you are building a component library rather than an application
Watch out for
- the state machine model is an extra concept to learn
- a React only team gains little over a React only library
- smaller community than the incumbents, so fewer existing answers
Compare with these
- UI componentsFree
shadcn/ui
Components you copy into your repository and then own outright
- react
- tailwind
- registry
MITRead - UI componentsFree tier
21st.dev
A searchable marketplace of community components with a prompt for each one
- react
- tailwind
- directory
Varies by component, most are MITRead - UI componentsFree
Radix Primitives
Unstyled, accessible behaviour for the components that are hard to get right
- react
- accessibility
- primitives
MITRead