gendesign/.design-sync/conventions.md

3.6 KiB
Raw Blame History

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, RouteGuarduseMe; 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.

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:

:root { --font-manrope: 'Manrope'; --font-plex-mono: 'IBM Plex Mono'; }
<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.