diff --git a/apps/docs/README.md b/apps/docs/README.md index d290747..b005c51 100644 --- a/apps/docs/README.md +++ b/apps/docs/README.md @@ -33,10 +33,11 @@ The presentation follows the Bloxwap HIG and consumes it as packages, not copies pinned, unpublished candidate tarballs in [`vendor/bloxwap-hig/`](../../vendor/bloxwap-hig/README.md). `app/global.css` imports `@bloxwap/hig-tokens/css` and `@bloxwap/hig-react/css` and maps HIG roles onto Fumadocs; it does not declare palette values. -- `styles/hig-roles.generated.css` is generated from the package manifest by - `scripts/hig-tokens.mjs --write` (radius, type, motion and density roles the CSS distribution does not - emit yet). `npm run lint` fails on drift, tarball hash changes, copied palettes, `.btn`-style primitive - copies or font binaries in the docs source. +- Radius, type, motion and density roles (`--hig-radius-*`, `--hig-type-*`, `--hig-motion-*`, + `--hig-density-*`) come straight from `@bloxwap/hig-tokens/css` (bloxwap/hig#66); there is no local + role file. `npm run lint` (`scripts/hig-tokens.mjs --check`) fails if those roles go missing, on tarball + hash changes, copied palettes, `.btn`-style primitive copies, a local `styles/` role layer or font + binaries in the docs source. - Buttons, install tabs/copy, code-window copy, callouts, search error/empty states and the playground loading status use HIG components (`Button`, `IconButton`, `Tabs`, `Surface`, `Callout`, `Alert`, `EmptyState`, `Spinner`). The embedded demo keeps the SDK's own controls, themed from HIG roles. @@ -94,7 +95,7 @@ chrome's `--cts-font`/`--cts-mono` at Bloxwap Sans/Mono, and sets the canvas `theme.fontFamily` to Bloxwap Sans and `monoFamily`/`scaleFontFamily` (status line, drawing labels and scales) to Bloxwap Mono. The standalone playground and SDK presets retain their existing font defaults. -Social cards use the static Bloxwap Sans faces shipped in `@bloxwap/hig-tokens/fonts` (OFL). +Social cards use the static Bloxwap Sans faces shipped in `@bloxwap/hig-native-fonts` (OFL), a build-time-only dependency; the web `@bloxwap/hig-tokens` tarball no longer carries font binaries (bloxwap/hig#64). HIG presentation, pinned candidate provenance, validation, exceptions and upgrade/rollback instructions are recorded in [the adoption report](../../docs/hig-adoption/README.md). diff --git a/apps/docs/app/global.css b/apps/docs/app/global.css index 583db9b..749a2fb 100644 --- a/apps/docs/app/global.css +++ b/apps/docs/app/global.css @@ -3,7 +3,6 @@ @import 'fumadocs-ui/css/preset.css'; @import '@bloxwap/hig-tokens/css'; @import '@bloxwap/hig-react/css'; -@import '../styles/hig-roles.generated.css'; @theme inline { --font-sans: var(--font-bloxwap-sans), ui-rounded, system-ui, sans-serif; @@ -73,7 +72,7 @@ html > body[data-scroll-locked] { #nd-page > p { font-size: var(--hig-type-body-size); - line-height: var(--hig-type-body-line); + line-height: var(--hig-type-body-line-height); } .prose { @@ -140,7 +139,7 @@ html > body[data-scroll-locked] { min-height: 2.5rem; padding: 0.5rem 0.75rem; border-radius: var(--hig-radius-pill); - transition: background-color var(--hig-duration-fast) var(--ease-spring), color var(--hig-duration-fast) var(--ease-spring); + transition: background-color var(--hig-motion-duration-fast) var(--ease-spring), color var(--hig-motion-duration-fast) var(--ease-spring); font-size: 0.875rem; font-weight: 600; } @@ -155,18 +154,18 @@ html > body[data-scroll-locked] { * point HIG's 'Bloxwap Sans'/'Bloxwap Mono' at the loaded faces, and let links and icons share the button. * Dense docs regions opt into HIG compact density on fine pointers; coarse pointers keep 48px targets. */ -.hig-button { display: inline-flex; align-items: center; justify-content: center; gap: var(--hig-space-sm); font-family: var(--font-sans); text-decoration: none; touch-action: manipulation; transition: filter var(--hig-duration-fast) var(--ease-spring), transform var(--hig-duration-fast) var(--ease-spring); } +.hig-button { display: inline-flex; align-items: center; justify-content: center; gap: var(--hig-space-sm); font-family: var(--font-sans); text-decoration: none; touch-action: manipulation; transition: filter var(--hig-motion-duration-fast) var(--ease-spring), transform var(--hig-motion-duration-fast) var(--ease-spring); } .hig-button svg { flex: none; width: 1rem; height: 1rem; } .hig-button > span[aria-hidden='true'] { display: contents; } .hig-surface pre { font-family: var(--font-mono); } -[data-hig-density='compact'] { --hig-control: var(--hig-control-compact); --hig-gap: var(--hig-space-sm); } +[data-hig-density='compact'] { --hig-control: var(--hig-density-compact-control); --hig-gap: var(--hig-space-sm); } [data-hig-density='compact'] .hig-button { padding: 0 var(--hig-space-md); font-size: var(--hig-type-label-size); } .docs-icon-button.hig-button { position: relative; width: var(--hig-control); padding: 0; } /* HIG busy text stays announced but is visually hidden inside icon-only buttons. */ .docs-icon-button .hig-busy { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } .copy-feedback { color: var(--hig-negative); font-size: var(--hig-type-caption-size); } @media (pointer: coarse) { - [data-hig-density='compact'] { --hig-control: var(--hig-control-comfortable); } + [data-hig-density='compact'] { --hig-control: var(--hig-density-comfortable-control); } } /* Chart-specific layout on the scale above; typography, surfaces, and states follow workers/docs. */ @@ -210,7 +209,7 @@ html > body[data-scroll-locked] { .window-dots { display: flex; gap: var(--hig-space-xs); } .window-dots > i { width: 6px; height: 6px; border-radius: var(--hig-radius-pill); background: var(--hig-nested); } .code-actions { display: flex; align-items: center; gap: var(--hig-space-xs); margin-right: calc(-1 * var(--hig-space-md)); } -.code-toolbar { min-height: var(--hig-control-compact); } +.code-toolbar { min-height: var(--hig-density-compact-control); } /* HIG CodeWindow recipe inside the hero card: the card supplies the surface, the recipe its language label and code. */ .code-window > .hig-surface { padding: 0; border-radius: 0; background: transparent; } .code-window > .hig-surface > .hig-text { margin: 0; padding: var(--hig-space-sm) var(--hig-space-xxl) 0; font: var(--text-2xs) / 1.5 var(--font-mono); color: color-mix(in oklab, var(--hig-info) 60%, var(--hig-text)); } @@ -244,9 +243,9 @@ html > body[data-scroll-locked] { /* Search (header and docs sidebar): a zero-stroke filled pill at the small control height, with key chips one step lighter than the box. */ button[data-search-full] { - height: var(--hig-control-compact); gap: var(--hig-space-sm); padding: 0 var(--hig-space-xs) 0 var(--hig-space-md); + height: var(--hig-density-compact-control); gap: var(--hig-space-sm); padding: 0 var(--hig-space-xs) 0 var(--hig-space-md); border: 0; border-radius: var(--hig-radius-pill); background: var(--hig-surface); color: var(--hig-muted); font-size: var(--text-sm); - transition: background-color var(--hig-duration-fast) var(--ease-spring), color var(--hig-duration-fast) var(--ease-spring); + transition: background-color var(--hig-motion-duration-fast) var(--ease-spring), color var(--hig-motion-duration-fast) var(--ease-spring); } button[data-search-full]:hover { background: var(--hig-nested); color: var(--hig-text); } button[data-search-full] kbd { @@ -300,13 +299,13 @@ button[data-search-full] kbd { .guide-links { display: grid; gap: var(--hig-space-md); } .guide-links a { display: flex; align-items: center; gap: var(--hig-space-xl); - transition: background-color var(--hig-duration-fast) var(--ease-spring); + transition: background-color var(--hig-motion-duration-fast) var(--ease-spring); } .guide-links a:hover { background: var(--hig-nested); } .guide-links a > span { font: var(--text-2xs) var(--font-mono); color: var(--color-fd-muted-foreground); } -.guide-links a > svg { flex: none; margin-left: auto; width: 1rem; height: 1rem; color: var(--color-fd-muted-foreground); transition: color var(--hig-duration-fast) var(--ease-spring), transform var(--hig-duration-fast) var(--ease-spring); } +.guide-links a > svg { flex: none; margin-left: auto; width: 1rem; height: 1rem; color: var(--color-fd-muted-foreground); transition: color var(--hig-motion-duration-fast) var(--ease-spring), transform var(--hig-motion-duration-fast) var(--ease-spring); } .guide-links a:hover > svg { color: var(--color-fd-primary); transform: translateX(2px); } -.guide-links h3 { font-size: var(--text-sm); margin-bottom: var(--hig-space-xs); font-weight: 600; transition: color var(--hig-duration-fast) var(--ease-spring); } +.guide-links h3 { font-size: var(--text-sm); margin-bottom: var(--hig-space-xs); font-weight: 600; transition: color var(--hig-motion-duration-fast) var(--ease-spring); } .guide-links a:hover h3 { color: var(--color-fd-primary); } .guide-links p { color: var(--color-fd-muted-foreground); font-size: var(--text-xs); } /* Full-bleed rule; content inset to the header's box so both edges line up with the nav. */ @@ -314,14 +313,14 @@ button[data-search-full] kbd { .site-footer { margin-top: auto; padding: var(--hig-space-section) max(var(--hig-space-lg), calc((100% - var(--fd-layout-width, 1400px)) / 2 + var(--hig-space-lg))) var(--hig-space-section); } /* Page end: Edit on GitHub as a quiet ghost pill, prev/next as zero-stroke fill cards (the landing's card style). */ #nd-page .edit-on-github { - align-self: flex-start; height: var(--hig-control-compact); padding: 0 var(--hig-space-md); border: 0; border-radius: var(--hig-radius-pill); + align-self: flex-start; height: var(--hig-density-compact-control); padding: 0 var(--hig-space-md); border: 0; border-radius: var(--hig-radius-pill); background: transparent; color: var(--hig-muted); font-size: var(--text-sm); - transition: background-color var(--hig-duration-fast) var(--ease-spring), color var(--hig-duration-fast) var(--ease-spring); + transition: background-color var(--hig-motion-duration-fast) var(--ease-spring), color var(--hig-motion-duration-fast) var(--ease-spring); } #nd-page .edit-on-github:hover { background: var(--hig-surface); color: var(--hig-text); } .page-nav > a { padding: var(--hig-space-xl) var(--hig-space-xxl); border: 0; border-radius: var(--hig-radius-xl); background: var(--hig-surface); - transition: background-color var(--hig-duration-fast) var(--ease-spring), color var(--hig-duration-fast) var(--ease-spring); + transition: background-color var(--hig-motion-duration-fast) var(--ease-spring), color var(--hig-motion-duration-fast) var(--ease-spring); } .page-nav > a:hover { background: var(--hig-nested); color: var(--hig-action); } .footer-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--hig-space-xxl); row-gap: var(--hig-space-section); } @@ -332,7 +331,7 @@ button[data-search-full] kbd { /* The wordmark's box reserves descender room for the "p"; shift it so the cap height (not the box) centers on the icon: (143/2 - (149-74.6)/2) / 223.6 of the viewBox. */ .footer-wordmark { width: auto; height: 32px; transform: translateY(15.3%); } .footer-col h2 { margin: 0 0 var(--hig-space-md); color: var(--color-fd-muted-foreground); font: 700 var(--text-2xs) / 1.5 var(--font-sans); letter-spacing: .14em; text-transform: uppercase; } -.footer-col a, .footer-base a { transition: color var(--hig-duration-fast) var(--ease-spring), opacity var(--hig-duration-fast) var(--ease-spring); } +.footer-col a, .footer-base a { transition: color var(--hig-motion-duration-fast) var(--ease-spring), opacity var(--hig-motion-duration-fast) var(--ease-spring); } .footer-col a { display: block; width: fit-content; padding: var(--hig-space-xs) 0; color: var(--color-fd-foreground); font-size: var(--text-sm); opacity: .8; } .footer-col a:hover, .footer-base a:hover { color: var(--color-fd-primary); opacity: 1; } .footer-base { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--hig-space-sm); margin-top: var(--hig-space-section); color: var(--color-fd-muted-foreground); font-size: var(--text-xs); } @@ -344,13 +343,13 @@ button[data-search-full] kbd { } @media (max-width: 480px) { .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } } .docs-sidebar-links { display: flex; align-items: center; gap: var(--hig-space-lg); padding-top: var(--hig-space-lg); font-size: var(--text-xs); color: var(--color-fd-muted-foreground); } -.docs-sidebar-links a { transition: color var(--hig-duration-fast) var(--ease-spring); } +.docs-sidebar-links a { transition: color var(--hig-motion-duration-fast) var(--ease-spring); } .docs-sidebar-links a:hover { color: var(--color-fd-foreground); } .not-found { max-width: 37.5rem; padding: 7.5rem var(--hig-space-xxl); margin: 0 auto; } .not-found h1 { font-size: var(--text-4xl); margin: var(--hig-space-xxl) 0; } .not-found .hig-button { margin-top: var(--hig-space-xxxl); } .not-found-links { display: flex; flex-wrap: wrap; gap: var(--hig-space-sm) var(--hig-space-xl); margin-top: var(--hig-space-xxxl); font: var(--text-2xs) / 1.5 var(--font-mono); letter-spacing: .09em; } -.not-found-links a { color: var(--color-fd-muted-foreground); transition: color var(--hig-duration-fast) var(--ease-spring); } +.not-found-links a { color: var(--color-fd-muted-foreground); transition: color var(--hig-motion-duration-fast) var(--ease-spring); } .not-found-links a:hover { color: var(--color-fd-foreground); } @media (max-width: 800px) { .home { padding-top: var(--hig-space-xxxl); } @@ -371,11 +370,11 @@ button[data-search-full] kbd { } /* HIG type roles and adaptive targets; the dense chart keeps compact controls. */ -body { font-size: var(--hig-type-body-size); line-height: var(--hig-type-body-line); } +body { font-size: var(--hig-type-body-size); line-height: var(--hig-type-body-line-height); } .hero h1 { font-size: clamp(var(--hig-type-title-size), 4.4vw, var(--hig-type-display-size)); line-height: 1.0833; font-weight: var(--hig-type-display-weight); } -#nd-page h1 { font-size: var(--hig-type-title-size); line-height: var(--hig-type-title-line); font-weight: var(--hig-type-title-weight); } +#nd-page h1 { font-size: var(--hig-type-title-size); line-height: var(--hig-type-title-line-height); font-weight: var(--hig-type-title-weight); } @media (pointer: coarse) { - .docs-app-link, #nd-page .edit-on-github { min-height: var(--hig-control-comfortable); } + .docs-app-link, #nd-page .edit-on-github { min-height: var(--hig-density-comfortable-control); } } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0ms !important; transition-duration: 0ms !important; scroll-behavior: auto !important; } diff --git a/apps/docs/lib/og-card.tsx b/apps/docs/lib/og-card.tsx index 0f3f651..3a07fe5 100644 --- a/apps/docs/lib/og-card.tsx +++ b/apps/docs/lib/og-card.tsx @@ -12,9 +12,9 @@ import { socialImageSize } from './social'; const ink = hig.colors.text.srgb; // --foreground const muted = hig.colors.muted.srgb; // --muted-foreground const bar: [color: string, share: number][] = [[hig.colors.action.srgb, 62], [hig.colors.info.srgb, 14], ['#b300ff', 10], ['#ff479c', 8], ['#fffb38', 6]]; -// Static Bloxwap Sans faces for the OG renderer come from @bloxwap/hig-tokens/fonts (OFL, derived from +// Static Bloxwap Sans faces for the OG renderer come from @bloxwap/hig-native-fonts (OFL, derived from // @bloxwap/font 0.1.2 upstream); the docs no longer keep copied font binaries. Hoisted by the workspace lock. -const higFonts = join(process.cwd(), '../../node_modules/@bloxwap/hig-tokens/assets/fonts'); +const higFonts = join(process.cwd(), '../../node_modules/@bloxwap/hig-native-fonts/fonts'); const assets = Promise.all([ readFile(join(higFonts, 'BloxwapSans-Bold.ttf')), readFile(join(higFonts, 'BloxwapSans-Black.ttf')), diff --git a/apps/docs/package.json b/apps/docs/package.json index e82c355..50b960c 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -16,9 +16,10 @@ "dependencies": { "@bloxwap/chart": "0.3.0", "@bloxwap/font": "0.1.2", - "@bloxwap/hig-contracts": "file:../../vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha7c67a07c.tgz", - "@bloxwap/hig-react": "file:../../vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha7c67a07c.tgz", - "@bloxwap/hig-tokens": "file:../../vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha7c67a07c.tgz", + "@bloxwap/hig-contracts": "file:../../vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.shad7ff4780.tgz", + "@bloxwap/hig-native-fonts": "file:../../vendor/bloxwap-hig/bloxwap-hig-native-fonts-0.1.0-candidate.shad7ff4780.tgz", + "@bloxwap/hig-react": "file:../../vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.shad7ff4780.tgz", + "@bloxwap/hig-tokens": "file:../../vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.shad7ff4780.tgz", "fumadocs-core": "16.15.14", "fumadocs-mdx": "15.4.5", "fumadocs-ui": "16.15.14", diff --git a/apps/docs/scripts/hig-tokens.mjs b/apps/docs/scripts/hig-tokens.mjs index 241bab4..e6e9761 100644 --- a/apps/docs/scripts/hig-tokens.mjs +++ b/apps/docs/scripts/hig-tokens.mjs @@ -1,8 +1,9 @@ // HIG adoption guard for the docs site. Tokens, CSS and components come from the vendored -// @bloxwap/hig-* candidate tarballs (vendor/bloxwap-hig); this script only derives the manifest roles -// that @bloxwap/hig-tokens/css does not emit as variables yet (radius, type, motion, density) and the -// canvas-compatible sRGB chart theme, and fails CI when copies of HIG sources creep back in. -import { readFile, readdir, writeFile } from 'node:fs/promises'; +// @bloxwap/hig-* candidate tarballs (vendor/bloxwap-hig). @bloxwap/hig-tokens/css emits the radius, type, +// motion and density roles itself (bloxwap/hig#66); this script only derives the canvas-compatible sRGB +// chart theme and fails CI when copies of HIG sources or generated role files creep back in. +import { readFile, readdir } from 'node:fs/promises'; +import { existsSync } from 'node:fs'; import { createHash } from 'node:crypto'; import { createRequire } from 'node:module'; import assert from 'node:assert/strict'; @@ -21,28 +22,19 @@ export const chartTheme = { series: { upColor: colors.buy, downColor: colors.sell, wickUpColor: colors.buy, wickDownColor: colors.sell, borderUpColor: colors.buy, borderDownColor: colors.sell }, }; -const rem = (px) => `${px / 16}rem`; -const vars = []; -for (const [key, value] of Object.entries(manifest.radius)) vars.push(` --hig-radius-${key}: ${key === 'pill' ? '9999px' : rem(value)};`); -for (const [key, role] of Object.entries(manifest.type)) vars.push(` --hig-type-${key}-size: ${rem(role.size)};`, ` --hig-type-${key}-line: ${rem(role.lineHeight)};`, ` --hig-type-${key}-weight: ${role.weight};`); -for (const [key, value] of Object.entries(manifest.motion)) vars.push(` --hig-duration-${key}: ${value}ms;`); -for (const [key, value] of Object.entries(manifest.density)) vars.push(` --hig-control-${key}: ${rem(value.control)};`); -const css = `/* Generated from @bloxwap/hig-tokens ${manifest.version} manifest by scripts/hig-tokens.mjs; do not edit. */\n:root {\n${vars.join('\n')}\n}\n@media (prefers-reduced-motion: reduce) {\n :root { ${Object.keys(manifest.motion).map((key) => `--hig-duration-${key}: 0ms;`).join(' ')} }\n}\n`; -const output = new URL('../styles/hig-roles.generated.css', import.meta.url); -if (process.argv.includes('--write')) await writeFile(output, css); - if (process.argv.includes('--check')) { - assert.equal(await readFile(output, 'utf8'), css, 'HIG role drift: run node apps/docs/scripts/hig-tokens.mjs --write'); + const tokensCss = await readFile(tokensCssPath, 'utf8'); + for (const role of ['--hig-radius-xl', '--hig-type-body-line-height', '--hig-motion-duration-fast', '--hig-density-compact-control']) assert.ok(tokensCss.includes(`${role}:`), `@bloxwap/hig-tokens/css must define ${role}`); const vendor = new URL('../../../vendor/bloxwap-hig/', import.meta.url); const provenance = JSON.parse(await readFile(new URL('provenance.json', vendor), 'utf8')); for (const [file, hash] of Object.entries(provenance.sha256)) assert.equal(createHash('sha256').update(await readFile(new URL(file, vendor))).digest('hex'), hash, `Vendored HIG tarball changed: ${file}`); const docsPackage = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8')); - for (const name of ['tokens', 'contracts', 'react']) { + for (const name of ['tokens', 'contracts', 'react', 'native-fonts']) { const spec = docsPackage.dependencies[`@bloxwap/hig-${name}`]; assert.ok(spec?.startsWith('file:../../vendor/bloxwap-hig/') && spec.includes(provenance.version), `@bloxwap/hig-${name} must come from the pinned vendored tarball`); assert.equal(JSON.parse(await readFile(new URL(`../../../node_modules/@bloxwap/hig-${name}/package.json`, import.meta.url), 'utf8')).version, provenance.version, `Installed @bloxwap/hig-${name} is not ${provenance.version}; run npm ci`); } - assert.deepEqual((await readdir(new URL('../styles/', import.meta.url))).sort(), ['hig-roles.generated.css'], 'Only the generated HIG role file belongs in styles/'); + assert.ok(!existsSync(new URL('../styles/', import.meta.url)), 'HIG roles come from @bloxwap/hig-tokens/css; do not add a local styles/ role layer'); // No copied palettes, token snapshots, primitive classes or font binaries in the docs shell. const forbidden = [ [/--(hig|bloxwap)-[\w-]+\s*:\s*(#|oklch\(|rgb|color\()/, 'copied palette declaration'], @@ -54,12 +46,12 @@ if (process.argv.includes('--check')) { const path = new URL(entry.name + (entry.isDirectory() ? '/' : ''), dir); if (entry.isDirectory()) await checkSurface(path); else if (/\.(ttf|otf|woff2?)$/.test(entry.name)) assert.fail(`Copied font binary: ${path}`); - else if (/\.(css|tsx?)$/.test(entry.name) && !entry.name.endsWith('.generated.css')) { + else if (/\.(css|tsx?)$/.test(entry.name)) { const source = await readFile(path, 'utf8'); for (const [pattern, reason] of forbidden) assert.ok(!pattern.test(source), `${reason}: ${path.pathname}`); } } } - for (const dir of ['app/', 'components/', 'lib/', 'styles/']) await checkSurface(new URL(`../${dir}`, import.meta.url)); - console.log(`HIG ${provenance.version} tarball provenance, installed versions, generated roles and copy drift checks passed.`); + for (const dir of ['app/', 'components/', 'lib/']) await checkSurface(new URL(`../${dir}`, import.meta.url)); + console.log(`HIG ${provenance.version} tarball provenance, installed versions, token roles and copy drift checks passed.`); } diff --git a/apps/docs/scripts/test-hig-browser.mjs b/apps/docs/scripts/test-hig-browser.mjs index 0985f18..bf0a605 100644 --- a/apps/docs/scripts/test-hig-browser.mjs +++ b/apps/docs/scripts/test-hig-browser.mjs @@ -80,7 +80,7 @@ try { const presentation = await page.evaluate(() => { const css = getComputedStyle(document.documentElement); const button = document.querySelector('.hig-button'); - return { surface: css.getPropertyValue('--hig-surface').trim(), font: getComputedStyle(document.body).fontFamily, buttonFont: getComputedStyle(button).fontFamily, motion: css.getPropertyValue('--hig-duration-fast').trim(), transform: getComputedStyle(button).transform, legacy: ['--card', '--bloxwap-green', '--space-md'].filter(name => css.getPropertyValue(name).trim()) }; + return { surface: css.getPropertyValue('--hig-surface').trim(), font: getComputedStyle(document.body).fontFamily, buttonFont: getComputedStyle(button).fontFamily, motion: css.getPropertyValue('--hig-motion-duration-fast').trim(), transform: getComputedStyle(button).transform, legacy: ['--card', '--bloxwap-green', '--space-md'].filter(name => css.getPropertyValue(name).trim()) }; }); assert.ok(await sameColor(page, presentation.surface, cssColor('surface')), `--hig-surface ${presentation.surface}`); assert.match(presentation.font, /BloxwapSans|Bloxwap Sans|bloxwap/i); diff --git a/apps/docs/styles/hig-roles.generated.css b/apps/docs/styles/hig-roles.generated.css deleted file mode 100644 index d992734..0000000 --- a/apps/docs/styles/hig-roles.generated.css +++ /dev/null @@ -1,31 +0,0 @@ -/* Generated from @bloxwap/hig-tokens 0.1.0 manifest by scripts/hig-tokens.mjs; do not edit. */ -:root { - --hig-radius-sm: 0.375rem; - --hig-radius-md: 0.5rem; - --hig-radius-lg: 0.625rem; - --hig-radius-xl: 0.875rem; - --hig-radius-pill: 9999px; - --hig-type-caption-size: 0.75rem; - --hig-type-caption-line: 1.125rem; - --hig-type-caption-weight: 500; - --hig-type-label-size: 0.875rem; - --hig-type-label-line: 1.25rem; - --hig-type-label-weight: 600; - --hig-type-body-size: 1rem; - --hig-type-body-line: 1.5rem; - --hig-type-body-weight: 400; - --hig-type-title-size: 1.5rem; - --hig-type-title-line: 1.875rem; - --hig-type-title-weight: 600; - --hig-type-display-size: 3rem; - --hig-type-display-line: 3.25rem; - --hig-type-display-weight: 600; - --hig-duration-fast: 180ms; - --hig-duration-base: 260ms; - --hig-duration-slow: 320ms; - --hig-control-comfortable: 3rem; - --hig-control-compact: 2.25rem; -} -@media (prefers-reduced-motion: reduce) { - :root { --hig-duration-fast: 0ms; --hig-duration-base: 0ms; --hig-duration-slow: 0ms; } -} diff --git a/docs/hig-adoption/README.md b/docs/hig-adoption/README.md index 92197a2..567b74e 100644 --- a/docs/hig-adoption/README.md +++ b/docs/hig-adoption/README.md @@ -14,10 +14,10 @@ repository-level evidence for [hig#36](https://github.com/bloxwap/hig/issues/36) - **Tokens and fonts.** The shell imports `@bloxwap/hig-tokens/css` and `@bloxwap/hig-react/css` and uses `--hig-*` roles directly. The shadcn-style alias layer (`--card`, `--bloxwap-green`, `--space-*`, …) - and the copied token snapshot are gone. Radius/type/motion/density roles, which the CSS distribution - does not emit yet, are generated from the package manifest (`styles/hig-roles.generated.css`). Body and + and the copied token snapshot are gone. Radius/type/motion/density roles come from `@bloxwap/hig-tokens/css` + itself since bloxwap/hig#66, so the generated `styles/hig-roles.generated.css` is gone. Body and code fonts stay on `@bloxwap/font@0.1.2`; the social-card renderer now reads the static Bloxwap Sans faces - from `@bloxwap/hig-tokens/fonts` instead of copied TTFs. + from `@bloxwap/hig-native-fonts` (moved out of the web tokens tarball in bloxwap/hig#64) instead of copied TTFs. - **Shell, navigation and search.** Fumadocs keeps layout, sidebar, mobile navigation and the static search index. HIG roles theme it; search failure renders HIG `Alert`, no results renders HIG `EmptyState`. - **Code, install and copy.** Install tabs are HIG `Tabs`; each command follows the HIG `InstallCommand` diff --git a/package-lock.json b/package-lock.json index a1eab26..17ceb4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,9 +20,10 @@ "dependencies": { "@bloxwap/chart": "0.3.0", "@bloxwap/font": "0.1.2", - "@bloxwap/hig-contracts": "file:../../vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha7c67a07c.tgz", - "@bloxwap/hig-react": "file:../../vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha7c67a07c.tgz", - "@bloxwap/hig-tokens": "file:../../vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha7c67a07c.tgz", + "@bloxwap/hig-contracts": "file:../../vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.shad7ff4780.tgz", + "@bloxwap/hig-native-fonts": "file:../../vendor/bloxwap-hig/bloxwap-hig-native-fonts-0.1.0-candidate.shad7ff4780.tgz", + "@bloxwap/hig-react": "file:../../vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.shad7ff4780.tgz", + "@bloxwap/hig-tokens": "file:../../vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.shad7ff4780.tgz", "fumadocs-core": "16.15.14", "fumadocs-mdx": "15.4.5", "fumadocs-ui": "16.15.14", @@ -94,19 +95,25 @@ } }, "node_modules/@bloxwap/hig-contracts": { - "version": "0.1.0-candidate.sha7c67a07c", - "resolved": "file:vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha7c67a07c.tgz", - "integrity": "sha512-QJ2gdBNpzzDM8pmGM3Vtw0nPPSdCFGXFtZvAaRhGZmGRw4asG4MIcIhfceXJaa3StuweZsxD/DSwzKNl71MwmA==", + "version": "0.1.0-candidate.shad7ff4780", + "resolved": "file:vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.shad7ff4780.tgz", + "integrity": "sha512-SgBhqA5wzljupfi7EiEIiPvsUb4+rw/AKNan9FoS2TfS2xg7T54HOj7XLTKGJZ90yT+tzj4teNGVYPS2oHIF8A==", + "license": "MIT" + }, + "node_modules/@bloxwap/hig-native-fonts": { + "version": "0.1.0-candidate.shad7ff4780", + "resolved": "file:vendor/bloxwap-hig/bloxwap-hig-native-fonts-0.1.0-candidate.shad7ff4780.tgz", + "integrity": "sha512-XUQeeSfkFlF65b10mjqAWW6mQfjy82bqO7C9QZ9gBgAzmDTUso0VSk6KQB5uwtWIWl2/egeU+wZYDHsBb0Msug==", "license": "MIT" }, "node_modules/@bloxwap/hig-react": { - "version": "0.1.0-candidate.sha7c67a07c", - "resolved": "file:vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha7c67a07c.tgz", - "integrity": "sha512-muTFRY9Co49PO9ZmmMeZDNscjtpnLamaa/zSOOazoQjjoBIQVpqa13jJw9x1qguPNAGaV9AN4v/UlBfIPEwiQA==", + "version": "0.1.0-candidate.shad7ff4780", + "resolved": "file:vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.shad7ff4780.tgz", + "integrity": "sha512-Ablf7S3bsbcY/uQehAnNjMW7qE8pmJDy6mte80tqyc625AGf704JKwEyyxTr/CfqGrsS1rvJahNtWufxLEIlBQ==", "license": "MIT", "dependencies": { - "@bloxwap/hig-contracts": "0.1.0-candidate.sha7c67a07c", - "@bloxwap/hig-tokens": "0.1.0-candidate.sha7c67a07c" + "@bloxwap/hig-contracts": "0.1.0-candidate.shad7ff4780", + "@bloxwap/hig-tokens": "0.1.0-candidate.shad7ff4780" }, "peerDependencies": { "@bloxwap/chart": "^0.3.0", @@ -136,9 +143,9 @@ } }, "node_modules/@bloxwap/hig-tokens": { - "version": "0.1.0-candidate.sha7c67a07c", - "resolved": "file:vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha7c67a07c.tgz", - "integrity": "sha512-GEgLcN1IQgqJfMvfmK88tn0B8y5ixGbzjnj7WO+oN9IHXJ7GC1TM7FQwDssanOaxrpDJisBLURR99WwE+rEHGw==", + "version": "0.1.0-candidate.shad7ff4780", + "resolved": "file:vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.shad7ff4780.tgz", + "integrity": "sha512-orzxiWBRhJr5uXV8MVtU5TChFGMIds7TgbxtR2tOTuuq6GgIOmfkrJX+GnLG+nnUVdny3/uxd5QASvb0gcICYg==", "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { diff --git a/vendor/bloxwap-hig/README.md b/vendor/bloxwap-hig/README.md index 12790b8..275339e 100644 --- a/vendor/bloxwap-hig/README.md +++ b/vendor/bloxwap-hig/README.md @@ -6,13 +6,14 @@ feedback engines are copied into this repository. | Tarball | Used for | | --- | --- | -| `bloxwap-hig-tokens-0.1.0-candidate.sha7c67a07c.tgz` | `@bloxwap/hig-tokens/css` (shell and chart demo), typed manifest (chart theme, generated roles, OG colors), static OG font faces | -| `bloxwap-hig-contracts-0.1.0-candidate.sha7c67a07c.tgz` | runtime dependency of `@bloxwap/hig-react` | -| `bloxwap-hig-react-0.1.0-candidate.sha7c67a07c.tgz` | `@bloxwap/hig-react/css`, `button`, `navigation`, `surface`, `status` entries | +| `bloxwap-hig-tokens-0.1.0-candidate.shad7ff4780.tgz` | `@bloxwap/hig-tokens/css` (shell and chart demo, including the radius/type/motion/density roles), typed manifest (chart theme, OG colors). No font binaries since bloxwap/hig#64 | +| `bloxwap-hig-native-fonts-0.1.0-candidate.shad7ff4780.tgz` | Static Bloxwap Sans Bold/Black TTFs for the OG card renderer only (build time, never served) | +| `bloxwap-hig-contracts-0.1.0-candidate.shad7ff4780.tgz` | runtime dependency of `@bloxwap/hig-react` | +| `bloxwap-hig-react-0.1.0-candidate.shad7ff4780.tgz` | `@bloxwap/hig-react/css`, `button`, `navigation`, `surface`, `status` entries | -Provenance: [bloxwap/hig@7c67a07](https://github.com/bloxwap/hig/tree/7c67a07ce20c02264b0fdc57e5f27d020cfd6fdc), +Provenance: [bloxwap/hig@d7ff478](https://github.com/bloxwap/hig/tree/d7ff478049bbe71056d9248dc48e08166be4431e), built with `npm ci && npm run build && npm run release:dry-run -- --channel candidate` (plus -`npm run generate:fonts` for the native TTFs the dry run packs). SHA-256 hashes are in `provenance.json` +`npm run generate:fonts` for the TTFs in `@bloxwap/hig-native-fonts`). SHA-256 hashes are in `provenance.json` and checked by `npm run lint`. MIT licenses travel inside each tarball. ## Notes @@ -29,6 +30,6 @@ and checked by `npm run lint`. MIT licenses travel inside each tarball. ## Upgrade or roll back Rebuild the tarballs from a reviewed HIG commit, replace them here, update `provenance.json` and the -three `file:` specs, run `npm install`, `node apps/docs/scripts/hig-tokens.mjs --write`, then +`file:` specs, run `npm install`, then `npm run lint`, `npm run typecheck`, the docs build and `npm run docs:test`. Rolling back is an atomic revert of the commit that changed this folder, the lockfile and the docs imports together. diff --git a/vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha7c67a07c.tgz b/vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha7c67a07c.tgz deleted file mode 100644 index 751a262..0000000 Binary files a/vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.sha7c67a07c.tgz and /dev/null differ diff --git a/vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.shad7ff4780.tgz b/vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.shad7ff4780.tgz new file mode 100644 index 0000000..54b5bb3 Binary files /dev/null and b/vendor/bloxwap-hig/bloxwap-hig-contracts-0.1.0-candidate.shad7ff4780.tgz differ diff --git a/vendor/bloxwap-hig/bloxwap-hig-native-fonts-0.1.0-candidate.shad7ff4780.tgz b/vendor/bloxwap-hig/bloxwap-hig-native-fonts-0.1.0-candidate.shad7ff4780.tgz new file mode 100644 index 0000000..fd2f776 Binary files /dev/null and b/vendor/bloxwap-hig/bloxwap-hig-native-fonts-0.1.0-candidate.shad7ff4780.tgz differ diff --git a/vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha7c67a07c.tgz b/vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha7c67a07c.tgz deleted file mode 100644 index 0c3b865..0000000 Binary files a/vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.sha7c67a07c.tgz and /dev/null differ diff --git a/vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.shad7ff4780.tgz b/vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.shad7ff4780.tgz new file mode 100644 index 0000000..70db788 Binary files /dev/null and b/vendor/bloxwap-hig/bloxwap-hig-react-0.1.0-candidate.shad7ff4780.tgz differ diff --git a/vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha7c67a07c.tgz b/vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha7c67a07c.tgz deleted file mode 100644 index c30feb2..0000000 Binary files a/vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.sha7c67a07c.tgz and /dev/null differ diff --git a/vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.shad7ff4780.tgz b/vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.shad7ff4780.tgz new file mode 100644 index 0000000..5631db0 Binary files /dev/null and b/vendor/bloxwap-hig/bloxwap-hig-tokens-0.1.0-candidate.shad7ff4780.tgz differ diff --git a/vendor/bloxwap-hig/provenance.json b/vendor/bloxwap-hig/provenance.json index b9fc6dc..525c32f 100644 --- a/vendor/bloxwap-hig/provenance.json +++ b/vendor/bloxwap-hig/provenance.json @@ -1,12 +1,13 @@ { "repository": "bloxwap/hig", - "commit": "7c67a07ce20c02264b0fdc57e5f27d020cfd6fdc", - "version": "0.1.0-candidate.sha7c67a07c", - "producedBy": "npm ci && npm run build && npm run release:dry-run -- --channel candidate (Node 22.22.0; native TTFs generated with scripts/generate-native-fonts.py, fonttools 4.61.1)", + "commit": "d7ff478049bbe71056d9248dc48e08166be4431e", + "version": "0.1.0-candidate.shad7ff4780", + "producedBy": "npm ci && npm run build && npm run release:dry-run -- --channel candidate (Node 22.22.0; native TTFs for @bloxwap/hig-native-fonts generated with scripts/generate-native-fonts.py, fonttools 4.61.1 and brotli 1.2.0)", "distribution": "unpublished candidate tarballs; no npm release, tag or GitHub release exists", "sha256": { - "bloxwap-hig-contracts-0.1.0-candidate.sha7c67a07c.tgz": "4519befc8d35c787b2f91302cf46801c82295f6dd33cbf84331be11308d71ef7", - "bloxwap-hig-react-0.1.0-candidate.sha7c67a07c.tgz": "6f3d7cc721ff246c647a2479ba39e898f4ba9d2ba75177b800a9942f5dab11f9", - "bloxwap-hig-tokens-0.1.0-candidate.sha7c67a07c.tgz": "701750f9b85f148533995d9b603f2ea1a6acbe31ac475ac7f8ecce8cd3cd61dc" + "bloxwap-hig-contracts-0.1.0-candidate.shad7ff4780.tgz": "3b05b1edd6f13c7abe0c88495859018aefef25462549d4c3c3b456645737ed92", + "bloxwap-hig-native-fonts-0.1.0-candidate.shad7ff4780.tgz": "a49cce132655ed5cfdba7425f19c5c6677cbf2345b2db186939f15e64984d48b", + "bloxwap-hig-react-0.1.0-candidate.shad7ff4780.tgz": "dee364fd33dee71f8b156bbede2076061b644b23d991c03fe619f3fd71d0f24f", + "bloxwap-hig-tokens-0.1.0-candidate.shad7ff4780.tgz": "0daafe684c2dd33fb531fe73d8ebfdf7b9a1a87dc2a0d32b43a6a7bd0e666e01" } }