Library / SDK
chakra-ui/ark avatar
chakra-ui/ark

chakra-ui/ark: one component library, four frameworks, and no opinions about how it looks

Unstyled, accessible UI components for your design System. Works in React, Vue, Solid, and Svelte.

5,394 stars217 forksTypeScriptMIT

At a glance

What is it?
Ark UI puts Zag.js state machines behind an unstyled React, Solid, Vue and Svelte API, so accessibility is somebody else's already-solved problem.
Who is it for?
Ark UI exists because accessibility is a solved problem that thousands of teams keep solving badly. The bet is that behaviour is the reusable part and appearance is not, so the project ships the behaviour once, as Zag.js state machines, and exposes it through one identical API in four frameworks.
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 14 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 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The split between behaviour and appearance

Ark UI is described as a headless component library providing the foundation for building accessible design systems and web applications. The word headless is doing the work here. There is no theme, no colour palette, no spacing scale and no default button colour. What you get is state, attributes and event handlers.

The README lists its reasons under a heading that asks why Ark UI, and the seven items are specific enough to check. Completely unstyled means zero styling opinions, and the project names the styling options it expects you to bring instead, CSS-in-JS, Tailwind, or vanilla CSS. Accessibility first is stated as WCAG compliant components tested with real assistive technologies out of the box, and the accessibility section expands that into ARIA attributes and roles, keyboard navigation, focus management, screen reader announcements and RTL support.

The remaining items are about architecture: state machine powered behaviour via Zag.js finite state machines, the same API across React, Solid, Vue and Svelte, truly composable granular primitives, production readiness with Chakra UI named as a product built on it along with teams at OVHCloud and PluralSight, and full TypeScript typing.

That is a coherent position. The library decides what a combobox does, and you decide what a combobox looks like. It is a narrower claim than a component library usually makes, which is exactly why the package works in four frameworks at once.

One install per framework, four parallel packages

Installation is a matter of picking the package that matches your framework, and the README shows all four in one block.

bash
# React
npm install @ark-ui/react

# Solid
npm install @ark-ui/solid

# Vue
npm install @ark-ui/vue

# Svelte
npm install @ark-ui/svelte

