Introduction

A source-shipped component system you own, what it assumes about your app, and when it is the wrong choice.

@voila.dev/ui is a React component system distributed as source. When you install it, node_modules/@voila.dev/ui/src contains the same .tsx files the maintainers edit. There is no dist/, no build step, and nothing compiled ahead of time. A compiled bundle is a wall. Source is a door.

"We believe your product should own its UI all the way down. Not just the buttons — the email your user receives, the table they export, the map they explore. That's why we build the complex components everyone else tells you to buy as a SaaS: an email template editor that lives inside your app, a spreadsheet, a globe. Install them, read them, rebrand them, keep them."

Three claims follow from shipping source, and everything on this site ladders up to them.

Built for the AI era. Your coding agent (and you) can read, trace and rewrite every component, because the code sitting in node_modules is the real code. There is no black box for the model to hallucinate around; the code is the documentation. Prompts like "make the checkout use our brand" actually work, because the component is readable source the agent can open. The Working with AI page shows how to set that up.

Ownership, both ways. Use it as a real dependency: one bun add, lockstep versions across every package, updates for free. Or copy any file into your repo and make it yours. It is the same source either way, and you never have to choose on day one. The dependency mode is the argument that scales: the moment you run more than one product, pasted components become N forks to maintain, while a dependency is one version bump for every app you own.

Beyond primitives. Buttons and dialogs are table stakes. The add-on packages ship the product-level surfaces a SaaS actually needs: a drag-and-drop email template editor, an editable spreadsheet, a data table, charts with zero charting library, maps and a globe, composable filters, full landing-page sections. Build your email templates directly inside your application; that is the flagship proof that ownership extends past primitives.

What you get

  • 85 components in the core package, from primitives (Button, Input, Dialog) up to composed pieces (Sidebar, Chat, ProfileHeader, ImageCropper).
  • A semantic token layer. Every colour, radius and font is a CSS custom property, so rebranding does not mean forking components.
  • Add-on packages for the heavy things: charts, data grids, maps, filter bars, landing sections, an email block editor. Install only what you use.

What it assumes

AssumptionWhy
React 19The components use the current React APIs and are typed against React 19.
Tailwind CSS 4Styling is Tailwind utility classes; the tokens are a Tailwind 4 @theme.
A bundlerVite, Rspack, Turbopack, anything that compiles TypeScript and JSX.

If your setup ticks those three boxes, everything works. If it does not (a Webpack 4 app, a Tailwind 3 app, no bundler at all) this is the wrong library and no amount of configuration will make it a good fit.

When to reach for something else

  • You want a design system you never touch. This one is meant to be read and edited. Something compiled and versioned may suit you better.
  • You need a specific accessibility certification. The components build on Base UI and follow its patterns, but no formal audit has been done. Verify what you must guarantee.
  • You need React 18 or earlier. Not supported.

How the pieces fit

@voila.dev/ui

        ├── styles/tokens/*            the token contract (colors, type, motion)
        ├── styles/themes/*            six palettes; pick one, or write yours
        ├── components/*               the core components

        ├── chart/*
        ├── spreadsheet/*
        ├── map/*
        ├── filter/*
        ├── landing/*
        └── email-block-editor

One package, one version — every domain lives behind its own subpath. A clean line all the same: the tokens know nothing about components, the core knows nothing about the add-on domains, and each domain depends only on the core. Import only what you use; nothing else lands in your bundle.

Next: Installation.