ZUI Is a CSS Library That Refuses to Be a Framework’s Prisoner
A close look at how ZUI uses CSS Layers, OKLCH color, shared controllers, and thin wrappers to make one design system work across many runtimes.
- ZUI treats CSS as the source of truth, then uses framework wrappers as adapters instead of making React or Vue the center of the system.
- Its cascade strategy is the architecture: CSS Layers, generated tokens, and OKLCH color let the library stay predictable without leaning on heavy runtime logic.
- Shared variant maps and vanilla controllers keep behavior consistent across frameworks, which reduces drift more effectively than copying component code per platform.
- The repo feels unusually mature because the tooling, ADRs, and DX extensions all point toward a system meant to survive framework churn.
The browser, not the framework, is the product
Most UI libraries start with a framework and then spread outward. ZUI flips that order. It treats the browser as the runtime, then builds thin adapters for React, Astro, Solid, Svelte, and Vue around a shared CSS core.
That matters because it changes where truth lives. In ZUI, the design system is not trapped inside React props or a framework-specific component API. It sits in CSS layers, tokens, and shared variant logic that every wrapper can reuse.
That is the core thesis of the repo: ZUI is not trying to win by being the biggest component kit. It is trying to make the styling and behavior model portable enough that the framework becomes incidental.
Why CSS Layers are the real architecture
@layer zui.reset, zui.base, zui.components, zui.utilities;
@layer zui.base {
:root {
--space-2: 0.5rem;
--radius-md: 0.75rem;
}
}
The cascade order is explicit, and that is the point. ZUI does not hope that specificity behaves. It declares the order up front: reset, base, components, utilities. Utility styles can override component defaults without a battle.
That is a small technical choice with a big product effect. It means the system is easier to reason about, easier to extend, and less likely to collapse into override spaghetti as teams customize it.
Tokens, OKLCH, and the auto-color trick
ZUI’s color work is not a decorative layer on top of the system. It is the system. The repo uses generated color tokens in OKLCH, which matters because OKLCH is built for perceptual consistency. Hues can vary without the palette falling apart visually.
The sharpest example is the auto-color behavior. Instead of asking each consumer to pick a text color manually, ZUI can infer readable foreground color from the background’s lightness and alpha. That turns a common accessibility chore into a browser-level calculation.
:root {
--button-bg: oklch(0.72 0.16 260);
--auto-color: oklch(from var(--button-bg) calc(l < 0.55 ? 0.98 : 0.12) 0 0);
}
The exact implementation is more nuanced than the sketch above, but the idea is simple: let CSS do the work. The less state that needs to live in JavaScript, the less state can drift across frameworks.
| Problem | Traditional approach | ZUI approach |
|---|---|---|
| Readable button text | Pick a text color by hand or in JS | Compute foreground behavior from the token itself |
| Palette consistency | Hand-maintained shades across components | Generated OKLCH tokens with a shared system |
| Accessibility logic | Repeated in each component wrapper | Centralized in the CSS source of truth |
One variant map, many frameworks
ZUI’s component wrappers look thin because the interesting part happens before the framework layer ever renders anything. Shared variant definitions, built with CVA, map props like size and variant to the same class logic across environments.
That means a button in React and a button in Astro do not each invent their own idea of what primary or large means. They both consume the same variant source, so design intent stays aligned even when the runtime changes.
import { cva } from 'class-variance-authority';
export const buttonVariants = cva('zui-button', {
variants: {
variant: {
primary: 'zui-button--primary',
ghost: 'zui-button--ghost'
},
size: {
sm: 'zui-button--sm',
lg: 'zui-button--lg'
}
}
});
This is where the repo’s philosophy becomes practical. Cross-framework consistency is not being enforced by documentation or discipline alone. It is being encoded into the shared variant layer.
| Dimension | Framework-first kit | CSS-first ZUI |
|---|---|---|
| Source of truth | Component props and framework APIs | Shared CSS tokens and shared variant maps |
| Framework dependence | High | Low |
| Cross-framework drift | Likely | Reduced |
| Behavior reuse | Often duplicated per wrapper | Shared once, consumed everywhere |
The controller pattern keeps behavior from drifting
The same logic applies to behavior. For more complex components like AppShell, ZUI uses vanilla TypeScript controllers so the interaction model lives outside any one framework. The wrapper becomes a shell around behavior instead of the owner of behavior.
That is a smart trade-off. Framework-specific state often drifts over time because each wrapper grows its own edge cases. A shared controller keeps keyboard shortcuts, layout state, and resize behavior consistent no matter which runtime mounts it.
class AppShellController {
constructor(root: HTMLElement) {
this.root = root;
this.restoreState();
this.bindResizeObserver();
}
restoreState() {
const collapsed = localStorage.getItem('sidebar-collapsed') === 'true';
this.root.dataset.collapsed = String(collapsed);
}
}
The pattern is boring in the best way. A framework wrapper instantiates the controller, then gets out of the way. That keeps logic portable and makes the browser itself feel like the execution layer.
The small details that make it feel native
ZUI also leans on browser-native primitives where it can. Dialog and popover behavior is handled with the platform in mind, not with a heavyweight abstraction by default. That trims the amount of code needed for common UI interactions.
The no-flash hydration detail is especially telling. Restoring local state before the main bundle takes over prevents the visible layout jump that often makes cross-framework UI feel brittle. It is a small polish move with outsized perceived quality.
The components are also polymorphic where that helps the user. If a button is actually a link, it can behave like one. That kind of detail makes a system feel native instead of merely styled.
| Pattern | Why it matters | What ZUI does |
|---|---|---|
| No-flash hydration | Avoids visible layout jumps | Restores state early from localStorage |
| Native popover and dialog | Reduces custom overlay logic | Uses platform primitives when possible |
| Polymorphic components | Matches semantic intent | Switches between link and button behavior |
What ZUI is really competing against
The competition here is not just another component library. It is a set of architectural defaults. React-first kits make the framework the center. Utility-first stacks often push consistency into class composition. Older CSS libraries can be portable, but they usually lack the layered token and behavior model ZUI is aiming for.
| Approach | Center of gravity | Strength | Weakness |
|---|---|---|---|
| React-first component kits | Framework API | Fast adoption inside one ecosystem | Drift and lock-in across runtimes |
| Utility-first stacks | Class composition | Flexible styling | Behavior and state still need structure |
| Traditional CSS libraries | Stylesheets | Framework agnostic | Often too blunt for modern component behavior |
| ZUI | Shared CSS and shared logic | Portable design system with thin adapters | Depends on modern browser capabilities |
That last row is the real story. ZUI is not trying to win by being the most universal in the abstract. It is trying to be portable in the places that matter: styling, tokens, state, and component behavior.
Why this repo feels unusually mature
The tooling tells the same story as the code. ADRs, a ubiquitous language document, semantic-release, Biome, a VS Code extension, and a Raycast extension are not cosmetic extras. They are signs that the project is being built as a system, not as a collection of demos.
That matters because design systems often fail at the seams between implementation and maintenance. ZUI looks intentionally organized to reduce seam friction before it becomes technical debt.
If the thesis holds, the long-term bet is simple: the browser changes more slowly than frameworks do. A UI library that treats CSS as architecture is betting on the slower-moving layer of the stack.