gendesign/.design-sync/AUTHORING.md

79 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Preview authoring guide (design-sync, tradein-mvp-frontend)
You author `.design-sync/previews/<Name>.tsx` for assigned components so their preview cards
render real, styled, plausible compositions. The bundle is already built; you only recompile
your own previews.
## Import contract (IMPORTANT)
- Import the component from the package name: `import { OfferCard } from 'tradein-mvp-frontend';`
(the build maps this to the shipped bundle global — do NOT import from a relative src path).
- Import realistic data from the shared fixtures: `import { FIXTURE_ESTIMATE } from './_fixtures';`
- Type-only imports (`import type {...} from '@/types/trade-in'`) are erased — fine to use for casts.
- A provider is ALREADY configured globally (the app's `Providers` = TanStack Query). You do NOT
wrap previews in QueryClientProvider yourself (a second copy breaks context identity).
## Shared fixtures available from `./_fixtures` (realistic ЕКБ 2-к secondary)
- `FIXTURE_ESTIMATE: AggregatedEstimate` — median 9.85M ₽, range 9.110.6M, confidence high,
analogs[3], actual_deals[2], cian_valuation, avito_imv, dkp_corridor, price_trend[6]. Covers any
`estimate: AggregatedEstimate` prop.
- `FIXTURE_INPUT: TradeInEstimateInput` — the quartira params (area 55.3, 2 rooms, floor 5/11, monolith, good).
- `FIXTURE_IMV: IMVBenchmarkResponse` — for IMVBenchmark.
- `FIXTURE_HOUSES: HouseInfoForEstimate[]` — for HouseInfoCard.
- `FIXTURE_PLACEMENT: PlacementHistoryItem[]` — placement history rows.
- `FIXTURE_ANALYTICS: HouseAnalyticsResponse` — kpi + price_history[4] + recent_sold[2].
- `FIXTURE_SELLTIME: SellTimeSensitivityResponse` — exposure-vs-premium buckets.
- `FIXTURE_SALES: SalesVsListingsResponse` — street deals/listings pairs.
Read `tradein-mvp/frontend/src/app/ui-preview/estimate/page.tsx` — it shows EXACT prop usage for
many components (the canonical "hero" composition). Port it.
## How to find props
Read each component's source `tradein-mvp/frontend/src/components/<group>/<Name>.tsx`. The `interface Props`
(or inline destructure) is the contract. Many take `estimate`; some take other fixtures; some take
callbacks (pass `() => {}`); some fetch via hooks by id (see "fetch-coupled" below).
## Recipe
- 1 canonical story (the docs/page.tsx usage) named `Default`. Add 13 more ONLY if they visibly
differ (sweep a real variant axis: a state, an enum, empty-vs-full). Budget 14 cells.
- Realistic content only (the ЕКБ fixtures) — never foo/test.
- Callbacks → `() => {}`. Booleans like `isLoading`/`isPending` → usually `false` for the full state.
- Keep visually-identical variants OUT (e.g. a flag that only changes a link, not the view) — one cell.
## Fetch-coupled components (PlacementHistoryCard, HouseAnalyticsSection, PhotoUpload, ListingsCard
maybe) take an `estimateId` and fetch internally. The global Provider's query cache is EMPTY, so they
render their loading/empty state. If the component accepts data via props too, prefer that. If it can
ONLY fetch and renders blank/loading, author the best you can and RECORD it in your learnings file as
"renders loading/empty — fetch-coupled" — do NOT fake data you can't pass.
## Your loop (per component)
1. Read source → write `.design-sync/previews/<Name>.tsx` (named exports, no marker line).
2. Rebuild ONLY your components:
`node .ds-sync/lib/preview-rebuild.mjs --config .design-sync/config.json --node-modules tradein-mvp/frontend/node_modules --out ./ds-bundle --components <YOUR_COMMA_LIST>`
3. Capture ONLY your components:
`node .ds-sync/package-capture.mjs --out ./ds-bundle --components <YOUR_COMMA_LIST>`
4. READ each `ds-bundle/_screenshots/review/<group>__<Name>.png`. Grade each cell on the absolute
rubric: Styled (DS tokens/font visible) · Complete (renders whole, no missing children) · Plausible.
5. Write `.design-sync/.cache/review/<Name>.grade.json`:
`{"cells":{"<CellLabel>":{"verdict":"good"|"needs-work","note":"..."}}}` (keys = exact cell labels
from the capture log). `needs-work` → fix the .tsx, rebuild, recapture, regrade until `good`.
## HARD RULES (violating corrupts other agents' work)
- Edit ONLY your assigned `previews/<Name>.tsx`, your `.cache/review/<Name>.grade.json`, and your
`.design-sync/learnings/<BATCH>.md`. NOTHING else. Never touch config.json / NOTES.md / other previews.
- NEVER run `package-build.mjs` or `package-validate.mjs`. NEVER run `package-capture.mjs` without
`--components` (a full run prunes other agents' state). Only the two scoped commands above.
- If the SAME root cause hits 2+ of your components, or ANY config-level issue (a needed provider chain,
a missing token/css, a needed `cardMode`/`viewport` override, an import that won't resolve) → STOP on
those, record in your learnings file `.design-sync/learnings/<BATCH>.md`, and report to the orchestrator.
Config/NOTES changes are orchestrator-only.
## Wide/overlay components
Cards with `className="card"` are full-width and fine. If a card visibly overflows its grid cell or an
overlay (dialog/map modal) collapses, that needs a `cfg.overrides.<Name>.cardMode` change — you CANNOT
do that (config is orchestrator-only). Record it in learnings and move on.
## Calibration learnings from the solo set (HeroSummary, OfferCard, PriceRangeBar)
- The contract works: `import { X } from 'tradein-mvp-frontend'` + `./_fixtures` + global Provider.
- Cards render fully styled with the trade-in tokens/Manrope font.
- Components with analog photos show a grey placeholder (fixture photo_url=null, offline) — that is the
component's REAL no-photo state, grade it good (do not try to add external image URLs).
- Drop variants that don't change the view (brandSlug, isResubmitting rendered identical → single cell).