mirror of
https://github.com/luxfi/work-board.git
synced 2026-09-24 00:24:57 +00:00
Run the live 4-org Dework hub on the @luxfi/ui / @hanzo/gui (Tamagui) engine without regressing the owner-approved look/feel. - Vite+Tamagui weld (proven exchange recipe): react-native->react-native-web alias, dedupe + single-copy of @hanzo/gui/@hanzogui/core/@hanzogui/web, optimizeDeps pre-bundle, __DEV__/EXPO_OS/IS_WEB defines, commonjsOptions so the engine stays in React's chunk. guiPlugin extraction deferred (its 7.3.0 peer pins [email protected]); app renders on the runtime style-injection path. - Wrap in AppProvider (GuiProvider + TanStack Query); brand = VALUE: root theme row dark_${BRAND_KEY} + --brand sourced from @luxfi/ui LUX_BRAND (hex identical to brands.ts, zero cross-brand leak). - tokens.css remap layer maps the @luxfi/ui --color-* contract onto the Dework palette + brand (no wholesale exchange-palette import). - Text fields -> @luxfi/ui Input/Textarea (native inputs, onChangeText<->onChange bridge): CommandPalette ⌘K, Suggestions editor, TaskDetail comment, chrome Toolbar, Leaderboards search. Keystroke round-trip verified. - Fix Leaderboards mobile clip: page container was a flex item whose mx-auto disabled cross-axis stretch, so min-w-[460px] tables forced cards to 460px and bled past 390px. w-full + min-w-0 chain + overflow-hidden cards -> tables now scroll inside rounded cards, no horizontal page scroll. Build green (tsc + vite). Visual-regression: 19/21 golden views pixel-match (<=2%); 2 mobile bottom-sheet overlays (task-detail, palette) diverge ~3% (under review). Preview branch — do NOT merge to main until owner review. Co-authored-by: Hanzo Dev <[email protected]>
47 lines
2.1 KiB
JavaScript
47 lines
2.1 KiB
JavaScript
// Reusable capture: load a work-board hash route at a viewport and screenshot it,
|
|
// matching how the goldens were captured (dark, dsf 2, 1440x900 / 390x844).
|
|
// Usage: node scripts/capture.mjs <baseUrl> <outDir> [view:hash ...]
|
|
// node scripts/capture.mjs http://localhost:5188 /tmp/shots overview:#/ board:#/board
|
|
import pw from '/Users/z/work/luxfi/ui/node_modules/@playwright/test/index.js';
|
|
import { mkdirSync } from 'node:fs';
|
|
const { chromium } = pw;
|
|
|
|
const base = process.argv[2] || 'http://localhost:5188';
|
|
const outDir = process.argv[3] || '/private/tmp/claude-501/-Users-z-work-lux-private/a30ef7fe-e14c-464e-8783-67708506331d/scratchpad/shots';
|
|
const specs = process.argv.slice(4);
|
|
const DEFAULT = [
|
|
'overview:#/', 'board:#/board', 'open-tasks:#/space/engineering/tasks',
|
|
'leaderboards:#/leaderboards', 'suggestions:#/suggestions', 'space:#/space/engineering/board',
|
|
'task-detail:#/board?task=0', 'explore:#/explore',
|
|
];
|
|
const views = (specs.length ? specs : DEFAULT).map((s) => {
|
|
const i = s.indexOf(':');
|
|
return { view: s.slice(0, i), hash: s.slice(i + 1) };
|
|
});
|
|
const VIEWPORTS = [
|
|
{ name: 'desktop', width: 1440, height: 900 },
|
|
{ name: 'mobile', width: 390, height: 844 },
|
|
];
|
|
mkdirSync(outDir, { recursive: true });
|
|
|
|
const errors = [];
|
|
const browser = await chromium.launch();
|
|
for (const vp of VIEWPORTS) {
|
|
const ctx = await browser.newContext({
|
|
viewport: { width: vp.width, height: vp.height },
|
|
deviceScaleFactor: 2,
|
|
colorScheme: 'dark',
|
|
});
|
|
const page = await ctx.newPage();
|
|
page.on('pageerror', (e) => errors.push(`[${vp.name}] PAGEERROR ${e.message}`));
|
|
page.on('console', (m) => { if (m.type() === 'error') errors.push(`[${vp.name}] ${m.text()}`); });
|
|
for (const { view, hash } of views) {
|
|
await page.goto(`${base}/${hash}`, { waitUntil: 'networkidle', timeout: 60000 });
|
|
await page.waitForTimeout(700); // settle fixture render + fonts
|
|
await page.screenshot({ path: `${outDir}/${view}-${vp.name}.png` });
|
|
}
|
|
await ctx.close();
|
|
}
|
|
await browser.close();
|
|
console.log(JSON.stringify({ captured: views.map((v) => v.view), viewports: VIEWPORTS.map((v) => v.name), errors: errors.slice(0, 15) }, null, 2));
|