The monorepo layout in the root package.json confirms this is a workspace with packages/*, templates, scripts and website as members, which means the four frameworks are built and tested side by side rather than one being a port of another after the fact. The repository tree agrees, with a packages directory, a templates directory, a website directory and a scripts directory.

Two things in that root manifest are worth noting because they describe how the project guarantees its central promise. There is a check:zag script and a check:anatomy script, alongside check:exports and check:publish-exports. The first of those is the important one. Since every component is supposed to derive its behaviour from a shared Zag.js state machine, a script that verifies components have not drifted from their machines is exactly the guard rail the approach needs.

There is also local:sync, local:sync:full and local:sync:revert, which is the standard mechanism for developing one framework package against local builds of the others rather than against published versions.

What identical API across four frameworks means in practice

The README proves the parity claim by showing the same Dialog in all four languages, and it is genuinely the same component tree in each case.

tsx
import { Dialog } from '@ark-ui/react/dialog'

export const MyDialog = () => (
  <Dialog.Root>
    <Dialog.Trigger>Open Dialog</Dialog.Trigger>
    <Dialog.Backdrop />
    <Dialog.Positioner>
      <Dialog.Content>
        <Dialog.Title>Dialog Title</Dialog.Title>
        <Dialog.Description>Dialog description</Dialog.Description>
        <Dialog.CloseTrigger>Close</Dialog.CloseTrigger>
      </Dialog.Content>
    </Dialog.Positioner>
  </Dialog.Root>
)

The Vue version differs only in that the same markup sits inside a template block and the import uses the vue package. The Solid and Svelte versions keep the component structure as well, with Svelte putting the markup at the top level of the file rather than inside a function.

Read the structure carefully, because it explains the design. Dialog.Root, Trigger, Backdrop, Positioner, Content, Title, Description and CloseTrigger are separate exports that you place yourself. Ark UI is not giving you a dialog, it is giving you the parts of a dialog and the machine that decides which parts should be present and what attributes each one needs right now. CloseTrigger is rendered only when the machine says a close is available, for example, and FocusTrap does its work because Content tells it where to trap.

The zero styling section makes the same point with three one-line variants of Dialog.Trigger, one with a Tailwind className, one with a css prop, one with a plain semantic class. Same component, same behaviour, three styling systems.

Forty five primitives and what is in the list

The component count is stated as 45 or more production ready components, grouped into four categories, and the grouping is more informative than the number.

Layout and navigation covers Accordion, Tabs, Splitter, Steps, Tree View and Tour. Overlays covers Dialog, Popover, Tooltip, Hover Card, Bottom Sheet and Floating Panel. Data display covers Avatar, Highlight, Progress, QR Code, Format, JSON Tree View and Marquee. Utilities is the largest group and includes Portal, Presence, Focus Trap, Frame, Collection, Listbox, Clipboard, Toast, Timer, Download Trigger and Client Only.

Forms and inputs is the longest single list: Checkbox, Radio Group, Select, Combobox, Number Input, Pin Input, Tags Input, Editable, File Upload, Color Picker, Date Picker, Password Input, Signature Pad, Slider, Angle Slider, Rating Group, Switch and Toggle or Toggle Group.

The utilities list is where the design shows. Presence, Frame and Collection are not widgets you would see in a screenshot, they are the plumbing a headless library needs so that an animation, a positioning context or a virtualized list behaves correctly. Offering them as public API is a deliberate choice, and it is a good signal about who this is for. Someone building a design system wants these primitives. Someone building one dialog does not need them and would be better served by a styled library.

The tree view, JSON tree view, signature pad and rating group are also newer or less common entries, which tells you the catalogue is still filling in. The roadmap lives on a separate Canny board linked from the README navigation.

How releases actually ship

This is a monorepo with independently versioned framework packages, and the release history shows three different version lines published within seconds of each other on 2026-09-13: @ark-ui/vue at 5.39.2, @ark-ui/svelte at 5.24.2 and @ark-ui/solid at 5.39.2.

The Svelte package is behind the others, which is the clearest signal in that list about framework parity. Same architecture, same promises in the README, and the version numbers tell you Svelte receives fewer of the primitives or less frequent fixes.

The changelogs are unusually specific, which is worth rewarding. Version 5.39.2 across frameworks fixes missing hotkeys and interaction entrypoints from the published exports map, and the explanation is genuinely instructive: the build files shipped, but the publish config maintains its own exports map and was never updated when those primitives were added, so importing useHotkeys from the react package failed with ERR_MODULE_NOT_FOUND. That is the kind of bug a build pipeline hides until someone installs from npm, and the entrypoints are now included for every framework.

Version 5.39.1, from 2026-08-28, is a one line fix for NavigationMenu.Content throwing document is not defined during server side rendering. Version 5.39.0, from 2026-08-21, adds a Toc component for tables of contents that track which headings are in view as the reader scrolls, with a scrollEl option for content inside a container rather than the page.

The Solid changelog for the same version is the most detailed of the three, and it documents an API change rather than only a fix. ItemContext.selected was staying false after selection because the render prop kept its first render value; it is now an accessor, so the guidance is to read item().selected instead of item.selected. That is a breaking change to how you call it, shipped in a patch version.

The toolchain and what it tells you about the project

The root package.json is a good map of how this codebase is developed, and it is a modern one.

Bun is the runtime, evidenced by bun.lock, bunfig.toml, the type module declaration and scripts written as bun run. Changesets handle versioning and publishing, with @changesets/cli at 3.0.3, a .changeset directory, and a version script that runs changeset version followed by a postprocess step over the changelogs. Biome handles linting and formatting at 2.5.14, with a biome.json at the root. Lefthook manages git hooks and is installed on postinstall. Renovate handles dependency updates. Shiki provides syntax highlighting for the docs site at both 4.4.3 for languages and themes.

The test and verification scripts are the interesting part. Tests run sequentially across workspaces rather than in parallel, which is slow and deliberate, since these packages share a behavioural source of truth and parallel runs would hide ordering problems. Linting and typechecking fan out across every workspace. The check scripts cover anatomy, exports, publish exports and zag.

Two entries in the tree suggest a project that has thought about AI tooling in a considered way rather than bolting it on. There is a .claude directory, a .cursor directory, a CLAUDE.md file and a TONE_OF_VOICE.md. The repository also has CONTRIBUTING.md, a CODE_OF_CONDUCT.md, a .storybook directory and a .vscode directory. With 5,394 stars, 217 forks and only 15 open issues, the issue queue is unusually small for a project of this activity level, and the last push was on 2026-09-22 with no archival.

Editorial conclusion

Ark UI exists because accessibility is a solved problem that thousands of teams keep solving badly. The bet is that behaviour is the reusable part and appearance is not, so the project ships the behaviour once, as Zag.js state machines, and exposes it through one identical API in four frameworks. That bet is visible in the codebase rather than asserted: a check:zag script exists in the root package.json precisely to catch a component drifting away from its machine, which is the maintenance cost of the approach and the evidence that it is maintained. What you give up is everything a styled library gives you for free, including the theme layer, the props shortcuts and the visual coherence that makes a product look designed. Those are real costs, not nitpicks. Start with one component, Dialog or Select, apply your own styles to it, and see whether the machine plus your CSS produces a result you would rather own than borrow. The packages are versioned independently by framework, they move every few weeks, and the last push was on 2026-09-22.

Frequently asked questions

What is Ark UI and is it related to Chakra UI?

Ark UI is an unstyled, accessible component library in the chakra-ui GitHub organization, and it is the headless foundation that Chakra UI itself is built on. Ark UI ships no styles at all and instead provides state and accessibility behaviour through Zag.js state machines, so you bring your own CSS.

Which frameworks does Ark UI support?

React, Solid, Vue and Svelte, each as its own package: @ark-ui/react, @ark-ui/solid, @ark-ui/vue and @ark-ui/svelte. The README shows the same Dialog component tree in all four languages, and the packages are versioned and released independently.

How many components does Ark UI provide?

45 or more production ready components, grouped into layout and navigation, overlays and dialogs, forms and inputs, data display, and utilities. The utilities group includes the plumbing primitives such as Portal, Presence, Focus Trap, Frame and Collection that a design system usually needs.

Does Ark UI ship any styles or can I use Tailwind?

It ships no styles, which is the point. The README explicitly says to bring your own with CSS-in-JS, Tailwind, vanilla CSS or any other solution, and shows Dialog.Trigger styled three different ways, with a Tailwind className, a css prop and a plain semantic class.

How do Ark UI packages get versioned and released?

Through Changesets, with each framework package versioned independently. On 2026-09-13 the vue, svelte and solid packages all published within seconds of each other, with vue and solid at 5.39.2 and svelte at 5.24.2, which shows svelte trails the others. Tests also run sequentially across workspaces rather than in parallel.

Official sources

  1. chakra-ui/ark on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/chakra-ui-ark.svg)](https://hysenlabs.com/projects/chakra-ui-ark)