krizaka-ui
Krizaka UI
Tokens, a Tailwind v4 preset, accessible primitives, icons and i18n — web and React Native.
The problem it removes
Three products, three token vocabularies, 1,153 light: overrides in one app.
Three products, three token vocabularies: we measured 1,153 light: overrides in one application, the same card written five times, and focus traps, keyboard handling and ARIA rewritten by hand in each kit.
- A theme implemented as
light:and dark: variants in every component — a new theme means touching all of them. - Accessibility rewritten per product, and wrong in at least one.
- A documentation site that describes last quarter's props.
What it does
- One semantic vocabulary,
--kz-*, compiled from design tokens — dark and light alike. - Accessible primitives with React Native parity, one entry point each.
- Every component's documentation generated from its code.
One semantic vocabulary (--kz-*) compiled from design tokens, a preset that turns it into Tailwind utilities, and primitives — button, card, dialog, field, tabs, toast, command palette… — with React Native parity, one entry point each. The documentation of every component is generated from its code.
The owl reads the code, not a wiki: every component's page on krizaka.com/docs/ui is generated from its
meta.tsand its named examples, and the registry tests fail when one is missing.
Decisions and trade-offs
We chose
One token vocabulary; dark on
:root, light onhtml.light; a brand overrides values (brands/scoped.css).We refused
light:/dark:variants in components, and a token set per product.Because
A theme or a brand is a set of values: Orazaka's orange and Orochia's violet use the same components as this site.
What it costs you
Components read
var(--kz-*)only; raw palette colours are refused by the lint rules.We chose
Radix for every non-trivial interaction, variants with tailwind-variants, every story audited by axe in dark and light on each pull request.
We refused
Hand-written focus traps and keyboard handling.
Because
Accessibility is written once and tested where it is written.
What it costs you
Radix in your bundle; size-limit budgets per entry keep it in check.
We chose
Words arrive as props; no translation function inside the library.
We refused
Bundling a translation runtime.
Because
Any i18n works — ours (
@krizaka/i18n, typed catalogues and a CI check) or yours.What it costs you
You pass the labels.
We chose
A ratchet: per-repository counters of raw palette classes,
light:variants,[var(--…)]utilities and className templates that may only go down.We refused
A big-bang migration, and a lint rule switched on at once.
Because
An existing application adopts it screen by screen without letting the debt grow back.
What it costs you
A
lint-ratchet.jsonto commit and a check in CI.
In code
/* globals.css — your brand is values, never components */
@import "tailwindcss";
@import "@krizaka/tailwind"; /* tokens + utilities + motion signature */
@import "@krizaka/ui/tailwind.css";
:root { --kz-accent: hsl(152 62% 40%); } /* dark is the default */
html.light { --kz-accent: hsl(152 70% 30%); }
// Save.tsx — one entry point per primitive: an app ships only what it imports
import { Button } from "@krizaka/ui/button";
export function Save({ label }: { label: string }) { // words arrive as props: any i18n works
return <Button variant="primary">{label}</Button>;
}Don't use it when
- You don't use Tailwind v4: the preset requires it (the tokens alone are plain CSS variables).
- You want an unstyled kit and own every pixel: use Radix directly.
- You need charts today:
@krizaka/chartsis being built.
Where it stands
@krizaka/ui, tokens and tailwind 2.2.0 on npm (latest) — 2.2.0 brought the five birds of this page (@krizaka/ui/mascots); icons, i18n, intl and config 0.1.0. Supported: majors N and N-1, fixes for six months after N+1.
Published
@krizaka/ui · @krizaka/tokens · @krizaka/tailwind 2.2.0 · npm@krizaka/icons · i18n · intl · config 0.1.0 · npmIn progress
@krizaka/charts— theme- and brand-aware charts on Apache ECharts, each with an accessible data table, and the effects and blocks after it: the roadmap is an open epic.krizaka-ui#49
Adopt it
npm install @krizaka/ui @krizaka/tailwind @krizaka/tokens tailwindcss
# the debt counters of an existing app (raw palette, light:, [var(--…)], className templates):
npx -p @krizaka/config krizaka-ratchet --json --root .Tell us where it hurts.
A block is right when it survives your code base, not ours. Ask in the block's thread, propose a change as an idea, or report a bug on its repository — every decision on this page is open to a better argument.
The other blocks
- Platform kitAn event published after the commit is lost on the next crash.
- UsersSign-up looks like a weekend. Reset tokens, OAuth and JWTs make it a quarter.
- NotificationsAn e-mail sent inside a transaction that rolls back can't be unsent.
- Billing & creditsDebit after and the work ran on credit nobody had. Debit before and failures get billed.
- Build, BOM & test kitParent POMs drift — and a Spring BOM silently overrides the Boot version you chose.