@center12/blade-ui-kit
v0.1.1
Published
Blade design system component library — merge-ready Bld* components, tokens, and theme for the Nexus application
Maintainers
Readme
@inertia-systems/blade-ui-kit
The Blade design-system component library — production-ready
Bld*React components, design tokens, MUI theme, and i18n bootstrap for the Nexus application.
Live Storybook
URL: https://inertia-blade-ui-kit-storybook.vercel.app
Browse the catalog — every component, every variant, every state — in Storybook before reaching for the imports below.
Install
Status (May 2026): the package is not yet published to npm — the
@inertia-systemsscope hasn't been claimed. Install directly from the private GitHub repo for now. The migration path to npm is documented in Publishing to npm (future state).
Today — install from GitHub
# Latest main
pnpm add "github:InertiaSystems/inertia-blade-ui-kit-storybook#main"
# Pin to a tag (recommended for production)
pnpm add "github:InertiaSystems/inertia-blade-ui-kit-storybook#v0.1.0"
# Pin to a specific commit (most reproducible)
pnpm add "github:InertiaSystems/inertia-blade-ui-kit-storybook#<sha>"What happens during install:
- pnpm clones the repo to a temp dir.
- pnpm installs the dev dependencies in the clone.
- The
preparescript runsvite build, producingdist/in the clone. - pnpm packs
files(dist/,README.md,LICENSE,package.json) and drops them into yournode_modules/@inertia-systems/blade-ui-kit/. - Dev dependencies are stripped — your final install is lean.
Authentication: the repo is private. You need git access to
InertiaSystems/inertia-blade-ui-kit-storybookeither via SSH (recommended —pnpm add "github:..."falls back togit+ssh) or via a Personal Access Token configured in your global~/.gitconfig. CI installs need aGITHUB_TOKENwithreposcope exposed to the install step.
Required peer dependencies
blade-ui-kit keeps its bundle small by not re-shipping the heavy stuff your app already has. Install the peers your app doesn't already depend on:
pnpm add react react-dom @mui/material @mui/icons-material \
@emotion/react @emotion/styled @emotion/cache \
lucide-react react-hook-form @hookform/resolvers zod \
i18next react-i18next i18next-browser-languagedetector \
@tanstack/react-query @tanstack/react-table \
@reduxjs/toolkit react-redux react-router \
mui-one-time-password-inputThe exact version ranges are declared in this package's peerDependencies — your package manager will warn you if any are missing or mismatched.
Why so many peers?
blade-ui-kitbuilds on MUI, RHF, i18next, Redux Toolkit, TanStack Query/Table, Lucide, and Zod. Externalising them means (a) one copy of MUI in your bundle, not two, (b) you control the version, and (c) the published artifact stays under ~250 KB gzipped.
Future state — install from npm
Once the @inertia-systems scope is claimed on npmjs.com and the first version is published, this will be the install command:
pnpm add @inertia-systems/blade-ui-kitNo code changes required on the consumer side — the package name and exports stay identical.
Quick start (consumer app)
1. Wrap your app with the theme + Emotion cache
import { ThemeProvider, CssBaseline } from '@mui/material';
import { CacheProvider } from '@emotion/react';
import { bldTheme, createBldEmotionCache } from '@inertia-systems/blade-ui-kit';
const cache = createBldEmotionCache();
export function AppRoot({ children }: { children: React.ReactNode }) {
return (
<CacheProvider value={cache}>
<ThemeProvider theme={bldTheme}>
<CssBaseline />
{children}
</ThemeProvider>
</CacheProvider>
);
}2. Import any Bld* component
import { BldButton, BldInput, BldStack, color } from '@inertia-systems/blade-ui-kit';
export function LoginCard() {
return (
<BldStack direction="column" gap="12">
<BldInput
labelKey="auth:login.emailLabel"
placeholderKey="auth:login.emailPlaceholder"
type="email"
size="large"
labelPosition="notch"
fullWidth
/>
<BldButton labelKey="auth:login.submitButton" variant="primary" size="xlg" fullWidth />
</BldStack>
);
}3. Use design tokens directly when needed
import { color, spacing, radius } from '@inertia-systems/blade-ui-kit';
const styles = {
background: color.bg.canvas,
padding: spacing[16],
borderRadius: radius.md,
};i18n integration
The library ships pre-bundled English locales under namespaces common, auth, project, files, drawings, viewer, settings, errors. Components reference these via labelKey / placeholderKey props.
Option A — let the kit own i18n (simple apps)
import '@inertia-systems/blade-ui-kit'; // imports the barrel
import { i18n } from '@inertia-systems/blade-ui-kit';
// `i18n.init()` already ran on import. Done.Option B — your app owns i18n (recommended for Nexus)
// In your own i18n bootstrap, register the bundled namespaces alongside yours:
import i18n from 'i18next';
import bladeCommon from '@inertia-systems/blade-ui-kit/locales/en/common.json'; // (planned export)
// …⚠️ Side-effect note: the default barrel import auto-initialises i18next. If your app initialises i18next itself, import only the components you need (tree-shaken) and avoid importing
i18nfrom this package. We're iterating on a side-effect-free entry point — track this issue for status.
What's in the catalog
| Category | Components |
|----------|-----------|
| Inputs | BldInput · BldPasswordInput · BldOtpInput · BldSearchInput · BldSelect · BldAutocomplete · BldCheckbox · BldRadio · BldSwitch |
| Actions | BldButton · BldIconButton · BldSecondaryButton · BldSplitButton |
| Layout | BldStack · BldDivider · BldDrawer · BldDrawerPanel · BldRightSidebarLayout · BldFilterPanel · BldFormSection · BldPaper · BldCollapse · BldScrollbar |
| Display | BldBadge · BldBadgeGroup · BldChip · BldHighlight · BldLoading · BldEmptyState · BldAlert · BldSnackbar · BldTooltip |
| Navigation | BldTabs · BldPagination · BldMenu · BldList · BldListItemButton · BldListItemIcon · BldListItemText · BldPageHeader · BldToolbar |
| Overlays | BldModal · BldConfirmDialog · BldPopper |
| Brand | BldBrandIcon · BldInertiaLogo |
Every component is documented in Storybook with all states, variants, controls, and accessibility notes.
Local development (contributors)
If you're working on the catalog rather than consuming it:
git clone [email protected]:InertiaSystems/inertia-blade-ui-kit-storybook.git
cd inertia-blade-ui-kit-storybook
pnpm install
pnpm storybook # → http://localhost:6006Commands
| Command | Description |
|--------------------------|-------------|
| pnpm storybook | Start Storybook dev server at :6006 |
| pnpm build-storybook | Build static Storybook (auto-deployed to Vercel on push to main) |
| pnpm build | Build the library — emits dist/blade-ui-kit.{cjs.js,es.mjs} + matching .d.ts |
| pnpm test | Run Vitest unit tests |
| pnpm test:watch | Vitest in watch mode |
| pnpm test:coverage | Vitest with coverage report |
| pnpm lint | ESLint (zero-warning policy) |
| pnpm format | Prettier format |
| pnpm typecheck | tsc --noEmit |
| pnpm tokens:build | Validate design-tokens.yaml against tokens.ts |
| pnpm catalog:audit | Scan feature code for forbidden patterns / catalog gaps |
Publishing to npm (future state)
Today the package is consumed via git URL (see Install). When the team is ready to flip to the npm registry, this is the runbook.
One-time setup (do this once, then forget)
- Claim the npm org. Go to https://www.npmjs.com/org/create and create the
inertia-systemsorganization. Pick the free plan if all packages will be public, or paid if any will be private. The org slug must match the scope inpackage.json(@inertia-systems/...). - Add publishers. Add anyone who needs to release the package as a member of the org with
developer(publish) rights. - Generate an automation token. In your npm account → Access Tokens → Generate New Token → Automation. This token bypasses 2FA so it can be used in CI.
- Add the token to the GitHub repo. Repo Settings → Secrets and variables → Actions → New repository secret → name
NPM_TOKEN, value the automation token from step 3. - Verify the package name is available. Run
npm view @inertia-systems/blade-ui-kit— should return 404. If someone else has claimed it, escalate to the platform team.
First publish (manual, one-shot)
After the org exists and you've run npm login locally:
cd blade-ui-kit
pnpm install
pnpm prepublishOnly # typecheck + tests + build
npm publish --access publicVerify with npm view @inertia-systems/blade-ui-kit — should now return the manifest.
Recurring releases (CI-driven)
The publish.yml workflow (.github/workflows/publish.yml) is already committed and triggers on any v* tag push:
# 1. Bump the version in package.json (semver: patch / minor / major)
pnpm version patch # bumps package.json and creates a git tag
# 2. Push the commit + tag — CI does the rest
git push --follow-tagsThe workflow runs pnpm install --frozen-lockfile → typecheck → test → vite build → npm publish --provenance --access public.
The workflow will fail until
NPM_TOKENis set in repo secrets (see step 4 of One-time setup above) and theinertia-systemsorg exists on npmjs.com. It is safe to keep committed in the meantime — it only runs onv*tag pushes, and you have full control over when those happen.
Architecture
design-system/tokens/design-tokens.yaml
↓ (pnpm tokens:build)
src/theme/tokens.ts ← SINGLE SOURCE OF TRUTH
↓ ↓
src/theme/bldTheme.ts tailwind.config.mjs
(MUI theme) (layout utilities)
↓
src/components/ui/Bld* ← Bld base wrappers
↓
src/index.ts ← Public barrel (PUBLISHED)
.storybook/ ← Stories + MDX docs
src/stories/foundations/ ← Token galleriesNaming convention
All components use the Bld* prefix (BldButton, BldTable, …). Public exports live under src/components/ui/.
ESLint enforcement (when working in the catalog repo)
Feature code in this repo is not allowed to import @mui/material, @tanstack/react-table, or @formio/react directly. Only src/components/ui/** may. ESLint blocks violations via no-restricted-imports. Pre-commit runs lint + format; pre-push runs tsc --noEmit.
Token discipline
- No raw hex values in component source (
rg "#[0-9a-f]{3,6}" src/components/→ zero hits) - No inline
style={{}}in component source - No hard-coded English strings — all user-facing text uses
t()with i18n keys
Storybook deployment
Static Storybook is built and hosted on Vercel.
| Setting | Value |
|-------------------|------------------------------------------------|
| Framework preset | None (static output) |
| Install command | pnpm install --frozen-lockfile |
| Build command | pnpm build-storybook |
| Output directory | storybook-static |
| Auto-deploy | Push to main → production; PRs → preview URL |
Config lives in vercel.json. Manual deploy from a clean checkout:
pnpm install
pnpm build-storybook
vercel --prodKnown follow-ups
BldIconButtonemits twoTS2742"inferred type cannot be named" warnings duringpnpm build. The compiled.d.tsis still correct and consumers don't see the warning, but it should be fixed by adding an explicit type annotation toStyledBldIconButton. Tracked as a polish task.- The default barrel import side-effect-initialises i18next. We plan to split a
@inertia-systems/blade-ui-kit/no-i18nsubpath export so consumers who own their own i18next can import components without the auto-init.
License
UNLICENSED — internal Inertia Systems use only. Contact the platform team before forking or external distribution.
