# UI Design Contract (ops apps) Единый контракт для **CFDM · vps-tracker · EvoBGP · EvoFirewall · auth-portal**. Surface: **ReUI Frame**. Kit: `apps/web/src/components/reui-kit/`. Иерархия: **ReUI PRO > shadcn primitives**. ## EvoFirewall: согласованное сохранение текущего интерфейса (2026-10-24) В текущем roadmap пользователь явно выбрал сохранение существующего внешнего вида. Это приоритетнее прежних рекомендаций этого документа о принудительном выравнивании всей оболочки. Не выполнять массовую замену registry-компонентов, нормализацию классов, типографики, размеров, плотности, KPI/Quick Actions или расположения header/sidebar ради соответствия историческому эталону. Текущие chrome, локальные адаптации Frame/KPI, кнопка палитры на мобильных экранах, freshness/monitor и формы сохраняются. Поведение, состояния загрузки/ошибки, подписи метрик и доступность исправляются на существующих компонентах. Новые аналитика и диагностика используют Frame, действующие Chart/DataGrid и те же theme tokens без перестройки страницы. Registry `--overwrite` и повторная установка существующих компонентов не разрешены этим этапом. Высокий контраст — явная пользовательская настройка, меняющая theme-aware токены только при `html[data-contrast='high']`. Стандартная тема сохраняется. Палитра имеет combobox/listbox/active-option связь и прокрутку выбранного результата; таблицы поддерживают Enter/Space, drag handles доступны клавиатурой. Для диагностических статусов и качества измерений используются Badge/Alert варианты, неизвестные данные не заменяются нулём или признаком успешности. F1 использует те же FormSheet/RHF/Zod/FieldError для Explain и форм Port ACL, а имеющийся Sheet-паттерн overrides сохраняет черновик и добавляет срок/причину. Выбор агентов в аналитике — установленный Base UI Combobox с именами и chips, без требования вводить UUID. Редкие формы загружаются лениво и предзагружаются по фокусу/намерению; существующее расположение основных страниц сохраняется. F2/F3 добавляют ленивые формы снимков/canary, webhook, ротации credentials и меток, сохраняя Frame/base-nova. Широкие таблицы используют `FormSheet size="lg"|"xl"`: ширина задана точными `data-[side=right]` вариантами, на мобильном — viewport, внутренний grid имеет `minmax(0,1fr)`, таблица прокручивается внутри DataGrid. Исходные registry-компоненты не переписываются. Предпросмотры не запускают изменения; ACK применения и публикация desired policy различаются. Снятие pin требует явного предупреждения о проверке и возобновлении live policy. Ключ подписи install-ссылок и webhook secrets не раскрываются при чтении. Большие списки используют серверную пагинацию `ResourcePage.serverPagination`: поиск и все фильтры применяются ко всему списку до страницы; локальная сортировка отключена, чтобы не выдавать сортировку страницы за сортировку всего набора. Между запросами сохраняются предыдущая страница и фокус поля, показывается обновление. Неполный CIDR preview помечен сокращённым, количество остаётся полным. Импорт с хотя бы одной ошибочной строкой блокируется целиком; уникальные валидные дубликаты нормализуются. Локальный ReUI skill обновлён до `68f0e6fa91`. PRO dry-run подтверждён для `settings-2` с `frame`/`base-nova`; файлы блока не установлены. Эти проверки не означают редизайн существующего интерфейса. Карта: [docs](https://reui.io/docs) · [llms.txt](https://reui.io/llms.txt) · [Get Started](https://reui.io/docs/get-started) · [Styling](https://reui.io/docs/styling) · [Registry](https://reui.io/docs/registry) · [License](https://reui.io/docs/license-setup) · [Blocks](https://reui.io/blocks) · [MCP](https://reui.io/docs/mcp) · [Agent Skills](https://reui.io/docs/agent-skills) ## Surface Project lock: **`surface: frame`**. Ops / list / dashboard / detail / settings — только **Frame**, не shadcn Card как shell. Не смешивать Card и Frame на одном ops-экране. ```ts // apps/web/src/lib/ui-surface.ts (где есть) export const UI_SURFACE = 'frame' as const ``` Settings: секции через Frame + `gap` (без hairline `Separator` под PageHeader); `SettingRow` без `FieldSeparator` по умолчанию (`separated` opt-in). Preview: [settings-3](https://reui.io/preview/base/settings-3) · [settings-16](https://reui.io/preview/base/settings-16). ## Canonical PRO references | Зона | Block | Preview | |------|-------|---------| | Shell | `app-shell-12` (+ cmdk/monitor где нужно) | https://reui.io/preview/base/app-shell-12 · https://reui.io/preview/base/app-shell-7 | | KPI | horizontal compact hybrid (EvoBGP SoT: icon left + label/Badge + value ± variant) | https://reui.io/preview/base/stats-12 | | Quick Actions | Frame tiles (sibling KPI) + Badge «Перейти» | https://reui.io/preview/base/stats-12 · https://reui.io/preview/base/card-12 | | Dashboard | `dashboard-1` | https://reui.io/preview/base/dashboard-1 | | Lists | `data-grid-filtering-2` | https://reui.io/preview/base/data-grid-filtering-2 | | Settings | `settings-16` + SettingRow | https://reui.io/preview/base/settings-16 | | Auth | `auth-13` | https://reui.io/preview/base/auth-13 | | Empty | `empty-state-14` (prefer) / `empty-state-12` | https://reui.io/preview/base/empty-state-14 · https://reui.io/preview/base/empty-state-12 | | Forms | `form-7` → Sheet/Drawer | https://reui.io/preview/base/form-7 | ## Kit API (`reui-kit/`) | Component | Role | |-----------|------| | `ResourcePage` | Frame + line tabs + Filters + DataGrid | | `KpiStatGrid` | EvoBGP hybrid KPI tiles (`items`/`cards`, `variant`, Badge) | | `QuickActionGrid` | KPI-like quick action tiles (gated by `showQuickActions`) | | `OpsDashboard` | KPI + optional `afterKpi` + charts + attention queue | | `SettingsShell` | settings nav + Outlet (**только 2+ секции**; текущий `/settings` — PageShell + Frame) | | `DetailPanel` | detail Frame sections | | `filter-utils` | apply/clear ReUI Filters | `KpiStatGrid` / `QuickActionGrid` markup — SoT **EvoBGP**; в остальных apps diff только `@scope/ui` imports. ## Dashboard layout | App | Section order | |-----|---------------| | EvoBGP / CFDM / EvoFirewall | KPI → **QuickActionGrid** → charts / rest | | vps-tracker | banner → KPI → charts → attention → **QuickActionGrid** → CSV | | auth-portal | portal-specific; Quick Actions при наличии dashboard | Gating: DB `show_quick_actions` / `showQuickActions` / `ui_show_quick_actions` (default `true`). ## Shared App Shell chrome Эталон разметки: production apps + ReUI [app-shell-12](https://reui.io/preview/base/app-shell-12). При переключении между apps меняются **только** sidebar nav labels/hrefs и `main` content. | Токен / зона | Значение | |--------------|----------| | `SIDEBAR_WIDTH` / `--sidebar-width` | `240px` | | Sidebar / hover colors | theme `--sidebar` / `--sidebar-accent` — **без** AppShell `color-mix` override | | Header | `h-12`, `sticky`, `border-b`, `px-4 md:px-6` | | Header left | `SidebarTrigger` + `Separator` + Breadcrumb | | Header right | **AppsMenu** → **SystemMonitorPopover** (тема — в NavUser) | | Sidebar | AppSwitcher → groups → icons `size-4` → **NavUser** в `SidebarFooter` | | `main` | `gap-4 md:gap-6`, `px-4 py-4 md:px-6 md:py-5` | | Search | hotkey ⌘K / Ctrl+K only (не кнопка в header) | Запрещено в chrome: `SidebarRail`, sync-row footer, Search pill в header, issues Badge в header, `ModeToggle` в header (тема только в NavUser), Provider `color-mix` для `--sidebar*`. NavUser (footer): avatar + name/email; dropdown — Настройки / Тема (segmented) / Выйти. Preview: [app-shell-1](https://reui.io/preview/base/app-shell-1). App Switcher: auth-portal `GET /api/v1/app-switcher`. Ids: `cfdm` · `vps` · `bgp` · `fw` · `dns`. Admin: portal `/admin/apps`. QuickActionGrid / KPI icons: только semantic **text** (`text-info` / `text-primary` / …) на `IconTile` `elevated` — без solid fills. ## System monitor `SystemMonitorPopover` in header after AppsMenu. Preview: https://reui.io/preview/base/app-shell-12 · https://reui.io/preview/base/app-shell-7 ## MCP workflow 1. MCP `user-reui` — `search` / `get_block` / `compose_page` / `get_component` with `surface: "frame"` 2. Cite `previewUrl` + `docsUrl` 3. CLI from `apps/web`: `pnpm dlx shadcn@latest add @reui/...` 4. Adapt into kit — do not hand-roll KPI / Quick Actions / grid / settings rows 5. `validate_usage` / `get_audit_checklist` Primitives: MCP `plugin-shadcn-shadcn` + project `@scope/ui` (`@cfdm/ui` / `@evobgp/ui` / `@evofw/ui` / `@authportal/ui`). ## License ```env # apps/web/.env.local (gitignored) REUI_LICENSE_KEY= ``` `apps/web/components.json` → `@reui` с `Authorization: Bearer ${REUI_LICENSE_KEY}`. ## Spacing - AppShell main / PageShell: `gap-4 md:gap-6`, `px-4 py-4 md:px-6 md:py-5` - No `space-y-*` / `space-x-*` — use `flex` + `gap-*` - Max 1 primary CTA per screen - Semantic tokens only — no raw `bg-emerald-*` ## Forbidden - Card as ops list/dashboard shell - Hand-rolled data tables when ReUI DataGrid / `ResourcePage` exists - Hand-rolled KPI when `KpiStatGrid` exists - Hand-rolled Quick Actions when `QuickActionGrid` exists - SectionCards / DataGridCard as design эталон - Mixing Card and Frame surfaces on one ops screen