diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index ebcaaf6..3b20e48 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -29,6 +29,7 @@ jobs: - run: npm run smoke:packed - run: npm run smoke:packed-native - run: npm run smoke:packed-boundaries + - run: npm run smoke:packed-fumadocs - run: npm run smoke:packed-examples - run: npx playwright install --with-deps chromium firefox webkit - run: npm run smoke:packed-next diff --git a/apps/docs/public/llms.txt b/apps/docs/public/llms.txt index ccbf8ee..43b196a 100644 --- a/apps/docs/public/llms.txt +++ b/apps/docs/public/llms.txt @@ -60,7 +60,7 @@ Source: docs/architecture/platform-matrix.md SSR: client components retain use-client boundaries in emitted JS. Importing a button needs React/tokens/contracts only at runtime. CSS is explicitly imported. Native API never imports DOM, Web Audio or chart. Native target size remains comfortable even when host density is compact; Pro density is a DOM exception, not a reason to shrink phone targets. -Optional peer packages: chart only for chart entry; community Slider for native selection entry; react-native-svg for native brand entry. Gorhom/Reanimated/Worklets/Gesture Handler are isolated behind the optional gesture-sheet entry; base imports do not load them. No root barrel loads every component. DOM overlays are one scoped family entry and carry Radix MIT attribution. ESM is supported; CommonJS consumer support is not claimed. +Optional peer packages: chart only for chart entry; community Slider for native selection entry; react-native-svg for native brand entry. Gorhom/Reanimated/Worklets/Gesture Handler are isolated behind the optional gesture-sheet entry; base imports do not load them. No root barrel loads every component. DOM overlays are one scoped family entry and carry Radix MIT attribution; Radix peers are optional caret ranges and overlay-free web recipes have their own entries. ESM is supported; CommonJS consumer support is not claimed. ## Actions & surfaces · HIG 0.1.0 @@ -308,7 +308,7 @@ Composed patterns for balances, markets, trade review, and documentation. Includes `MarketRow`, `BalanceCard`, `TradeEntry`, `ActivityList`, `InstallCommand`, `CodeWindow`, and `MarketingHero`. -Issue #26. Entry: `recipes`. Import platform entries from `@bloxwap/hig-react/recipes` or `@bloxwap/hig-native/recipes` according to applicability below. Import `@bloxwap/hig-react/css` once on web; tokens CSS is a separate explicit import. +Issue #26. Entry: `recipes`. Import platform entries from `@bloxwap/hig-react/recipes` or `@bloxwap/hig-native/recipes` according to applicability below. On web, each recipe also has its own entry, for example `@bloxwap/hig-react/recipes/install-command`, `recipes/code-window`, `recipes/market-row`, `recipes/balance-card`, `recipes/marketing-hero` and `recipes/activity-list`. These need no Radix peer; `smoke:packed-boundaries` renders and bundles them with no Radix installed (#63). `recipes/trade-entry` and the aggregate `recipes` entry need `@radix-ui/react-dialog` for the confirm step. Import `@bloxwap/hig-react/css` once on web; tokens CSS is a separate explicit import. ## API and anatomy @@ -1226,6 +1226,10 @@ These are review candidates, not published npm packages. Use local dry-run tarba Run `npm ci && npm run build && npm run smoke:packed`. The smoke script installs tarballs into an independent temporary consumer and builds the fixture. For a host app install tokens, contracts and React tarballs plus React/DOM 19.2. Import `@bloxwap/hig-tokens/css` and `@bloxwap/hig-react/css` once; import individual components such as `@bloxwap/hig-react/button`. Pin @bloxwap/font 0.1.2 and choose only the required families/scripts using asset URL @font-face rules named `'Bloxwap Sans'` and `'Bloxwap Mono'`; HIG controls read `--hig-font-sans`/`--hig-font-mono`, which fall back to those literal families. The included fixture has Sans and Mono only, and its browser smoke checks that `.hig-button` and `.hig-number` render loaded Bloxwap faces. Never copy font binaries or component folders. +### Radix overlay peers and Fumadocs + +The four Radix packages are optional peers with caret ranges: `@radix-ui/react-dialog ^1.1.15`, `@radix-ui/react-popover ^1.1.15`, `@radix-ui/react-dropdown-menu ^2.1.16` and `@radix-ui/react-tooltip ^1.2.8`. Install them only for `@bloxwap/hig-react/overlay`, `@bloxwap/hig-react/recipes` or `@bloxwap/hig-react/recipes/trade-entry` (dialog only). Hosts that already use Radix, such as Fumadocs, share their copy: `npm run smoke:packed-fumadocs` installs the packed React tarball next to fumadocs-ui 16.17.3 with strict peers and `npm ci`, asserts every `@radix-ui/*` package appears once, and renders the overlays on the resolved current releases. The workspace fixtures keep testing the lower bounds. Do not set `legacy-peer-deps` for HIG. + ## SSR and Next client boundaries Run `npm run smoke:ssr`, `npm run build:next` and `npm run smoke:packed-next`. Token/formatting imports and button/provider SSR are deterministic. Components with hooks carry `use client` in their emitted modules. In Next, import HIG CSS in the app layout and put interactive example state in a client component; keep wallet/network logic with the host. Next's published Bloxwap font loaders remain owned upstream. diff --git a/apps/docs/public/markdown/architecture/platform-matrix.md b/apps/docs/public/markdown/architecture/platform-matrix.md index bd9f40f..9965cf9 100644 --- a/apps/docs/public/markdown/architecture/platform-matrix.md +++ b/apps/docs/public/markdown/architecture/platform-matrix.md @@ -16,4 +16,4 @@ SSR: client components retain use-client boundaries in emitted JS. Importing a button needs React/tokens/contracts only at runtime. CSS is explicitly imported. Native API never imports DOM, Web Audio or chart. Native target size remains comfortable even when host density is compact; Pro density is a DOM exception, not a reason to shrink phone targets. -Optional peer packages: chart only for chart entry; community Slider for native selection entry; react-native-svg for native brand entry. Gorhom/Reanimated/Worklets/Gesture Handler are isolated behind the optional gesture-sheet entry; base imports do not load them. No root barrel loads every component. DOM overlays are one scoped family entry and carry Radix MIT attribution. ESM is supported; CommonJS consumer support is not claimed. +Optional peer packages: chart only for chart entry; community Slider for native selection entry; react-native-svg for native brand entry. Gorhom/Reanimated/Worklets/Gesture Handler are isolated behind the optional gesture-sheet entry; base imports do not load them. No root barrel loads every component. DOM overlays are one scoped family entry and carry Radix MIT attribution; Radix peers are optional caret ranges and overlay-free web recipes have their own entries. ESM is supported; CommonJS consumer support is not claimed. diff --git a/apps/docs/public/markdown/components/recipes.md b/apps/docs/public/markdown/components/recipes.md index 6aeef21..1836cce 100644 --- a/apps/docs/public/markdown/components/recipes.md +++ b/apps/docs/public/markdown/components/recipes.md @@ -4,7 +4,7 @@ Composed patterns for balances, markets, trade review, and documentation. Includes `MarketRow`, `BalanceCard`, `TradeEntry`, `ActivityList`, `InstallCommand`, `CodeWindow`, and `MarketingHero`. -Issue #26. Entry: `recipes`. Import platform entries from `@bloxwap/hig-react/recipes` or `@bloxwap/hig-native/recipes` according to applicability below. Import `@bloxwap/hig-react/css` once on web; tokens CSS is a separate explicit import. +Issue #26. Entry: `recipes`. Import platform entries from `@bloxwap/hig-react/recipes` or `@bloxwap/hig-native/recipes` according to applicability below. On web, each recipe also has its own entry, for example `@bloxwap/hig-react/recipes/install-command`, `recipes/code-window`, `recipes/market-row`, `recipes/balance-card`, `recipes/marketing-hero` and `recipes/activity-list`. These need no Radix peer; `smoke:packed-boundaries` renders and bundles them with no Radix installed (#63). `recipes/trade-entry` and the aggregate `recipes` entry need `@radix-ui/react-dialog` for the confirm step. Import `@bloxwap/hig-react/css` once on web; tokens CSS is a separate explicit import. ## API and anatomy diff --git a/apps/docs/public/markdown/installation.md b/apps/docs/public/markdown/installation.md index 0a20afb..7d05395 100644 --- a/apps/docs/public/markdown/installation.md +++ b/apps/docs/public/markdown/installation.md @@ -6,6 +6,10 @@ These are review candidates, not published npm packages. Use local dry-run tarba Run `npm ci && npm run build && npm run smoke:packed`. The smoke script installs tarballs into an independent temporary consumer and builds the fixture. For a host app install tokens, contracts and React tarballs plus React/DOM 19.2. Import `@bloxwap/hig-tokens/css` and `@bloxwap/hig-react/css` once; import individual components such as `@bloxwap/hig-react/button`. Pin @bloxwap/font 0.1.2 and choose only the required families/scripts using asset URL @font-face rules named `'Bloxwap Sans'` and `'Bloxwap Mono'`; HIG controls read `--hig-font-sans`/`--hig-font-mono`, which fall back to those literal families. The included fixture has Sans and Mono only, and its browser smoke checks that `.hig-button` and `.hig-number` render loaded Bloxwap faces. Never copy font binaries or component folders. +### Radix overlay peers and Fumadocs + +The four Radix packages are optional peers with caret ranges: `@radix-ui/react-dialog ^1.1.15`, `@radix-ui/react-popover ^1.1.15`, `@radix-ui/react-dropdown-menu ^2.1.16` and `@radix-ui/react-tooltip ^1.2.8`. Install them only for `@bloxwap/hig-react/overlay`, `@bloxwap/hig-react/recipes` or `@bloxwap/hig-react/recipes/trade-entry` (dialog only). Hosts that already use Radix, such as Fumadocs, share their copy: `npm run smoke:packed-fumadocs` installs the packed React tarball next to fumadocs-ui 16.17.3 with strict peers and `npm ci`, asserts every `@radix-ui/*` package appears once, and renders the overlays on the resolved current releases. The workspace fixtures keep testing the lower bounds. Do not set `legacy-peer-deps` for HIG. + ## SSR and Next client boundaries Run `npm run smoke:ssr`, `npm run build:next` and `npm run smoke:packed-next`. Token/formatting imports and button/provider SSR are deterministic. Components with hooks carry `use client` in their emitted modules. In Next, import HIG CSS in the app layout and put interactive example state in a client component; keep wallet/network logic with the host. Next's published Bloxwap font loaders remain owned upstream. diff --git a/apps/docs/src/content.json b/apps/docs/src/content.json index 241c99d..7151873 100644 --- a/apps/docs/src/content.json +++ b/apps/docs/src/content.json @@ -27,7 +27,7 @@ "route": "guides/architecture/platform-matrix", "title": "Candidate platform support · 0.1.0", "source": "docs/architecture/platform-matrix.md", - "html": "
| Area | \nDOM | \nRN | \nEvidence | \n
|---|---|---|---|
| Actions, surfaces, text, fields | \nSemantic DOM elements | \nPressable/View/Text/TextInput | \nbehavior tests, Vite/SSR/Metro | \n
| Native text scaling and script tracking | \nBrowser zoom; no cap | \nText/Heading/NumberReadout maxFontSizeMultiplier (prop or HIGProvider default); Korean/Chinese runs at companion spacing via script and letterSpacingByScript | \nnative Jest (#67); iOS AX5 and Android 200% gallery captures pending | \n
| Native colour roles | \nCSS severity/data attributes | \nSwitch tone, Alert severity/tone take token roles only; raw colours fall back | \nnative Jest (#67) | \n
| Selection/range | \nBuilt-in input/select | \nOS Switch/community Slider, radio/check Pressables, Modal chooser; Android Slider adds ACTION_SET_PROGRESS through the autolinked HIGAdjustableView (plain View without native linking) | \ncontract tests; module compiled in a headless Android release build (#71); emulator set-progress run pending | \n
| Dialog/sheet/menu | \nRadix scoped primitives | \nModal and explicit close/back; optional Gorhom GestureSheet entry | \nDOM nested focus/Escape; mocked native focus/back/detents plus separate packed Android/iOS gesture entry | \n
| Tooltip/popover | \nRadix hover/focus/anchored | \npersistent HelpText/modal | \nno RN hover claim | \n
| Navigation/search | \nhref/callback adapters | \nhost route/back callbacks | \ntab/search/disclosure contracts | \n
| Financial lists/table | \nsemantic table/list | \nFlatList labeled rows | \nformatting and contract tests | \n
| Chart | \noptional lazy @bloxwap/chart canvas | \nnumeric/list summary only | \ntyped theme; physical gesture evidence pending | \n
| Brand mark | \nindividual SVG renderer/asset | \noptional react-native-svg | \npinned geometry; device comparison pending | \n
| Fonts | \npinned Sans/Mono asset URLs | \nhash-pinned static faces, typed manifest, explicit weight registration and host script fallback | \nExpo-web loading/byte/hash gates; no physical native-font certification | \n
SSR: client components retain use-client boundaries in emitted JS. Importing a button needs React/tokens/contracts only at runtime. CSS is explicitly imported. Native API never imports DOM, Web Audio or chart. Native target size remains comfortable even when host density is compact; Pro density is a DOM exception, not a reason to shrink phone targets.
\nOptional peer packages: chart only for chart entry; community Slider for native selection entry; react-native-svg for native brand entry. Gorhom/Reanimated/Worklets/Gesture Handler are isolated behind the optional gesture-sheet entry; base imports do not load them. No root barrel loads every component. DOM overlays are one scoped family entry and carry Radix MIT attribution. ESM is supported; CommonJS consumer support is not claimed.
\n", + "html": "| Area | \nDOM | \nRN | \nEvidence | \n
|---|---|---|---|
| Actions, surfaces, text, fields | \nSemantic DOM elements | \nPressable/View/Text/TextInput | \nbehavior tests, Vite/SSR/Metro | \n
| Native text scaling and script tracking | \nBrowser zoom; no cap | \nText/Heading/NumberReadout maxFontSizeMultiplier (prop or HIGProvider default); Korean/Chinese runs at companion spacing via script and letterSpacingByScript | \nnative Jest (#67); iOS AX5 and Android 200% gallery captures pending | \n
| Native colour roles | \nCSS severity/data attributes | \nSwitch tone, Alert severity/tone take token roles only; raw colours fall back | \nnative Jest (#67) | \n
| Selection/range | \nBuilt-in input/select | \nOS Switch/community Slider, radio/check Pressables, Modal chooser; Android Slider adds ACTION_SET_PROGRESS through the autolinked HIGAdjustableView (plain View without native linking) | \ncontract tests; module compiled in a headless Android release build (#71); emulator set-progress run pending | \n
| Dialog/sheet/menu | \nRadix scoped primitives | \nModal and explicit close/back; optional Gorhom GestureSheet entry | \nDOM nested focus/Escape; mocked native focus/back/detents plus separate packed Android/iOS gesture entry | \n
| Tooltip/popover | \nRadix hover/focus/anchored | \npersistent HelpText/modal | \nno RN hover claim | \n
| Navigation/search | \nhref/callback adapters | \nhost route/back callbacks | \ntab/search/disclosure contracts | \n
| Financial lists/table | \nsemantic table/list | \nFlatList labeled rows | \nformatting and contract tests | \n
| Chart | \noptional lazy @bloxwap/chart canvas | \nnumeric/list summary only | \ntyped theme; physical gesture evidence pending | \n
| Brand mark | \nindividual SVG renderer/asset | \noptional react-native-svg | \npinned geometry; device comparison pending | \n
| Fonts | \npinned Sans/Mono asset URLs | \nhash-pinned static faces, typed manifest, explicit weight registration and host script fallback | \nExpo-web loading/byte/hash gates; no physical native-font certification | \n
SSR: client components retain use-client boundaries in emitted JS. Importing a button needs React/tokens/contracts only at runtime. CSS is explicitly imported. Native API never imports DOM, Web Audio or chart. Native target size remains comfortable even when host density is compact; Pro density is a DOM exception, not a reason to shrink phone targets.
\nOptional peer packages: chart only for chart entry; community Slider for native selection entry; react-native-svg for native brand entry. Gorhom/Reanimated/Worklets/Gesture Handler are isolated behind the optional gesture-sheet entry; base imports do not load them. No root barrel loads every component. DOM overlays are one scoped family entry and carry Radix MIT attribution; Radix peers are optional caret ranges and overlay-free web recipes have their own entries. ESM is supported; CommonJS consumer support is not claimed.
\n", "toc": [], "section": "architecture" }, @@ -213,7 +213,7 @@ "route": "guides/components/recipes", "title": "Recipes · HIG 0.1.0", "source": "docs/components/recipes.md", - "html": "Composed patterns for balances, markets, trade review, and documentation.
\nIncludes MarketRow, BalanceCard, TradeEntry, ActivityList, InstallCommand, CodeWindow, and MarketingHero.
Issue #26. Entry: recipes. Import platform entries from @bloxwap/hig-react/recipes or @bloxwap/hig-native/recipes according to applicability below. Import @bloxwap/hig-react/css once on web; tokens CSS is a separate explicit import.
All data and actions are supplied by the host application.
\n| Recipe | \nKey props and behavior | \n
|---|---|
TradeEntry | \nRaw amount, onAmountChange, onConfirm, available, busy, and error; opens review before submission. | \n
InstallCommand | \ncommand and onCopy; accepts an asynchronous host clipboard adapter. | \n
Do: compose primitives and explicit outcomes in comfortable app or compact Pro context. Don’t: put wallet/network/SDK services in core packages.
\nNative CodeWindow and InstallCommand render code in the provider's monoFontFamily (for example the registered BloxwapMonoRegular; platform monospace otherwise) and keep code left-to-right inside RTL roots. Copy failures leave a manual-selection recovery message. Trade confirm remains host-controlled; no demo sends a transaction. Web/native fixtures show balance, market, entry and feedback preference previews.
State review: rest; keyboard focus/hover (DOM); accepted press and release/cancel; selected/checked where applicable; disabled; busy; inline error/recovery; empty/loading; long translations/large text; reduced motion; sound and haptics disabled. No host action occurs on mere focus. Disabled/busy targets suppress accepted activation. Core has no required feedback backend; the optional provider callback follows the action, honors cancellation and isolates errors.
\nM2 supplies visual recipes; M3 adds semantic feedback composition because #26 depends on #25. Product visual fidelity is provisional until inaccessible monorepo audit. Account/positions variants can compose these primitives without service coupling.
\nSee tests/components.dom.test.tsx, tests/native/components.test.cjs, consumer fixtures and milestone evidence. Physical hardware, assistive-technology and baseline product comparisons are unperformed unless linked explicitly. Cite HIG 0.1.0 with this chapter anchor and a commit permalink, not a mutable preview branch. Preserve business behavior behind a host rollback flag during adoption.
Composed patterns for balances, markets, trade review, and documentation.
\nIncludes MarketRow, BalanceCard, TradeEntry, ActivityList, InstallCommand, CodeWindow, and MarketingHero.
Issue #26. Entry: recipes. Import platform entries from @bloxwap/hig-react/recipes or @bloxwap/hig-native/recipes according to applicability below. On web, each recipe also has its own entry, for example @bloxwap/hig-react/recipes/install-command, recipes/code-window, recipes/market-row, recipes/balance-card, recipes/marketing-hero and recipes/activity-list. These need no Radix peer; smoke:packed-boundaries renders and bundles them with no Radix installed (#63). recipes/trade-entry and the aggregate recipes entry need @radix-ui/react-dialog for the confirm step. Import @bloxwap/hig-react/css once on web; tokens CSS is a separate explicit import.
All data and actions are supplied by the host application.
\n| Recipe | \nKey props and behavior | \n
|---|---|
TradeEntry | \nRaw amount, onAmountChange, onConfirm, available, busy, and error; opens review before submission. | \n
InstallCommand | \ncommand and onCopy; accepts an asynchronous host clipboard adapter. | \n
Do: compose primitives and explicit outcomes in comfortable app or compact Pro context. Don’t: put wallet/network/SDK services in core packages.
\nNative CodeWindow and InstallCommand render code in the provider's monoFontFamily (for example the registered BloxwapMonoRegular; platform monospace otherwise) and keep code left-to-right inside RTL roots. Copy failures leave a manual-selection recovery message. Trade confirm remains host-controlled; no demo sends a transaction. Web/native fixtures show balance, market, entry and feedback preference previews.
State review: rest; keyboard focus/hover (DOM); accepted press and release/cancel; selected/checked where applicable; disabled; busy; inline error/recovery; empty/loading; long translations/large text; reduced motion; sound and haptics disabled. No host action occurs on mere focus. Disabled/busy targets suppress accepted activation. Core has no required feedback backend; the optional provider callback follows the action, honors cancellation and isolates errors.
\nM2 supplies visual recipes; M3 adds semantic feedback composition because #26 depends on #25. Product visual fidelity is provisional until inaccessible monorepo audit. Account/positions variants can compose these primitives without service coupling.
\nSee tests/components.dom.test.tsx, tests/native/components.test.cjs, consumer fixtures and milestone evidence. Physical hardware, assistive-technology and baseline product comparisons are unperformed unless linked explicitly. Cite HIG 0.1.0 with this chapter anchor and a commit permalink, not a mutable preview branch. Preserve business behavior behind a host rollback flag during adoption.
These are review candidates, not published npm packages. Use local dry-run tarballs or CI artifact downloads; do not assume @bloxwap/hig-* is available on the registry. Published-style imports in examples are tested against packed candidates. Version references identify a candidate until release gates are complete.
Run npm ci && npm run build && npm run smoke:packed. The smoke script installs tarballs into an independent temporary consumer and builds the fixture. For a host app install tokens, contracts and React tarballs plus React/DOM 19.2. Import @bloxwap/hig-tokens/css and @bloxwap/hig-react/css once; import individual components such as @bloxwap/hig-react/button. Pin @bloxwap/font 0.1.2 and choose only the required families/scripts using asset URL @font-face rules named 'Bloxwap Sans' and 'Bloxwap Mono'; HIG controls read --hig-font-sans/--hig-font-mono, which fall back to those literal families. The included fixture has Sans and Mono only, and its browser smoke checks that .hig-button and .hig-number render loaded Bloxwap faces. Never copy font binaries or component folders.
Run npm run smoke:ssr, npm run build:next and npm run smoke:packed-next. Token/formatting imports and button/provider SSR are deterministic. Components with hooks carry use client in their emitted modules. In Next, import HIG CSS in the app layout and put interactive example state in a client component; keep wallet/network logic with the host. Next's published Bloxwap font loaders remain owned upstream.
Fonts in Next: put the @bloxwap/font loader variables on <html>, for example <html className={${BloxwapSans.variable} ${BloxwapMono.variable}}>. The loaders register hashed family names, so HIG never matches a literal 'Bloxwap Sans' there. Instead --hig-font-sans and --hig-font-mono in @bloxwap/hig-tokens/css resolve var(--font-bloxwap-sans) and var(--font-bloxwap-mono) first and fall back to the literal families. No bridge CSS is needed. If a host keeps its own variable names, override the roles on :root after importing the tokens CSS: :root { --hig-font-sans: var(--my-sans), 'Bloxwap Sans', system-ui, sans-serif; }. The variables must be defined on <html> (not <body>), because the roles resolve on :root. npm run smoke:packed-next serves the packed consumer and checks, in Chromium, that .hig-button and .hig-number compute to a loaded Bloxwap face (document.fonts.check plus the FontFace status). Next 16.4.0 (webpack), React 19.2 and the published Bloxwap Sans Next loader are verified in the dedicated production fixture; other Next versions require host checks. Verify hydration, stable IDs and StrictMode before adopting a host version.
Run npm run smoke:packed-native after packed artifacts are built, or npm run start -w hig-native-fixture for the device gallery. Matrix: React 19.1, RN 0.81.5, Expo 54, Metro as locked. Native consumers install tokens/contracts/native tarballs; optional feedback installs its tarball and explicit Expo backend peers. Slider and SVG peers are only needed by their family entries. Import @bloxwap/hig-native/button, not the DOM renderer. Dynamic Type remains enabled; native targets stay 48. Keyboard/safe-area/back behavior belongs to the native host and its supported OS.
Install Expo native peers with npx expo install (for example expo-asset ~12.0.13 and expo-constants ~18.0.14 alongside expo-font/expo-audio). Expo 54 autolinking links the copy resolved from the app root; a hoisted SDK 57 expo-asset pulled by expo-audio's * peer compiles away and the app fails at launch with Cannot find native module 'ExpoAsset' (observed on the iOS Simulator). verifyExpoNativeModules in scripts/native-compatibility.mjs guards the fixture and packed consumer. HIGProvider follows the OS layout direction (I18nManager.isRTL) unless direction is passed.
@bloxwap/hig-native ships one small Android library (android/, com.bloxwap.hig.HIGPackage) that React Native and Expo autolinking pick up in development and release builds (npx expo prebuild, npx expo run:android). It adds Android set-progress to Slider; nothing else depends on it, and in Expo Go the Slider falls back to increment/decrement only. iOS needs no native code.
Simulator/emulator verification: scripts/native-sim/ builds the packed candidate gallery as real Release apps and drives them with XCUITest (iOS Simulator) and UiAutomation instrumentation, uiautomator and TalkBack (Android emulator). Results and residual physical-hardware limits are in evidence/native-sim/.
WOFF2 is not a native font asset. @bloxwap/hig-native-fonts ships 15 static Bloxwap Sans/Mono (plus Korean and Simplified Chinese Sans) TTFs generated reproducibly from pinned Font 0.1.2 sources, with a typed fontManifest export and @bloxwap/hig-native-fonts/manifest. Install it alongside the tokens, contracts and native tarballs, then require('@bloxwap/hig-native-fonts/fonts/BloxwapSans.ttf') and register the faces with expo-font before setting the native provider fontFamily, as the gallery does. @bloxwap/hig-tokens no longer contains font binaries (#64); see native font migration. Rasterization on physical displays remains part of #55. New repositories follow docs/governance/new-repository.md.
Install the tokens tarball alone and import CSS variables or typed tokens. No React/RN/audio peer is required. Plain HTML uses semantic --hig-* roles.
@bloxwap/hig-tokens/css defines every role a plain CSS host needs, so nobody has to read the manifest or generate role files:
| Roles | \nExample | \nValues | \n
|---|---|---|
| Color | \n--hig-surface, --hig-action | \nsRGB, then OKLCH/P3 in @supports | \n
| Space | \n--hig-space-md | \nxs–xxxl, section, in rem | \n
| Font | \n--hig-font-sans, --hig-font-mono | \n@bloxwap/font Next variable, then literal family | \n
| Radius | \n--hig-radius-md, --hig-radius-pill | \nsm md lg xl in rem; pill 9999px | \n
| Type | \n--hig-type-body-size, --hig-type-body-line-height, --hig-type-body-weight, --hig-type-body | \ncaption label body title display; the bare role is a font shorthand in Sans | \n
| Motion | \n--hig-motion-duration-base, --hig-motion-easing-standard | \nfast base slow ms; 0ms under prefers-reduced-motion: reduce or [data-hig-motion='reduced'] | \n
| Density | \n--hig-density-control, --hig-density-compact-gap | \ncontrol target gap per mode; the unprefixed roles follow [data-hig-density='compact'] | \n
@import '@bloxwap/hig-tokens/css';\n.card { border-radius: var(--hig-radius-lg); padding: var(--hig-space-lg); font: var(--hig-type-body); }\n.card h2 { font: var(--hig-type-title); }\n.card button { min-height: var(--hig-density-control); transition: background var(--hig-motion-duration-fast) var(--hig-motion-easing-standard); }\n``` Tailwind may reference these values through host configuration; HIG does not require content scans or a shadcn registry. Native uses dp and explicit hex/channel maps; do not feed CSS functions or rename rem to dp. The audited monorepo web/native rem roots are both 16; HIG supports StyleSheet rather than claiming a verified NativeWind consumer. See the source-reconciliation chapter for native font generation and registration.\n\n## Optional chart, sound and haptics\n\nChart is DOM-only and lazy; install @bloxwap/chart 0.3.0 for that entry and supply a textual summary. Native uses labeled readouts/lists. Feedback install paths, preferences, iOS physical-tap limitations and Expo backends are in the feedback chapters. Keep essential outcome text available with both channels off.\n\n## Stable citations and upgrades\n\nCite “Bloxwap HIG 0.1.0 candidate, chapter/anchor” plus an immutable GitHub commit permalink. Branch and docs preview links are mutable. Upgrade tokens, contracts, renderer, docs/examples and semantic cue mapping together; compare API behavior and adopt behind a rollback flag. Token appearance and accessibility behavior changes require semver review. No publication, release or tag is performed by this implementation.\n\nThe native fixture pins React **19.1.0**, matching the RN 0.81.5 renderer exactly. Web/Next/Fumadocs fixtures use React 19.2.0. Metro explicitly resolves every native `react`/`react/*` import to the native fixture's version so shared-workspace code cannot load web React. Quality and packed-native checks compare the installed version to RN's actual renderer guard; a successful Metro bundle alone does not prove runtime compatibility.\n\n",
+ "html": "These are review candidates, not published npm packages. Use local dry-run tarballs or CI artifact downloads; do not assume @bloxwap/hig-* is available on the registry. Published-style imports in examples are tested against packed candidates. Version references identify a candidate until release gates are complete.
Run npm ci && npm run build && npm run smoke:packed. The smoke script installs tarballs into an independent temporary consumer and builds the fixture. For a host app install tokens, contracts and React tarballs plus React/DOM 19.2. Import @bloxwap/hig-tokens/css and @bloxwap/hig-react/css once; import individual components such as @bloxwap/hig-react/button. Pin @bloxwap/font 0.1.2 and choose only the required families/scripts using asset URL @font-face rules named 'Bloxwap Sans' and 'Bloxwap Mono'; HIG controls read --hig-font-sans/--hig-font-mono, which fall back to those literal families. The included fixture has Sans and Mono only, and its browser smoke checks that .hig-button and .hig-number render loaded Bloxwap faces. Never copy font binaries or component folders.
The four Radix packages are optional peers with caret ranges: @radix-ui/react-dialog ^1.1.15, @radix-ui/react-popover ^1.1.15, @radix-ui/react-dropdown-menu ^2.1.16 and @radix-ui/react-tooltip ^1.2.8. Install them only for @bloxwap/hig-react/overlay, @bloxwap/hig-react/recipes or @bloxwap/hig-react/recipes/trade-entry (dialog only). Hosts that already use Radix, such as Fumadocs, share their copy: npm run smoke:packed-fumadocs installs the packed React tarball next to fumadocs-ui 16.17.3 with strict peers and npm ci, asserts every @radix-ui/* package appears once, and renders the overlays on the resolved current releases. The workspace fixtures keep testing the lower bounds. Do not set legacy-peer-deps for HIG.
Run npm run smoke:ssr, npm run build:next and npm run smoke:packed-next. Token/formatting imports and button/provider SSR are deterministic. Components with hooks carry use client in their emitted modules. In Next, import HIG CSS in the app layout and put interactive example state in a client component; keep wallet/network logic with the host. Next's published Bloxwap font loaders remain owned upstream.
Fonts in Next: put the @bloxwap/font loader variables on <html>, for example <html className={${BloxwapSans.variable} ${BloxwapMono.variable}}>. The loaders register hashed family names, so HIG never matches a literal 'Bloxwap Sans' there. Instead --hig-font-sans and --hig-font-mono in @bloxwap/hig-tokens/css resolve var(--font-bloxwap-sans) and var(--font-bloxwap-mono) first and fall back to the literal families. No bridge CSS is needed. If a host keeps its own variable names, override the roles on :root after importing the tokens CSS: :root { --hig-font-sans: var(--my-sans), 'Bloxwap Sans', system-ui, sans-serif; }. The variables must be defined on <html> (not <body>), because the roles resolve on :root. npm run smoke:packed-next serves the packed consumer and checks, in Chromium, that .hig-button and .hig-number compute to a loaded Bloxwap face (document.fonts.check plus the FontFace status). Next 16.4.0 (webpack), React 19.2 and the published Bloxwap Sans Next loader are verified in the dedicated production fixture; other Next versions require host checks. Verify hydration, stable IDs and StrictMode before adopting a host version.
Run npm run smoke:packed-native after packed artifacts are built, or npm run start -w hig-native-fixture for the device gallery. Matrix: React 19.1, RN 0.81.5, Expo 54, Metro as locked. Native consumers install tokens/contracts/native tarballs; optional feedback installs its tarball and explicit Expo backend peers. Slider and SVG peers are only needed by their family entries. Import @bloxwap/hig-native/button, not the DOM renderer. Dynamic Type remains enabled; native targets stay 48. Keyboard/safe-area/back behavior belongs to the native host and its supported OS.
Install Expo native peers with npx expo install (for example expo-asset ~12.0.13 and expo-constants ~18.0.14 alongside expo-font/expo-audio). Expo 54 autolinking links the copy resolved from the app root; a hoisted SDK 57 expo-asset pulled by expo-audio's * peer compiles away and the app fails at launch with Cannot find native module 'ExpoAsset' (observed on the iOS Simulator). verifyExpoNativeModules in scripts/native-compatibility.mjs guards the fixture and packed consumer. HIGProvider follows the OS layout direction (I18nManager.isRTL) unless direction is passed.
@bloxwap/hig-native ships one small Android library (android/, com.bloxwap.hig.HIGPackage) that React Native and Expo autolinking pick up in development and release builds (npx expo prebuild, npx expo run:android). It adds Android set-progress to Slider; nothing else depends on it, and in Expo Go the Slider falls back to increment/decrement only. iOS needs no native code.
Simulator/emulator verification: scripts/native-sim/ builds the packed candidate gallery as real Release apps and drives them with XCUITest (iOS Simulator) and UiAutomation instrumentation, uiautomator and TalkBack (Android emulator). Results and residual physical-hardware limits are in evidence/native-sim/.
WOFF2 is not a native font asset. @bloxwap/hig-native-fonts ships 15 static Bloxwap Sans/Mono (plus Korean and Simplified Chinese Sans) TTFs generated reproducibly from pinned Font 0.1.2 sources, with a typed fontManifest export and @bloxwap/hig-native-fonts/manifest. Install it alongside the tokens, contracts and native tarballs, then require('@bloxwap/hig-native-fonts/fonts/BloxwapSans.ttf') and register the faces with expo-font before setting the native provider fontFamily, as the gallery does. @bloxwap/hig-tokens no longer contains font binaries (#64); see native font migration. Rasterization on physical displays remains part of #55. New repositories follow docs/governance/new-repository.md.
Install the tokens tarball alone and import CSS variables or typed tokens. No React/RN/audio peer is required. Plain HTML uses semantic --hig-* roles.
@bloxwap/hig-tokens/css defines every role a plain CSS host needs, so nobody has to read the manifest or generate role files:
| Roles | \nExample | \nValues | \n
|---|---|---|
| Color | \n--hig-surface, --hig-action | \nsRGB, then OKLCH/P3 in @supports | \n
| Space | \n--hig-space-md | \nxs–xxxl, section, in rem | \n
| Font | \n--hig-font-sans, --hig-font-mono | \n@bloxwap/font Next variable, then literal family | \n
| Radius | \n--hig-radius-md, --hig-radius-pill | \nsm md lg xl in rem; pill 9999px | \n
| Type | \n--hig-type-body-size, --hig-type-body-line-height, --hig-type-body-weight, --hig-type-body | \ncaption label body title display; the bare role is a font shorthand in Sans | \n
| Motion | \n--hig-motion-duration-base, --hig-motion-easing-standard | \nfast base slow ms; 0ms under prefers-reduced-motion: reduce or [data-hig-motion='reduced'] | \n
| Density | \n--hig-density-control, --hig-density-compact-gap | \ncontrol target gap per mode; the unprefixed roles follow [data-hig-density='compact'] | \n
@import '@bloxwap/hig-tokens/css';\n.card { border-radius: var(--hig-radius-lg); padding: var(--hig-space-lg); font: var(--hig-type-body); }\n.card h2 { font: var(--hig-type-title); }\n.card button { min-height: var(--hig-density-control); transition: background var(--hig-motion-duration-fast) var(--hig-motion-easing-standard); }\n``` Tailwind may reference these values through host configuration; HIG does not require content scans or a shadcn registry. Native uses dp and explicit hex/channel maps; do not feed CSS functions or rename rem to dp. The audited monorepo web/native rem roots are both 16; HIG supports StyleSheet rather than claiming a verified NativeWind consumer. See the source-reconciliation chapter for native font generation and registration.\n\n## Optional chart, sound and haptics\n\nChart is DOM-only and lazy; install @bloxwap/chart 0.3.0 for that entry and supply a textual summary. Native uses labeled readouts/lists. Feedback install paths, preferences, iOS physical-tap limitations and Expo backends are in the feedback chapters. Keep essential outcome text available with both channels off.\n\n## Stable citations and upgrades\n\nCite “Bloxwap HIG 0.1.0 candidate, chapter/anchor” plus an immutable GitHub commit permalink. Branch and docs preview links are mutable. Upgrade tokens, contracts, renderer, docs/examples and semantic cue mapping together; compare API behavior and adopt behind a rollback flag. Token appearance and accessibility behavior changes require semver review. No publication, release or tag is performed by this implementation.\n\nThe native fixture pins React **19.1.0**, matching the RN 0.81.5 renderer exactly. Web/Next/Fumadocs fixtures use React 19.2.0. Metro explicitly resolves every native `react`/`react/*` import to the native fixture's version so shared-workspace code cannot load web React. Quality and packed-native checks compare the installed version to RN's actual renderer guard; a successful Metro bundle alone does not prove runtime compatibility.\n\n",
"toc": [
{
"label": "React / Vite",
@@ -2571,7 +2571,7 @@
"source": "docs/components/recipes.md",
"api": {
"react": {
- "entry": "recipes",
+ "entry": "recipes/market-row",
"signature": "export declare function MarketRow({ symbol, name, price, change, onSelect }: {\n symbol: string;\n name: string;\n price: number | null;\n change: number | null;\n onSelect: () => void;\n}): import(\"react/jsx-runtime\").JSX.Element;"
},
"native": {
@@ -2597,7 +2597,7 @@
"source": "docs/components/recipes.md",
"api": {
"react": {
- "entry": "recipes",
+ "entry": "recipes/balance-card",
"signature": "export declare function BalanceCard({ label, balance, stale }: {\n label: string;\n balance: number | null;\n stale?: boolean;\n}): import(\"react/jsx-runtime\").JSX.Element;"
},
"native": {
@@ -2623,7 +2623,7 @@
"source": "docs/components/recipes.md",
"api": {
"react": {
- "entry": "recipes",
+ "entry": "recipes/trade-entry",
"signature": "export declare function TradeEntry({ asset, amount, onAmountChange, onConfirm, busy, error, available }: {\n asset: string;\n amount: string;\n onAmountChange: (v: string) => void;\n onConfirm: () => void;\n busy?: boolean;\n error?: string;\n available: string;\n}): import(\"react/jsx-runtime\").JSX.Element;"
},
"native": {
@@ -2647,7 +2647,7 @@
"source": "docs/components/recipes.md",
"api": {
"react": {
- "entry": "recipes",
+ "entry": "recipes/install-command",
"signature": "export declare function InstallCommand({ command, onCopy }: {\n command: string;\n onCopy: () => Promise{command}{status}
{children}{children}{command}{status}