---
paths:
  - frontend/src/components/**
  - frontend/src/app/**/page.tsx
  - frontend/src/app/**/layout.tsx
---

# UI components & data-viz conventions — GenDesign

> Часть набора `ui-*.md`. Tokens см. `ui-tokens.md`, microcopy/copy — `ui-microcopy.md`.

## Tone & audience

- **Аудитория**: финдиректор / продукт-директор девелопера №4-15 РФ (PRINZIP-tier). НЕ архитектор, НЕ ритейл.
- **Tone of voice**: DOM.РФ × CoStar × Bloomberg-density. «Государственная аналитика, которая считает за тебя». НЕ стартап-AI-маркетинг.
- **Информационная плотность > красивости.** Цифры читаются с проектора с 5 метров.

## Component conventions

### KpiCard
- Использовать `<KpiCard>` из `components/analytics/KpiCard.tsx` — НЕ городить inline.
- KPI row: `display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px;` — НЕ flex+wrap (даёт ровные ряды).
- 3-4 KPI выше fold — максимум. Больше → под аккордеон «Детали».
- `delta.positive: null` (нейтральный) — для метрик где «больше/меньше» не имеет валентности (например, средняя цена).

### Section
- Заворачивать каждый блок графика/таблицы в `<Section title="..." subtitle="...">`.
- `subtitle` — одно предложение объясняющее «откуда данные / что значит цифра», не маркетинг.
- `right` slot — для controls (filter dropdown, export button, slicer chips).

### Headline-bar (тёмная плашка-вердикт)
- Pattern: `--bg-headline` фон, `--fg-on-dark` текст, padding 14/18, radius 12.
- **Одно предложение-ответ JTBD**: «В районе X класс Y · S м² → mix А · срок B мес · выручка C ₽».
- Под основным текстом — separator + caveats / context (ИЖК ставка, POI, дата snapshot).
- Размещать выше всех KPI-карточек.

### Badge
- Использовать `<Badge variant="success|warn|danger|neutral">`. НЕ inline-span с hex.
- Если компонента нет — создать в `components/ui/Badge.tsx`, не дублировать stylesheet'ы по pages.

### Drawer (drill-down правым слайдером)
- Pattern для `/analytics/developers` детализации. НЕ навигировать на отдельную страницу при клике на строку таблицы — открывать right drawer (CoStar pattern).
- Width 480px desktop, full-screen на phone.

## Data-viz (ECharts) rules

- **Ось Y ВСЕГДА с подписью** (`yAxis.name`). Без подписи — это нарушение review.
- **Tooltip ВСЕГДА с единицей измерения**: «1 240 ₽/м²», «73%», «28 мес».
- **Цвета серий** — только из `--viz-1..5` в указанном порядке.
- **Forecast / prediction** — пунктирная линия + band ±p25/p75 (HouseCanary). Не показывать точку без интервала.
- **Никаких 3D charts**, никаких pie с >5 сегментов (заменить на bar). Treemap — OK.
- Lazy-mount тяжёлых charts через `dynamic(() => import(...), { ssr: false })` (см. `objects/[id]/page.tsx`).

## Iconography

- **Lucide React only** — `lucide-react` пакет. Размеры 16 / 20 / 24px, stroke 1.5px.
- **НЕ emoji в UI** — 🚀 ❄ 💼 📊 → `<TrendingUp/>`, `<Snowflake/>`, `<Briefcase/>`, `<BarChart3/>`.
- Trend-glyph в KPI — Unicode arrow `↑ ↓ →` или Lucide, НЕ emoji.
- Иконка-без-текста → `aria-label`.

## Карта (Leaflet) — когда и как

- **Аналитика overview без карты — фейл** (Bnmap-parity). На `/analytics` нужна секция «Карта рынка» с точками новостроек DOM.РФ, цвет по `sold%`.
- Leaflet через `dynamic(..., { ssr: false })` — НИКОГДА не импортировать в server component.
- Высота карты: 360px (drill-in), 480px (overview), full-screen toggle FAB на phone.
- Layers: OSM base + наш geojson. Не подключать платные tile-серверы без согласования.

## Above-the-fold rule

Финдиректор закрывает вкладку через 8 секунд если не видит:
1. Что это за страница (h1 + один subtitle).
2. **Один вердикт** одним предложением (headline-bar).
3. **3 главных числа** (KPI row).

Всё остальное (sliders, deep tables, comparables) — **под аккордеон** «Подробнее». По умолчанию закрыто.

## Responsive (см. issue #66)

- 3 контекста: phone `<768`, tablet `768-1280`, desktop `>1280`. НЕ Tailwind sm/md/lg напрямую.
- Phone: nav-tabs → horizontal scroll + snap, НЕ hamburger.
- Phone: KPI grid → 1 col full-width.
- Chart высоты фиксированные, `ResizeObserver` для ECharts.
- НЕ делать PWA / offline. Аудитория с десктопа.

## Accessibility (минимум, не максимум)

- Контраст AA для body (4.5:1). Hex-token подобраны под AA на белом / slate-900.
- `aria-label` для icon-only buttons.
- Focus ring видимый (НЕ `outline: none` без замены).
- Кликабельный элемент — `<button>` или `<a>`, не `<div onClick>`.

## CTA hierarchy

- **Primary** (`--accent` blue): главное действие на странице («Рассчитать», «Создать концепцию»).
- **Secondary** (`--accent-2` orange): «Export CSV», «Поделиться», «Снимок отчёта».
- **Tertiary** (text-only link с underline на hover): nav, breadcrumbs, «← Назад».
- Одна primary CTA на экран. Больше — расфокус.

## Запреты (анти-паттерны)

- ❌ Dark mode toggle (аудитория читает с проектора)
- ❌ Emoji в UI (🚀 ❄ 💼 📊 🎉) — Lucide вместо
- ❌ Tab nav в Tailwind sm/md/lg breakpoints (использовать наши 3 контекста)
- ❌ Pie chart с >5 сегментов
- ❌ 3D-чарты, изометрия, lifestyle-фото в analytics
- ❌ Live-chat widget (Intercom) — наша аудитория звонит/пишет
- ❌ Customer logos без подтверждённого права
- ❌ Анимации >200ms (это финансовый дашборд)
- ❌ Skeleton с shimmer — простой grey fade
- ❌ TestFit / Spacemaker / Figma-dribbble стиль — НЕ наш референс
- ❌ Chart без axis label / unit в tooltip
- ❌ Predictions без confidence interval (точка без диапазона выглядит «слишком уверенно»)
- ❌ Drill-down переходом на новую страницу (использовать Drawer)

## Что проверять в pre-push review (UI-PR)

1. Цвета все из токенов? (grep `#[0-9a-fA-F]{3,8}` в .tsx — должно быть пусто кроме токенов).
2. Emoji в UI? (`grep -P '[\x{1F300}-\x{1FAFF}]'` — пусто).
3. KPI label uppercase + letter-spacing?
4. Chart с axis label и tooltip unit?
5. Section title не центрирован?
6. Lazy-mount для Leaflet / тяжёлых ECharts?
7. Headline-bar присутствует на странице с JTBD-ответом?

## References

- vault `research/UX_Analytics_Developers_Report_May17.md` — полный отчёт с бенчмарком
- vault `audits/batch_03_b_series_generative` — issues #64-66 (landing, analytics search, mobile)
- `frontend/src/components/analytics/KpiCard.tsx`, `Section.tsx` — эталонные компоненты
