One Mitosis source. React, Vue, and React Native output. 204 production-grade components.
Explore the live component gallery →
BitCode UI is a cross-framework component library built on Mitosis.
Every component is authored once as a .lite.tsx source file and compiled into
idiomatic React, Vue 3, and React Native output. No forked codebases, no drifting
APIs between frameworks.
The library was built for BitCode, a JSON-driven low-code platform, which means the component contracts are shaped by real ERP screens — data tables with server-side pagination, schema-driven forms with reactive field rules, kanban and gantt views, print previews, and media viewers — not by a generic design-system checklist.
The live gallery renders all 204 components in 620 demo sections, with a searchable sidebar and light/dark theming.
src/components/**/BcXxx.lite.tsx ← the only source of truth
│
├─ Mitosis ──▶ output/react/src/ React 18+
├─ Mitosis ──▶ output/vue/src/ Vue 3
└─ Mitosis ──▶ output/react-native/src/ React Native + NativeWind
This package is consumed as source (no dist build step for consumers). Clone it
next to ui-schema, which holds
the portable schema, expression, and block-catalog types it depends on.
# The two repos must be siblings — ui-schema is a `file:../ui-schema` dependency.
git clone https://github.com/bitcode-framework/ui-schema.git ui-schema
git clone https://github.com/bitcode-framework/ui.git ui
cd ui
npm install
npm run build # compiles all four targets into output/Then run the demo app:
cd demo-app
npm install
npm run dev # http://localhost:3002Or produce a static build:
cd demo-app
npm run build
npx vite preview --port 3005Note on
npm run build. Always use the full script, never a baremitosis build. The script chains four post-steps — adapt overrides, regular.tsmirroring into every target, React output reformatting, and index generation — and skipping them leavesoutput/in a state that downstream bundlers cannot parse.
| Target | Path | Consumed by |
|---|---|---|
| React 18+ | output/react/src |
Vite, Next.js, Tauri |
| Vue 3 | output/vue/src |
Vite |
| React Native | output/react-native/src |
Metro + NativeWind v4 |
| Stencil (frozen) | output/stencil/src |
Legacy Web Components consumers |
Import through the per-target entry points:
import { BcButton, BcDataTable } from '@bitcode/ui/react';
import { BcButton, BcDataTable } from '@bitcode/ui/vue';
import { BcButton, BcDataTable } from '@bitcode/ui/native';Shared, framework-neutral logic lives in src/core and is exposed directly:
import { configure, applyTheme, onThemeChange } from '@bitcode/ui/core/context';
import { ReactiveStore } from '@bitcode/ui/core/reactive';
import { resolveAdapt } from '@bitcode/ui/core/adapt';
import { BcI18n, AppConfigStore } from '@bitcode/ui/core/providers';The public barrel exports 204 symbols from 16 component groups.
| Group | Count | Highlights |
|---|---|---|
| Forms | 42 | BcForm (reactive fields), BcSelect, BcCombobox, BcCascader, BcTreeSelect, BcDateField, BcColorPicker, BcOtp, BcSignature, BcDropZone |
| Charts | 29 | ECharts-backed: line, bar, pie, radar, sankey, treemap, sunburst, candlestick, gauge, heatmap, theme-river, plus BcKpi and BcSparkline |
| Primitives | 18 | BcBox, BcFlex, BcStack, BcGrid, BcCenter, BcSeparator, BcVisuallyHidden |
| Navigation | 16 | BcMenubar, BcMegaMenu, BcNavigationMenu, BcBreadcrumb, BcPagination, BcSteps, BcAnchor |
| Overlays | 16 | BcDialog, BcDrawer, BcPopover, BcCommand, BcContextMenu, BcTour, BcWizard, BcToast |
| Data display | 12 | BcDescriptions, BcTimeline, BcTree, BcAccordion, BcCarousel, BcEmpty, BcQRCode |
| Layout | 10 | BcCard, BcSection, BcSplitter, BcHeader, BcSidebar, BcAffix, BcWatermark |
| Views | 10 | BcDataTable, BcKanbanBoard, BcViewGantt, BcViewMap, BcViewReport, BcViewEditor, BcRenderer |
| Media | 9 | BcViewerPdf, BcViewerImage, BcViewerVideo, BcViewerAudio, BcViewerYoutube, BcViewerInstagram, BcViewerTiktok, BcGalleria |
| Feedback | 8 | BcSkeleton, BcSpinner, BcLoadingOverlay, BcResult, BcBackdrop, BcTour |
| Data | 7 | BcCalendar, BcKanban, BcChip, BcStatistic, BcMeterGroup |
| Social | 6 | BcChatter, BcActivity, BcFavorites, BcTimelineSocial, BcNotification |
| 5 | BcPrint, BcPrintPreview, BcExport, BcReportLink |
|
| Builders | 4 | BcBuilder, BcFormBuilder, BcSchemaBuilder, BcWorkflowBuilder |
| Content | 1 | BcMarkdown |
| Input | 1 | BcInput (shared input shell used by the Forms group) |
Full per-component documentation lives in docs/ — one Markdown file per
component, covering props, slots, events, and accessibility notes.
Every component is classified by tier (ADR-006) and ships a .contract.ts
descriptor alongside its .lite.tsx:
- Pure — a single Mitosis source compiles cleanly to all targets. No platform branching.
- Adapt — web and native need materially different markup. A
resolveAdaptresolver picks the platform implementation at runtime; the contract stays identical. - Platform — inherently single-target (e.g.
BcViewerPdfon web,BcSignatureon mobile).
npm run audit:contract enforces the contract surface so props cannot silently
drift between the source and a hand-written platform override.
BcForm and BcRenderer are driven by @bitcode/ui-schema:
ReactiveStoreevaluates field reactions (visible,disabled,required,options, computed values) against a sandboxed expression AST.BcRendererturns aUiSchemaJSON tree into components, resolving field types through a pluggableFieldResolver.- Expressions are permission-scoped: a field the caller may not read is removed
from the evaluation scope before the expression runs, and surfaces as
EXPR_PATH_UNAUTHORIZEDrather than leaking a value.
- Tailwind v4 preset at
tokens/tailwind.preset.cjs, generated fromtokens/tokens.ts—npm run tokens:checkfails the build on drift. - NativeWind v4 preset at
tokens/nativewind.preset.cjsfor React Native. - Light and dark themes ship as CSS custom properties in
tokens/theme.css, driven byapplyTheme()/onThemeChange()from@bitcode/ui/core. - RTL is supported through CSS logical properties and
AppConfigInit.direction('ltr' | 'rtl' | 'auto'), whereautoderives from the active locale. Every component has an accompanying.rtl.test.tsx. - 11 locales are built in:
en,id,fr,de,es,pt-BR,ja,zh-CN,ko,ar,ru— witharresolving to RTL automatically.
| Command | Purpose |
|---|---|
npm run build |
Compile all targets + run post-steps (this is the real build) |
npm run dev |
Registry generation → Mitosis build → Vite playground |
npm test |
Source tests (node --test) then runtime tests (Vitest) |
npm run test:source |
Source-level assertions only |
npm run test:runtime |
Vitest + jsdom only |
npm run test:coverage |
Vitest with V8 coverage |
npm run tokens:check |
Fail if generated tokens are stale |
npm run tokens:generate |
Regenerate token artifacts from tokens/tokens.ts |
npm run audit:contract |
Enforce ADR-007/009 contract surface |
npm run docs:generate |
Regenerate docs/*.md from component contracts |
npm run registry |
Rebuild the component registry |
CI runs the four-target build, source tests, Vitest, and a Playwright pass over the demo app.
ui/
├── src/
│ ├── components/ # 204 Mitosis .lite.tsx sources, grouped by domain
│ │ └── <group>/<name>/ # BcXxx.lite.tsx + BcXxx.contract.ts + tests
│ ├── core/ # Framework-neutral runtime
│ │ ├── adapt/ # platform resolvers
│ │ ├── reactive/ # ReactiveStore bindings
│ │ ├── renderer/ # BcRenderer + field resolvers
│ │ ├── block-renderer/ # Block Catalog web binding
│ │ ├── i18n/ # 11 locales
│ │ └── providers/ # AppProvider, theme, RTL
│ └── index.ts # Public barrel (204 exports)
├── demo-app/ # Vite + React gallery (deployed to Pages)
├── demos/ # Additional demo shells (react-app, playground, rn-app)
├── docs/ # Per-component documentation
├── tokens/ # Design tokens, Tailwind + NativeWind presets, themes
├── patches/ # patch-package patches for Mitosis 0.13.1
└── scripts/ # Build, codegen, audit, and test tooling
Architecture Decision Records live in the parent BitCode repository. The ones that shape this library most directly:
| ADR | Decision |
|---|---|
| ADR-006 | Three-tier component classification (Pure / Adapt / Platform) and the Mitosis target matrix |
| ADR-007 | Contract-first freeze — .contract.ts is the API, the .lite.tsx is one implementation of it |
| ADR-009 | Slot-props contract for composable component parts |
| ADR-012 | Portable schema types extracted into @bitcode/ui-schema |
| ADR-017 / ADR-018 | Block Catalog and the expression/action runtime behind BcRenderer |
patches/@builder.io+mitosis+0.13.1.patch fixes two upstream 0.13.1 defects:
a if (true || ...) leftover that forces Prettier on Vue output (crashing on
complex SVG templates), and a NativeWind plugin bug that stringifies dynamic
class bindings to "[object Object]". Applied automatically by
patch-package on install. Remove it once both fixes land upstream.
- Author or edit the
.lite.tsxsource insrc/components/<group>/<name>/. - Keep the sibling
.contract.tsin sync —npm run audit:contractwill tell you if it drifted. - Run
npm run buildand confirm all four targets compile. - Add or update
docs/BcXxx.md, thennpm run registry. - Run
npm test.
Component conventions worth knowing:
constdeclared outsideuseStoreis dropped by the Mitosis compiler — expose computed values as getters insideuseStore.- The
styleprop must be an object, not a string, for the React target. - Dynamic JSX tags (
<Tag>) are not supported — use<Show>branches instead. - DOM refs belong in
useRef, never inuseStore; a lint script enforces this.
MIT — see LICENSE.