56 lines
3.6 KiB
Markdown
56 lines
3.6 KiB
Markdown
# Trade-In UI — how to build with this design system
|
||
|
||
React components from the GenDesign **trade-in** product (real-estate trade-in valuation, RU/ЕКБ). Import everything from `tradein-mvp-frontend` (bound at `window.TradeInUI`). The cards are domain-specific and **prop-driven** — you compose them with data, you don't restyle their internals.
|
||
|
||
## Setup & wrapping (required for data components)
|
||
|
||
Most cards take their data as **props** and render standalone. But several read app state through **TanStack Query** hooks (`UserMenu`, `Topbar`, `RouteGuard` → `useMe`; `HouseAnalyticsSection`, `PlacementHistoryCard`, `StreetDealsCard` → estimate sub-queries). Those MUST be rendered inside a `QueryClientProvider` (the app ships one as `Providers`). Without it they throw "No QueryClient set"; with an empty client they render their loading/null state. Prop-only cards (`HeroSummary`, `OfferCard`, `PriceRangeBar`, `DealsCard`, `ListingsCard`, charts…) need no provider.
|
||
|
||
```tsx
|
||
import { Providers, HeroSummary, OfferCard } from "tradein-mvp-frontend";
|
||
|
||
<Providers>
|
||
<main className="page" style={{ display: "flex", flexDirection: "column", gap: 24 }}>
|
||
<HeroSummary estimate={estimate} input={input} onResubmit={fn} />
|
||
<OfferCard estimate={estimate} brandSlug={null} />
|
||
</main>
|
||
</Providers>
|
||
```
|
||
|
||
Load `styles.css` once at the root — it pulls the component CSS + design tokens.
|
||
|
||
## Styling idiom — global stylesheet + CSS custom properties
|
||
|
||
This is **not Tailwind and not CSS-in-JS**. Styling is a **global stylesheet** of semantic class names plus **CSS custom-property design tokens**. Two rules:
|
||
|
||
1. **The components carry their own classes** (`.card`, `.card-head`, `.section-kicker`, `.count-strip`, `.pricebar`, `.source-chip`, `.control`, `.pill`, `.mono`, `.top-nav`, `.meta-grid`…). Don't reach inside them; compose via props. New class names you invent will not exist in the stylesheet.
|
||
2. **For your own layout/wrapper glue, use the token vars + inline styles**, on the 4/8/12/16/24/32 spacing scale (tabular-nums for numbers). Color/shape tokens, all defined in the shipped CSS:
|
||
|
||
| Group | Tokens |
|
||
|---|---|
|
||
| Surface | `--bg-app` `--bg-card` `--bg-card-alt` `--bg-headline` |
|
||
| Text | `--fg-primary` `--fg-secondary` `--fg-tertiary` `--fg-on-dark` |
|
||
| Brand/CTA | `--accent` `--accent-hover` `--accent-soft` `--accent-2` |
|
||
| Semantic | `--success` `--warn` `--danger` (`*-soft` variants) |
|
||
| Border | `--border-soft` `--border-card` `--border-strong` |
|
||
| Shape/type | `--radius` `--radius-sm` `--radius-lg` `--shadow-md` `--font-sans` (Manrope) `--font-mono` `--container` |
|
||
|
||
**v2 (МЕРА HUD) fonts:** the `v2/*` components read `var(--font-manrope)` / `var(--font-plex-mono)` (in the app these come from `next/font`). The woff2 for both families ships in `fonts/fonts.css`; define the vars once at your design root:
|
||
|
||
```css
|
||
:root { --font-manrope: 'Manrope'; --font-plex-mono: 'IBM Plex Mono'; }
|
||
```
|
||
|
||
```tsx
|
||
<div style={{ background: "var(--bg-card)", border: "1px solid var(--border-card)",
|
||
borderRadius: "var(--radius)", padding: 16, color: "var(--fg-primary)",
|
||
fontFamily: "var(--font-sans)" }}>
|
||
<b style={{ color: "var(--accent)" }}>9 850 000 ₽</b>
|
||
</div>
|
||
```
|
||
|
||
## Where the truth is
|
||
|
||
- **Styles/tokens:** read the bound `styles.css` and its `@import` `_ds_bundle.css` — the authoritative class + token list.
|
||
- **Per component:** `<Name>.d.ts` (props) and `<Name>.prompt.md` (usage). NB: synth-built `.d.ts` props are loose (`[key: string]: unknown`); the `.prompt.md` + preview card show real prop shapes and realistic data.
|
||
- Money/area/dates are RU-formatted (`toLocaleString("ru-RU")`, `₽`, `м²`). Keep that idiom.
|