Skip to content

Open source · MIT · zero dependencies

React components that work anywhere.

Any device. Any network. Any language. Any ability. Built for the conditions most component libraries are never tested against, and verified against all ten of them, in CI.

866 tests passing87 componentsZero dependencies

One value, three locales

English1.2MJan 1 – 5, 2026
हिन्दी12.3 लाख1–5 जन॰ 2026
العربية١٫٢ مليون١‏/١‏/٢٠٢٦ – ٥‏/١‏/٢٠٢٦

Same components, same props. Grouping, digits, calendar, and direction all come from the locale.

The bugs you cannot see

Every example below is real code running in your browser right now. The left column is what most applications ship, not a strawman, the actual line people write. The right column is this library. If you only read one section, read this one.

CompactNumber

हिन्दी

A K/M/B ladder is not how most of the world shortens numbers. India groups by lakh and crore; Japan and China group by ten-thousands.

What most apps ship

1.2M

`${(n / 1e6).toFixed(1)}M`

CompactNumber

12.3 लाख

compact-number

BidiText

العربية

A right-to-left name next to a number pulls the number to the wrong side of it. Here the naive version renders the reply count before the name instead of after. The sentence reads backwards, and only for users with RTL names.

What most apps ship

إيان - 42 replies

<span>{name} - {n} replies</span>

BidiText

إيان - 42 replies

bidi-text

SortableTable

Deutsch

Array#sort compares UTF-16 code points, not letters. Accented names file after Z, and lowercase files after uppercase.

What most apps ship

Zebra · apple · Ångström · Élodie

names.sort()

SortableTable

Ångström · apple · Élodie · Zebra

sortable-table

CurrencyField

Deutsch

parseFloat on a German-formatted amount silently truncates at the thousands separator. Twelve hundred euros becomes one euro twenty-three.

What most apps ship

€1.23

parseFloat("1.234,56")

CurrencyField

1.234,56 €

currency-field

Ten axes, every component

Each one is a real assertion in the test suite, not a claim in this paragraph. The whole library is 110 components and 11 primitives, with nothing between them and your project.

  • Performance

    Every item is bundled, minified, and gzipped with React external. It fails against its declared tier budget if it exceeds it.

  • Accessibility

    axe runs over every component in every state, plus what axe cannot see: focus moving to new errors, live regions mounted before they are filled.

  • Internationalisation

    Direction, calendar, numbering system, and week start come from the locale tag. Every string is a prop. RTL is a data change, not a rewrite.

  • Privacy

    A source scan forbids fetch, XHR, sendBeacon, and fingerprinting APIs across the whole registry. Nothing here phones home.

  • Security

    dangerouslySetInnerHTML, eval, and innerHTML assignment are forbidden registry-wide. sanitizeHref strips executable URL schemes.

  • Resilience

    ErrorBoundary contains a render crash to its own subtree with an announced, focusable, recoverable fallback.

  • Offline

    A component that makes no network calls cannot be broken by a dropped connection. ResilientForm goes further and replays.

  • SSR safety

    Every component renders through react-dom/server in CI. No reaching for window, document, or navigator during render.

  • Sensory safety

    Any file that animates must also reference prefers-reduced-motion, checked by the same static scan.

  • Supply chain

    Zero runtime dependencies. react is the only permitted import anywhere in the registry, enforced in CI.

Install one, or all of them

Components are copied into your repo by the shadcn CLI. No package to depend on, no version to upgrade, nothing to remove if you change your mind.

npx shadcn@latest add https://kata-ui-rho.vercel.app/r/async-boundary.json

Most component libraries are tested on the laptop they were written on.

~2.6 billion

are offline or intermittently connected

Requests do not fail loudly on a bad connection. They hang. The spinner spins forever, the user taps again, and now there are two orders.

~1.3 billion

live with a significant disability

The live region is created in the same tick its text appears, so no screen reader ever announces it. The code looks accessible. It is silent.

~6.5 billion

do not speak English as a first language

Layouts assume left-to-right, dates assume the Gregorian calendar, numbers assume Latin digits, and address forms assume American ones.

None of this is unknown. It is just never the default, so every team rebuilds the same handling badly, under deadline, and ships the version that worked where it was written.

Try it

Switch the network to Offline and submit the form. Your answers are kept and sent when the connection returns. Switch the language to العربية and the whole thing mirrors, including the calendar and the digits.

Simulated networkNetwork
LanguageLanguage

Nothing below is re-rendered by the switcher with different code paths. These are the same components reading the same APIs your users' browsers report.

AsyncBoundary

Four states, announced to screen readers, with height reserved so nothing jumps.

Your order shipped

3 days ago · August 29, 2026

$1,299.50

AdaptiveImage

On Save-Data or 2G it refuses to spend the user's data until they ask.

A small ship sailing toward the horizon at sunset

ResilientForm

Type something, then switch to Offline and press Send.

Locale facts

Direction, calendar, digits, and week start, all resolved from the tag, not hardcoded.

Direction
ltr
Calendar
gregory
Number
1,234,567.89
Date
Saturday, August 29, 2026

Accessible, translation-ready React components engineered for slow networks, cheap phones, and screen readers. Every component is verified in CI on ten axes: performance, accessibility, internationalisation, privacy, security, resilience, offline support, SSR safety, sensory safety, and supply chain.