diff --git a/docs/demo-fidelity.md b/docs/archive/demo-fidelity.md similarity index 91% rename from docs/demo-fidelity.md rename to docs/archive/demo-fidelity.md index 16ca583..d4f5dec 100644 --- a/docs/demo-fidelity.md +++ b/docs/archive/demo-fidelity.md @@ -1,5 +1,11 @@ # Demo fidelity: /preview/demo vs refs-html/demo.html +> ⚠️ **УТРАТИЛ АКТУАЛЬНОСТЬ — архивная копия.** Актуальный план фикса верности и +> текущий статус пунктов B/F — в `docs/plan-design-fix.md` (Этап 1). Аудит верности +> теперь автоматизирован (`pnpm audit` → `web/audit/audit-report.md`; пиксель-дифф не +> используется); темы в `refs-html` переключаются (скрипт инжектится в +> `scripts/extract-static.mjs`). Ниже — исходный текст на момент написания. + Метод: Playwright, viewport 1440×900, скриншоты обеих страниц + замер вычисленных стилей ключевых элементов + пиксель-дифф (без чтения картинки моделью). Пиксель-дифф: **24.9%** (наш скролл 1731px, реф 1579px). Зоны различий размазаны @@ -88,6 +94,9 @@ flex/grid раскладок против статичного мока); виз ## План действий (предлагаю) +> Актуальный пошаговый план фикса вынесен в `docs/plan-design-fix.md` +> (Этапы 0–1: рефакторинг + верность). Ниже — исходные наброски. + 1. Сразу поправить B1 + B2 (чёткие баги, улучшают все страницы). 2. По F1–F4 — решение за тобой (совпадать с рефом дословно ИЛИ оставить как сигнатуру нового дизайна). 3. F5–F10 — мелочи, подчистить в том же проходе, если решаем «совпадать с рефом». diff --git a/docs/plan-design-fix.md b/docs/plan-design-fix.md new file mode 100644 index 0000000..f05f868 --- /dev/null +++ b/docs/plan-design-fix.md @@ -0,0 +1,131 @@ +# План: доводка дизайна до верности (фикс по refs) + +> Статус: к выполнению. Ветка `feat/redesign`. +> Источники: `docs/archive/demo-fidelity.md` (архивная копия старого отчёта по +> верности, неактуальна), `docs/plan-redesign.md` (общая стратегия, фазы 1–4 +> выполнены до C16). Актуальный аудит верности — `pnpm refs-audit` (Playwright) → +> `web/audit/audit-report.md`. + +## Контекст + +- Новый дизайн собран параллельно под `preview/*` (см. `plan-redesign.md`), + старый сайт `(old)/` не трогаем до C17. +- `refs/` и `refs-html/` приведены к консистентному виду — текущая «правда по + пикселям». Механизм синхронизации ref→код не создаётся (см. §9 plan-redesign). +- Аудит верности автоматизирован: `pnpm refs-audit` (Playwright, 1440×900) пишет + `web/audit/audit-report.md` — light/dark токены + поэлементный дифф стилей; + пиксель-дифф не используется. Палитры токенов уже сверены с рефом (light + совпадает, dark собран). Темы в `refs-html` переключаются — скрипт инжектится + в `scripts/extract-static.mjs`. +- Исходный отчёт `demo-fidelity.md` перенесён в `docs/archive/` как утративший + актуальность; его данные актуализированы ниже (Этап 1). +- Зафиксированные решения (подтверждены автором): + - **F1 — плоский фон холста**, без blueprint-сетки (как в рефе). + - **F4 — preview-stack в одну колонку** (как в рефе). + +## Принципы + +- Никаких правок старого дизайна `(old)/` и старого `ui/`. +- Компоненты пишем в `kit/` (переименование в `ui/` — на C19 по plan-redesign). +- Коммиты атомарные (< ~500 строк), по 1–2 компонента; после каждого — + `svelte-check` + `lint` + `build` + `refs-audit` (diff% не должен расти без причины). +- Коммиты делает автор (агент не коммитит). + +## Этап 0 — Рефакторинг (SRP / дизайн-обёртки), без изменения визуала + +Гигантские страницы (`demo` ~513, `tools/[id]` ~451 строк) дробим на +компоненты единой ответственности; убираем дублирующиеся inline-стили. + +Новые обёртки в `src/lib/components/kit/`: + +- `FieldGrid` — сетка полей (заменяет `.controls` / `.controls.compact`). +- `ToggleRow` — лейбл + `Toggle` (дублировался в `demo` и `tools/[id]`). +- `PreviewStack` — контейнер превью-плиток, **одна колонка** (реализует F4 в + одном месте). +- `SectionLabel` — label + strong + actions (вместо `.pipeline-head` / + `.preview-top`). +- `FileChip` — пилюля файла. +- `PipelineFooter` — reset + auto-note. +- `WorkspaceLayout` — двухпанельная сетка (settings | preview) со sticky + + брейкпоинт 800px. + +Декомпозиция страниц: + +- `tools/[id]`: вынести `ParamControl` (диспетчер полей по `ParamDef`), + `SettingsPanel` (левая панель), `PreviewPanel` (правая панель) — + колоцированно в `routes/preview/tools/[id]/`. Страница сжимается до + состояния + глёв. +- `demo`: переписать на те же обёртки + `WorkspaceHeader` (eyebrow + h1 + lede + + file-chip). + +Побочный баг, устраняемый тут же: в `demo` поля сейчас обёрнуты в +`
` — +**двойной лейбл**, т.к. `ColorField`/`SliderField`/`SelectField`/`NumberField` +уже содержат `Field` (MonoLabel) изнутри. При рефакторе убираем внешний +`MonoLabel`, оставляем само поле. + +Критерий Этапа 0: визуал идентичен (audit diff% без регрессии), старые тесты +зелёные. + +## Этап 1 — Верность (по refs-html; статус на момент плана) + +Аудит: `pnpm refs-audit` (Playwright, 1440×900) пишет `web/audit/audit-report.md` — +light/dark токены + поэлементный дифф стилей. Пиксель-дифф не используется. +Палитры токенов уже сверены с рефом: light совпадает (`--background`, +`--panel`, `--foreground`, `--muted`, `--line`, `--blue`), dark собран (16 +токенов). Темы в `refs-html` переключаются (скрипт инжектится в +`extract-static.mjs`). + +Открытые / решённые пункты (исходник — `docs/archive/demo-fidelity.md`): + +- **B1** (открыт, P1): `button, input, select, textarea` рендерятся Arial — + добавить в reset `design2.css` `font-family: inherit`. Влияет на все страницы. +- **B2** (решён — проверить): двойного топбара нет. `preview/+layout.svelte` + рендерит ровно один `TopBar`; `demo` свой `.topbar` не рендерит. Подтвердить + аудитом/визуально при Этапе 1. +- **F1** (решено — плоский фон): наш `--background` уже `#EEF1F4` (как реф); + видимое отличие было в blueprint-сетке поверх фона. Фикс: убрать `BlueprintGrid` + из `AppShell`. +- **F2** (сделано C16): тип шага (`StepCard`) — приглушённый mono-текст, не + синий бейдж; индекс шага — синий `#1769D2`. +- **F3** (сделано C16): подпись превью-тайла (`PreviewTile`) — синяя `#1769D2`. +- **F4** (решено — одна колонка): реализуется в `PreviewStack` (Этап 0), + колонка = `1fr`. +- **F5** (открыт): вес `MonoLabel` 500 → 400 (как в рефе). +- **F6** (открыт): мета-подписи (MetaRow/MetaList, DIMENSIONS/FORMAT/SIZE) + fs 10px → 9px. +- **F7** (низкий): копирайт/стиль — у нас `+ Add tool` (реф `Add tool`); + кнопка `Download result` — сверить с рефом (синяя, ~478×42). Проверить + визуально (замеры NOT FOUND — артефакт вложенного чипа размера). +- **F8** (низкий): `h1` line-height чуть выше рефа (150px vs 115px). +- **F9** (открыт): вертикальный ритм — подровнять паддинги секций под реф + (pipeline-head и пр.). +- **F10** (открыт): внутренние отступы preview-панели (паддинг панели). + +После Этапа 1 — повторный `refs-audit`, зафиксировать остаточный diff (sub-pixel / +структурный) и обновить статус пунктов выше прямо в этом файле. + +## Этап 2 — plan-redesign.md (C17–C21), ОТЛОЖЕНО + +Выполняется **только после** того, как новый дизайн доведён до приемлемого +уровня верности (Этапы 0–1). Сами пункты — в `plan-redesign.md` §10 Шаг 5–6: + +- **C17**: `preview/*` → реальные маршруты, удалить `(old)/`, корневой + `+layout.svelte` ← `design2.css`, поправить `newCode` в `eslint.config.js` + (`src/routes/preview/**` → `src/routes/**`). +- **C18**: правки импортов/редиректов, проверка билда. +- **C19**: удалить старое `ui/` + `app.css`, `kit/` → `ui/` (или оставить), + раскрыть ESLint `recommended` на весь код. +- **C20**: брейкпоинты 1200/1100/800/480; build без предупреждений; `grep` по + старым токенам/классам пуст. +- **C21**: опц. удалить `refs/` и `refs-html/` из репо. + +## Порядок коммитов (Этап 0) + +1. `kit/`: `FieldGrid`, `ToggleRow`, `PreviewStack`, `SectionLabel`, `FileChip`, + `PipelineFooter`, `WorkspaceLayout` — по 1–2 на коммит. +2. `tools/[id]`: `ParamControl` → `SettingsPanel` + `PreviewPanel` → тонкая + страница. +3. `demo`: переписать на обёртки. + +После каждого коммита: `svelte-check` + `lint` + `build` + `refs-audit`. diff --git a/docs/plan-redesign.md b/docs/plan-redesign.md index 59ed03a..fbc339a 100644 --- a/docs/plan-redesign.md +++ b/docs/plan-redesign.md @@ -1,6 +1,8 @@ # План: переезд на новый дизайн (refs) — параллельная сборка -> Статус: план к выполнению. +> Статус: план к выполнению. Шаги 5–6 (C17–C21) **отложены** до вывода нового +> дизайна на приемлемый уровень верности — см. `docs/plan-design-fix.md` +> (Этапы 0–1: рефакторинг + верность по `demo-fidelity.md`). > > Источники: `refs/` — Next/React-референс (правда по пикселям и интерактиву), > `refs-html/` — статические HTML-снимки для быстрого просмотра в браузере. @@ -341,7 +343,11 @@ src/routes/preview/tools/[id]/+page.svelte (доказательство отсутствия регресса). Фиксы по результатам — отдельными мелкими коммитами. -### Шаг 5. Сделать новый дизайн основным +### Шаг 5. Сделать новый дизайн основным — ОТЛОЖЕНО + +> Выполняется только после Этапов 0–1 из `docs/plan-design-fix.md` (новый +> дизайн доведён до приемлемой верности). Пока не трогаем `preview/*` и +> `(old)/`. - [ ] **[C17]** Перенести `preview/*` → реальные маршруты (move), удалить `(old)/`, корневой `+layout.svelte` импортирует `design2.css` + новый shell. diff --git a/web/audit/audit-report.json b/web/audit/audit-report.json index 7d60ada..42859b6 100644 --- a/web/audit/audit-report.json +++ b/web/audit/audit-report.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-08-28T07:02:47.972Z", + "generatedAt": "2026-08-28T11:41:19.954Z", "ours": "http://127.0.0.1:5179/preview/demo", "ref": "C:\\+XBOCTuK\\+life_projects\\easy-png-tools\\refs-html\\demo.html", "tokenDiffs": { @@ -165,39 +165,9 @@ "tag": "button", "text": "RU", "deltas": { - "color": { - "ours": "rgb(255, 255, 255)", - "ref": "rgb(238, 241, 244)" - }, - "backgroundColor": { - "ours": "rgb(23, 105, 210)", - "ref": "rgb(23, 33, 43)" - }, - "padding": { - "ours": "0px 11.2px", - "ref": "6px 9px" - }, "letterSpacing": { "ours": "0.6px", "ref": "normal" - }, - "display": { - "ours": "flex", - "ref": "block" - }, - "rect": { - "ours": { - "x": 1309, - "y": 17, - "w": 36, - "h": 30 - }, - "ref": { - "x": 1323, - "y": 20, - "w": 29, - "h": 24 - } } } }, @@ -206,24 +176,16 @@ "tag": "button", "text": "EN", "deltas": { - "padding": { - "ours": "0px 11.2px", - "ref": "6px 9px" - }, "letterSpacing": { "ours": "0.6px", "ref": "normal" }, - "display": { - "ours": "flex", - "ref": "block" - }, "rect": { "ours": { - "x": 1345, - "y": 17, - "w": 37, - "h": 30 + "x": 1349, + "y": 19, + "w": 32, + "h": 25 }, "ref": { "x": 1352, @@ -239,9 +201,33 @@ "tag": "span", "text": "/", "deltas": { + "fontFamily": { + "ours": "\"IBM Plex Mono\", monospace", + "ref": "\"IBM Plex Sans\", sans-serif" + }, + "fontSize": { + "ours": "10px", + "ref": "16px" + }, "color": { "ours": "rgb(23, 105, 210)", - "ref": "rgb(109, 120, 131)" + "ref": "rgb(23, 33, 43)" + }, + "margin": { + "ours": "0px 7px", + "ref": "0px" + }, + "letterSpacing": { + "ours": "1.2px", + "ref": "normal" + }, + "lineHeight": { + "ours": "normal", + "ref": "24px" + }, + "display": { + "ours": "inline", + "ref": "block" }, "rect": { "ours": { @@ -251,10 +237,10 @@ "h": 13 }, "ref": { - "x": 165, - "y": 124, - "w": 13, - "h": 12 + "x": 1348, + "y": 20, + "w": 4, + "h": 24 } } } @@ -1380,6 +1366,7 @@ } ], "onlyOurs": [ + "/ DEMO", "+ Add tool", "AUTO", "Gradient color", @@ -1396,7 +1383,11 @@ "18px" ], "onlyRef": [ - "/ DEMO", + "/ \n WORKSPACE", + "Workspace", + "Catalog", + "Gradient", + "Background remover", "135\n °", "100%", "2\n px", @@ -1408,7 +1399,7 @@ "tokenLight": 10, "tokenDark": 16, "elements": 47, - "onlyOurs": 14, - "onlyRef": 7 + "onlyOurs": 15, + "onlyRef": 11 } } \ No newline at end of file diff --git a/web/audit/audit-report.md b/web/audit/audit-report.md index 90560d3..5c54f86 100644 --- a/web/audit/audit-report.md +++ b/web/audit/audit-report.md @@ -2,14 +2,14 @@ vs C:\+XBOCTuK\+life_projects\easy-png-tools\refs-html\demo.html -_2026-08-28T07:02:47.972Z_ +_2026-08-28T11:41:19.954Z_ ## Сводка - Токены light: **10** расх. - Токены dark: **16** расх. - Элементы (стиль/геометрия): **47** расх. -- Только у нас: 14, только в рефе: 7 +- Только у нас: 15, только в рефе: 11 ## Токены — Light @@ -49,13 +49,15 @@ _2026-08-28T07:02:47.972Z_ ## Расхождения элементов (топ 47) -### `body>div:nth-child(1)>div:nth-child(1)>header:nth-child(1)>div:nth-child(2)>div:nth-child(4)>button:nth-child(1)` — "RU" - - **color**: `rgb(255, 255, 255)` → `rgb(238, 241, 244)` - - **backgroundColor**: `rgb(23, 105, 210)` → `rgb(23, 33, 43)` - - **padding**: `0px 11.2px` → `6px 9px` - - **letterSpacing**: `0.6px` → `normal` - - **display**: `flex` → `block` - - **rect**: `1309,17 36x30` → `1323,20 29x24` +### `body>div:nth-child(1)>div:nth-child(1)>div:nth-child(2)>div:nth-child(2)>div:nth-child(1)>section:nth-child(1)>div:nth-child(1)>span:nth-child(1)` — "/" + - **fontFamily**: `"IBM Plex Mono", monospace` → `"IBM Plex Sans", sans-serif` + - **fontSize**: `10px` → `16px` + - **color**: `rgb(23, 105, 210)` → `rgb(23, 33, 43)` + - **margin**: `0px 7px` → `0px` + - **letterSpacing**: `1.2px` → `normal` + - **lineHeight**: `normal` → `24px` + - **display**: `inline` → `block` + - **rect**: `173,124 7x13` → `1348,20 4x24` ### `body>div:nth-child(1)>div:nth-child(1)>div:nth-child(2)>div:nth-child(2)>div:nth-child(1)>section:nth-child(1)>div:nth-child(4)>div:nth-child(1)>div:nth-child(2)>div:nth-child(2)>div:nth-child(1)>span:nth-child(1)` — "COLOR" - **fontWeight**: `500` → `400` @@ -72,12 +74,6 @@ _2026-08-28T07:02:47.972Z_ - **display**: `inline` → `block` - **rect**: `1090,240 36x13` → `1246,291 79x13` -### `body>div:nth-child(1)>div:nth-child(1)>header:nth-child(1)>div:nth-child(2)>div:nth-child(4)>button:nth-child(2)` — "EN" - - **padding**: `0px 11.2px` → `6px 9px` - - **letterSpacing**: `0.6px` → `normal` - - **display**: `flex` → `block` - - **rect**: `1345,17 37x30` → `1352,20 29x24` - ### `body>div:nth-child(1)>div:nth-child(1)>div:nth-child(2)>div:nth-child(2)>div:nth-child(1)>section:nth-child(1)>div:nth-child(4)>div:nth-child(1)>div:nth-child(2)>div:nth-child(2)>div:nth-child(3)>div:nth-child(2)>button:nth-child(1)` — "100" - **padding**: `0px 11.2px` → `0px` - **letterSpacing**: `0.6px` → `normal` @@ -148,9 +144,9 @@ _2026-08-28T07:02:47.972Z_ - **letterSpacing**: `0.8px` → `normal` - **rect**: `806,1185 262x13` → `808,1378 59x10` -### `body>div:nth-child(1)>div:nth-child(1)>div:nth-child(2)>div:nth-child(2)>div:nth-child(1)>section:nth-child(1)>div:nth-child(1)>span:nth-child(1)` — "/" - - **color**: `rgb(23, 105, 210)` → `rgb(109, 120, 131)` - - **rect**: `173,124 7x13` → `165,124 13x12` +### `body>div:nth-child(1)>div:nth-child(1)>header:nth-child(1)>div:nth-child(2)>div:nth-child(4)>button:nth-child(2)` — "EN" + - **letterSpacing**: `0.6px` → `normal` + - **rect**: `1349,19 32x25` → `1352,20 29x24` ### `body>div:nth-child(1)>div:nth-child(1)>div:nth-child(2)>div:nth-child(2)>div:nth-child(1)>section:nth-child(1)>div:nth-child(2)>div:nth-child(1)>h1:nth-child(1)` — "Build your image pipeline." - **lineHeight**: `normal` → `57.6px` @@ -211,6 +207,9 @@ _2026-08-28T07:02:47.972Z_ ### `body>div:nth-child(1)>div:nth-child(1)>header:nth-child(1)>div:nth-child(1)>span:nth-child(2)` — "easy-png-tools" - **rect**: `98,23 118x18` → `98,23 108x17` +### `body>div:nth-child(1)>div:nth-child(1)>header:nth-child(1)>div:nth-child(2)>div:nth-child(4)>button:nth-child(1)` — "RU" + - **letterSpacing**: `0.6px` → `normal` + ### `body>div:nth-child(1)>div:nth-child(1)>div:nth-child(2)>div:nth-child(2)>div:nth-child(1)>section:nth-child(1)>div:nth-child(2)>div:nth-child(1)>p:nth-child(2)` — "Chain simple tools together. Every chang" - **rect**: `58,321 474x51` → `58,285 482x51` @@ -255,6 +254,7 @@ _2026-08-28T07:02:47.972Z_ ## Только у нас (структурно) +- `/ DEMO` - `+ Add tool` - `AUTO` - `Gradient color` @@ -272,7 +272,12 @@ _2026-08-28T07:02:47.972Z_ ## Только в рефе (структурно) -- `/ DEMO` +- `/ + WORKSPACE` +- `Workspace` +- `Catalog` +- `Gradient` +- `Background remover` - `135 °` - `100%` diff --git a/web/package.json b/web/package.json index 840a803..7cb6aac 100644 --- a/web/package.json +++ b/web/package.json @@ -13,7 +13,7 @@ "test": "vitest run", "format": "prettier --write .", "lint": "eslint .", - "audit": "node scripts/audit.mjs" + "refs-audit": "node scripts/audit.mjs" }, "devDependencies": { "@eslint/js": "^10.0.1",