129 lines
8.1 KiB
Markdown
129 lines
8.1 KiB
Markdown
---
|
||
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` — эталонные компоненты
|