From c60c48b23008fb92c7b9969770542d3ba1d60a75 Mon Sep 17 00:00:00 2001 From: Joe Blau <1218847+joeblau@users.noreply.github.com> Date: Tue, 13 Oct 2026 19:08:35 -0700 Subject: [PATCH 1/2] docs: adopt HIG shell presentation and test market playground --- .github/workflows/docs.yml | 8 + .gitignore | 3 + apps/docs/README.md | 20 +- apps/docs/app/brand-tokens.css | 172 ------------------ apps/docs/app/global.css | 105 +++++++---- apps/docs/app/layout.tsx | 4 +- apps/docs/components/copy-button.tsx | 41 ++++- apps/docs/components/install-command.tsx | 36 +--- apps/docs/components/provider.tsx | 11 +- apps/docs/components/search.tsx | 14 +- apps/docs/design-review/hig/README.md | 90 +++++++++ apps/docs/design-review/hig/after-clients.png | Bin 0 -> 2527035 bytes apps/docs/design-review/hig/after-home.png | Bin 0 -> 140469 bytes apps/docs/design-review/hig/after-mobile.png | Bin 0 -> 2172841 bytes apps/docs/design-review/hig/after.json | 8 + .../docs/design-review/hig/before-clients.png | Bin 0 -> 2521720 bytes apps/docs/design-review/hig/before-home.png | Bin 0 -> 122240 bytes apps/docs/design-review/hig/before-mobile.png | Bin 0 -> 2176925 bytes apps/docs/design-review/hig/before.json | 8 + apps/docs/design-review/hig/live-market.json | 7 + apps/docs/design-review/hig/validation.txt | 69 +++++++ apps/docs/e2e/shell.spec.ts | 134 ++++++++++++++ apps/docs/lib/fonts.ts | 9 - apps/docs/package.json | 11 +- apps/docs/playwright.config.ts | 15 ++ apps/docs/public/fonts/README.md | 2 +- apps/docs/public/fonts/SpaceGrotesk-Bold.ttf | Bin 116056 -> 0 bytes apps/docs/public/fonts/SpaceGrotesk-OFL.txt | 93 ---------- apps/docs/scripts/capture-hig.mjs | 16 ++ apps/docs/vendor/hig/LICENSE | 5 + apps/docs/vendor/hig/README.md | 18 ++ apps/docs/vendor/hig/package.json | 11 ++ apps/docs/vendor/hig/styles.css | 45 +++++ apps/docs/vendor/hig/tokens.css | 35 ++++ biome.jsonc | 6 +- bun.lock | 12 +- 36 files changed, 629 insertions(+), 379 deletions(-) delete mode 100644 apps/docs/app/brand-tokens.css create mode 100644 apps/docs/design-review/hig/README.md create mode 100644 apps/docs/design-review/hig/after-clients.png create mode 100644 apps/docs/design-review/hig/after-home.png create mode 100644 apps/docs/design-review/hig/after-mobile.png create mode 100644 apps/docs/design-review/hig/after.json create mode 100644 apps/docs/design-review/hig/before-clients.png create mode 100644 apps/docs/design-review/hig/before-home.png create mode 100644 apps/docs/design-review/hig/before-mobile.png create mode 100644 apps/docs/design-review/hig/before.json create mode 100644 apps/docs/design-review/hig/live-market.json create mode 100644 apps/docs/design-review/hig/validation.txt create mode 100644 apps/docs/e2e/shell.spec.ts create mode 100644 apps/docs/playwright.config.ts delete mode 100644 apps/docs/public/fonts/SpaceGrotesk-Bold.ttf delete mode 100644 apps/docs/public/fonts/SpaceGrotesk-OFL.txt create mode 100644 apps/docs/scripts/capture-hig.mjs create mode 100644 apps/docs/vendor/hig/LICENSE create mode 100644 apps/docs/vendor/hig/README.md create mode 100644 apps/docs/vendor/hig/package.json create mode 100644 apps/docs/vendor/hig/styles.css create mode 100644 apps/docs/vendor/hig/tokens.css diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 897c334c..2e5e61bf 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -70,6 +70,14 @@ jobs: working-directory: apps/docs run: bun run build + - name: Install browser for documentation checks + working-directory: apps/docs + run: bunx playwright install --with-deps chromium + + - name: Test production documentation interactions + working-directory: apps/docs + run: bun run test:browser + - name: Check documentation links uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2 with: diff --git a/.gitignore b/.gitignore index 0ad297e8..806fd60d 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ apps/docs/tsconfig.tsbuildinfo # a funded key must never be committable. .env .env.* + +apps/docs/test-results/ +apps/docs/playwright-report/ diff --git a/apps/docs/README.md b/apps/docs/README.md index c67e8f5f..0b0b8f9d 100644 --- a/apps/docs/README.md +++ b/apps/docs/README.md @@ -8,17 +8,18 @@ from the SDK package published from `packages/hyperliquid/dist`. ## Design system -The design follows the Bloxwap monorepo's documentation site at commit `15201923b`: +The shared presentation uses HIG 0.1.0 candidate at commit +`1a776b9326c6ba03702894943b3edbfd178c4b40` via the approved plain CSS distribution. -- `app/brand-tokens.css` is a verbatim snapshot of `packages/ui/src/styles/tokens.generated.css`. -- Fumadocs colors, typography, navigation, and forced dark mode follow `workers/docs/src/app/global.css` and its layouts. +- `@bloxwap/hig-docs-css` is a private local package; `vendor/hig/README.md` records provenance, hashes and update instructions. +- HIG tokens/CSS supply colors, controls, geometry and states; `app/global.css` adapts them to Fumadocs and the market playground. +- Fumadocs owns routing, navigation, search and MDX adapters; dark mode remains forced. - The app icon and favicon in `public/logos/` preserve the original Bloxwap artwork and metadata. -- Bloxwap Sans body text and Bloxwap Mono code use the self-hosted Next.js exports from `@bloxwap/font@0.1.2`. -- Space Grotesk Bold headings retain the local asset and OFL notice in `public/fonts/`. -- Static Open Graph font instances and their license/provenance are documented in `public/fonts/README.md`. +- Headings/body use Bloxwap Sans and code uses Bloxwap Mono from self-hosted `@bloxwap/font@0.1.2` Next.js exports. +- Static Open Graph font instances retain the license/provenance documented in `public/fonts/README.md`. -Update these snapshots from the monorepo when its design changes. Keep the artwork and font notices intact. -Building this site does not require a checkout of the monorepo or a request to a font CDN. +Read the [HIG migration evidence](design-review/hig/README.md) for validation, measurements, +exceptions and rollback. No monorepo checkout, font CDN or npm publication is required. The [historical design review](design-review/README.md) preserves the original findings and screenshots from 2026-09-26. @@ -55,6 +56,9 @@ NEXT_PUBLIC_BASE_PATH=/hyperliquid bun run docs:build NEXT_PUBLIC_BASE_PATH=/hyperliquid bun run docs:preview ``` +Run `bun run --cwd apps/docs test:browser` after the production build to test the static shell +and market playground interactions. Install Chromium with `bunx --cwd apps/docs playwright install chromium`. + Open `http://localhost:4173/hyperliquid/`. The preview serves only the static files in `apps/docs/out`. The build verifies every documentation page, internal link, asset, and anchor, plus the static JSON search index and `.nojekyll`. It also checks each page's social metadata and its distinct 1200 × 630 PNG card. diff --git a/apps/docs/app/brand-tokens.css b/apps/docs/app/brand-tokens.css deleted file mode 100644 index 1e180211..00000000 --- a/apps/docs/app/brand-tokens.css +++ /dev/null @@ -1,172 +0,0 @@ -/* GENERATED by @workspace/tokens (bun run gen:css) — do not edit by hand. */ - -/* sRGB fallback brand colors */ -:root { - --bloxwap-green: #00ff3f; - --bloxwap-blue: #35b5ff; - --bloxwap-purple: #b300ff; - --bloxwap-pink: #ff479c; - --bloxwap-yellow: #fffb38; - --bloxwap-gold: #ffc83d; - --bloxwap-black: #0a0a0a; -} - -.dark { - --bloxwap-green: #00ff3f; - --bloxwap-blue: #35b5ff; - --bloxwap-purple: #b300ff; - --bloxwap-pink: #ff479c; - --bloxwap-yellow: #fffb38; - --bloxwap-gold: #ffc83d; - --bloxwap-black: #0a0a0a; -} - -/* Display P3 wide-gamut brand colors — more vibrant on supported displays */ -@supports (color: color(display-p3 1 1 1)) { - :root { - --bloxwap-green: color(display-p3 0 1 0.24); - --bloxwap-blue: color(display-p3 0.18 0.72 1); - --bloxwap-purple: color(display-p3 0.7 0 1); - --bloxwap-pink: color(display-p3 1 0.24 0.62); - --bloxwap-yellow: color(display-p3 1 0.98 0.18); - --bloxwap-gold: color(display-p3 1 0.78 0.2); - --bloxwap-black: color(display-p3 0.04 0.04 0.04); - } - - .dark { - --bloxwap-green: color(display-p3 0 1 0.24); - --bloxwap-blue: color(display-p3 0.18 0.72 1); - --bloxwap-purple: color(display-p3 0.7 0 1); - --bloxwap-pink: color(display-p3 1 0.24 0.62); - --bloxwap-yellow: color(display-p3 1 0.98 0.18); - --bloxwap-gold: color(display-p3 1 0.78 0.2); - --bloxwap-black: color(display-p3 0.04 0.04 0.04); - } -} - -@theme { - --color-bloxwap-green: var(--bloxwap-green); - --color-bloxwap-blue: var(--bloxwap-blue); - --color-bloxwap-purple: var(--bloxwap-purple); - --color-bloxwap-pink: var(--bloxwap-pink); - --color-bloxwap-yellow: var(--bloxwap-yellow); - --color-bloxwap-gold: var(--bloxwap-gold); - --color-bloxwap-black: var(--bloxwap-black); -} - -/* Semantic (shadcn/Radix) palette */ -:root { - --radius: 0.625rem; - color-scheme: dark; - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); -} - -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); -} - -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); -} - -/* Type scale — additive: ONLY the steps Tailwind's own ladder stops short of */ -@theme { - --text-3xs: 0.625rem; - --text-3xs--line-height: 0.875rem; - --text-2xs: 0.6875rem; - --text-2xs--line-height: 1rem; -} diff --git a/apps/docs/app/global.css b/apps/docs/app/global.css index 751bdd70..7d8abb8c 100644 --- a/apps/docs/app/global.css +++ b/apps/docs/app/global.css @@ -1,7 +1,8 @@ @import "tailwindcss"; @import "fumadocs-ui/css/neutral.css"; @import "fumadocs-ui/css/preset.css"; -@import "./brand-tokens.css"; +@import "@bloxwap/hig-docs-css/tokens"; +@import "@bloxwap/hig-docs-css/styles"; @source "../node_modules/fumadocs-ui/dist/**/*.js"; @@ -10,36 +11,35 @@ --font-mono: var(--font-bloxwap-mono), ui-monospace, monospace; } -/* - * Semantic layer. Components below reference only these names, never the brand primitives in - * brand-tokens.css (generated by the monorepo's token package) or the two parallel palettes it - * aliases. The site is dark-only by brand decision (see components/provider.tsx), so this layer has - * a single mode. - * - * Bloxwap green is used at full brand intensity everywhere it appears, as text, line or fill; - * softening it drifts it toward mint and off-brand. The secondary syntax hues (pink, blue) are - * desaturated for code text — mixed toward the text color rather than faded toward the surface, - * which keeps them above 4.5:1 on the code window. - */ +/* Host aliases adapt Fumadocs and the SDK demo to the pinned HIG distribution. */ :root { - --color-surface: var(--bloxwap-black); - --color-surface-raised: var(--card); - --color-text: var(--foreground); - --color-text-muted: var(--muted-foreground); - /* Quietest gray that still clears WCAG AA 4.5:1 on the surface (bloxwap.com's footer base). */ - --color-text-quiet: #878d96; - --color-line: var(--border); - /* A fill one step above whatever overlay it sits in (dialogs use --popover, the same gray as - --color-surface-raised, so raised fills vanish inside them). */ - --color-fill-subtle: color-mix(in oklab, var(--popover) 88%, var(--color-text)); - --color-accent: var(--bloxwap-green); - --color-accent-on: var(--bloxwap-black); - --color-code-keyword: color-mix(in oklab, var(--bloxwap-pink) 70%, var(--color-text)); - --color-code-string: var(--color-accent); - --color-code-type: color-mix(in oklab, var(--bloxwap-blue) 60%, var(--color-text)); + --color-surface: var(--hig-background); + --color-surface-raised: var(--hig-surface); + --color-text: var(--hig-text); + --color-text-muted: var(--hig-muted); + --color-text-quiet: var(--hig-faint); + --color-line: var(--hig-border); + --color-fill-subtle: var(--hig-nested); + --color-accent: var(--hig-action); + --color-accent-on: var(--hig-onAction); + --color-code-keyword: var(--hig-warning); + --color-code-string: var(--hig-action); + --color-code-type: var(--hig-info); + --popover: var(--hig-surface); + --popover-foreground: var(--hig-text); + --muted: var(--hig-nested); + --radius: 10px; + --radius-md: 10px; + --radius-xl: 14px; --ease-out: cubic-bezier(0.2, 0, 0, 1); --duration-interactive: 160ms; } +@theme { + --text-3xs: 0.625rem; + --text-3xs--line-height: 0.875rem; + --text-2xs: 0.75rem; + --text-2xs--line-height: 1.125rem; +} #nd-sidebar { border-color: var(--color-line); @@ -165,7 +165,7 @@ textarea:focus-visible { } .hero h1 { margin: --spacing(7) 0 --spacing(5); - font-family: var(--font-docs-display), var(--font-sans); + font-family: var(--font-sans); font-size: clamp(50px, 5.5vw, 72px); line-height: 1.08; font-weight: 700; @@ -387,7 +387,7 @@ textarea:focus-visible { text-align: center; } .section-intro h2 { - font-family: var(--font-docs-display), var(--font-sans); + font-family: var(--font-sans); font-size: var(--text-3xl); font-weight: 700; line-height: 1.2; @@ -592,7 +592,7 @@ textarea:focus-visible { align-items: center; margin: --spacing(2) 0 --spacing(2); font-size: var(--text-xl); - font-family: var(--font-docs-display), var(--font-sans); + font-family: var(--font-sans); font-weight: 700; letter-spacing: -0.02em; } @@ -613,12 +613,9 @@ textarea:focus-visible { line-height: 1.7; } /* Site footer, ported from bloxwap.com and aligned to the header column like .landing. */ -/* Full-bleed so its fill hides the page scrolling beneath it; the padding keeps the content in the - header's column. */ +/* Footer follows the content so it cannot cover the playground or keyboard targets. */ .site-footer { - position: sticky; - bottom: 0; - z-index: 10; + position: static; width: 100%; padding: --spacing(8) max(--spacing(4), calc((100% - var(--fd-layout-width, 1400px)) / 2 + --spacing(4))); background: var(--color-surface); @@ -736,7 +733,7 @@ textarea:focus-visible { max-width: 73rem; } #nd-page h1 { - font-family: var(--font-docs-display), var(--font-sans); + font-family: var(--font-sans); font-size: clamp(1.875rem, 3vw, 2.5rem); font-weight: 700; letter-spacing: -0.035em; @@ -749,14 +746,14 @@ textarea:focus-visible { } /* Trust pages (about, contact, privacy, 404): a readable article column inside the landing width. */ .trust-page h1 { - font-family: var(--font-docs-display), var(--font-sans); + font-family: var(--font-sans); font-size: clamp(1.875rem, 3vw, 2.5rem); font-weight: 700; letter-spacing: -0.035em; line-height: 1.2; } .prose h2 { - font-family: var(--font-docs-display), var(--font-sans); + font-family: var(--font-sans); font-size: var(--text-2xl); font-weight: 700; letter-spacing: -0.02em; @@ -1013,7 +1010,9 @@ textarea:focus-visible { } } @media (prefers-reduced-motion: reduce) { - .hero-copy > *, + .hero-copy > .eyebrow, + .hero-copy > h1, + .hero-copy > :not(.eyebrow, h1), .hero .code-window, .search-skeleton > span { animation: none; @@ -1032,3 +1031,31 @@ textarea:focus-visible { transform: none; } } + +/* HIG comfortable controls, using the host font loader and Fumadocs adapters. */ +.hig-button { + font-family: var(--font-sans); +} +.install-tabs > button, +.playground-options button { + min-height: var(--hig-control); +} +.code-copy, +.install-copy { + min-width: 48px; + min-height: 48px; +} +.copy-feedback { + font-size: 0.75rem; + color: var(--hig-muted); +} +.copy-feedback[data-error="true"] { + color: var(--hig-negative); +} +.hig-shell { + min-height: 100vh; +} +.search-error { + padding: var(--hig-space-lg); + color: var(--hig-negative); +} diff --git a/apps/docs/app/layout.tsx b/apps/docs/app/layout.tsx index 9169739f..1b4da4e6 100644 --- a/apps/docs/app/layout.tsx +++ b/apps/docs/app/layout.tsx @@ -1,7 +1,7 @@ import type { Metadata } from "next"; import type { ReactNode } from "react"; import { Provider } from "@/components/provider"; -import { display, mono, sans } from "@/lib/fonts"; +import { mono, sans } from "@/lib/fonts"; import { homeDescription, siteUrl, socialMetadata } from "@/lib/social"; import "./global.css"; @@ -14,7 +14,7 @@ export const metadata: Metadata = { export default function RootLayout({ children }: { children: ReactNode }) { return ( - +
{installers[active].command}
-
+ + Search unavailable. Reload to retry, or use the navigation. +
+ ) : ( +gCu?Zz3bNT<)32}$l|Og(R(Wz6##lARMFRziyz^*
zI0%>X03N8P9(w+;HByf;`rAK(L?55ChCtDcFBl>7ay4f27zW
zgU@weO~Q&pmT^S
*mD