gendesign/.claude/rules/ui-conventions.md

8.1 KiB
Raw Blame History

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 onlylucide-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 — эталонные компоненты