WebHemi design system: React components built and reviewed in Storybook, published for both WebHemi.PHP (AssetMapper) and WebHemi.JS (Next.js).
src/
├── admin/ # Admin Theme (Retro OS) — rewrite in progress
│ ├── chrome/ # atoms — one folder each (Button/, FieldRow/, …)
│ │ └── _lib/ # shared helpers (accessKey, scrollbar, table view, …)
│ ├── bricks/ # product bricks — one folder each
│ │ └── _lib/ # PaneWindowShell, windowBrickStory
│ ├── styles/ # tokens, chrome/, product/, entry.scss
│ ├── assets/ # chrome/ icons/{system,explorer,toolbar}/ system/ fonts/ logo/ — synced as files (never inlined)
│ ├── lib/ # adminAsset() URL helpers
│ └── … # pages / components
├── themes/
│ └── default/ # self-contained frontend theme
├── shared/ # transitional (atoms → themes/default; no long-term shared UI)
├── lib/ # non-UI helpers (cn / clsx)
└── styles/
├── platform.css # Tailwind theme+utilities (no Preflight)
└── entry.js # production CSS entry (Vite + Sass)
Themes are self-contained. Storybook toolbar (data-wh-theme) switches Admin vs Default.
npm install
npm run storybookRepo-managed hooks live in .githooks/ (enable once per clone):
chmod +x .githooks/pre-commit
git config core.hooksPath .githooks- pre-commit — reject staged text files with CRLF
Typecheck, lint, and Storybook interaction tests run in GitHub Actions CI; Chromatic publishes on push. No local pre-push gate (keeps PhpStorm Commit and Push reliable).
npm run buildtsup→dist/index.js/.cjs/.d.tsvite build --config vite.css.config.ts→dist/index.css(Sass chrome/product + Tailwind utilities;cssMinify: false; no base64-inlined images — graphics use/assets/admin/...)
npm publish --access publicnpm run build
npm link
# in consumer:
npm link @webhemi/uiFor Symfony AssetMapper during local PHP work, point at dist/ (see webhemi-php docs).