quality / commitlint (push) Skipped
quality / changes (push) Successful in 8s
quality / go (push) Skipped
quality / bird2 (push) Skipped
quality / docker-check (push) Skipped
quality / openapi (push) Successful in 22s
quality / web (push) Successful in 1m0s
CD / quality (push) Successful in 1m35s
CD / publish (push) Successful in 2m59s
Секции страниц переведены на segmented Tabs (c-tabs-9), статус грида — ToggleGroup в toolbar. Убраны календарь задач, пустые вкладки мониторинга и demo-деревья ReUI. KPI overflow как в CFDM, DetailPanel на карточке модуля, один FrameSection. Co-authored-by: Cursor <[email protected]>
146 lines
9.5 KiB
Plaintext
146 lines
9.5 KiB
Plaintext
---
|
||
description: EvoBGP WebUI — React 19, shadcn/ui (base-nova), ReUI, TanStack Router/Query
|
||
globs:
|
||
- apps/web/**
|
||
- packages/ui/**
|
||
alwaysApply: false
|
||
---
|
||
|
||
# Web UI — React + shadcn/ui + ReUI
|
||
|
||
**Источники правды:**
|
||
- **ReUI PRO first:** MCP `user-reui` ([`reui-mcp.mdc`](reui-mcp.mdc)) — pages / KPI / lists / settings / shell
|
||
- shadcn primitives: MCP `plugin-shadcn-shadcn` (secondary)
|
||
- ReUI Base UI: https://reui.io/docs/components/base/<name> · [llms.txt](https://reui.io/llms.txt)
|
||
- shadcn/ui React: https://ui.shadcn.com/docs/components
|
||
|
||
Иерархия: **ReUI PRO > shadcn**. Общие: `.cursor/rules/engineering.mdc`, `context7-stack.mdc`.
|
||
|
||
## Слои UI
|
||
|
||
| Слой | Путь | Назначение |
|
||
|------|------|------------|
|
||
| shadcn-примитивы | `packages/ui/src/components/` | output `shadcn add` (не трогать под кейс) |
|
||
| ReUI enterprise | `apps/web/src/components/reui/` | output `shadcn add @reui/*` |
|
||
| Shared обёртки | `apps/web/src/components/` | PageHeader, QueryState, ConfirmDialog, StatusBadge, LoadingButton |
|
||
| ReUI kit | `apps/web/src/components/reui-kit/` | ResourcePage, KpiStatGrid, QuickActionGrid, OpsDashboard, SettingsShell, DetailPanel, FrameSection |
|
||
| Роуты | `apps/web/src/routes/` | TanStack Router (file-based) |
|
||
|
||
**Design contract:** [`docs/ui-design-contract.md`](../../docs/ui-design-contract.md). Surface: **frame**. KPI hybrid SoT: [stats-12](https://reui.io/preview/base/stats-12). Lists: [data-grid-filtering-2](https://reui.io/preview/base/data-grid-filtering-2). Page tabs: [c-tabs-9](https://reui.io/preview/base/components/c-tabs-9). Grid status: [c-toggle-group-5](https://reui.io/preview/base/components/c-toggle-group-5). Quick Actions: `QuickActionGrid`.
|
||
|
||
Тема: `packages/ui/src/styles/globals.css`. CLI из `apps/web`: `pnpm dlx shadcn@latest add <component>`.
|
||
|
||
## Правила
|
||
|
||
**WEB-01** | MUST | Перед новым UI — сначала MCP **`user-reui`** (`search` → `get_block` / `compose_page`, `surface: "frame"`) + cite `previewUrl`/`docsUrl`. Primitives — MCP `plugin-shadcn-shadcn`. Только после — JSX.
|
||
*Rationale:* ReUI PRO выше shadcn; единый Frame surface.
|
||
*Проверка:* review; [`reui-mcp.mdc`](reui-mcp.mdc).
|
||
|
||
**WEB-02** | MUST | Отсутствующий shadcn-примитив — `pnpm dlx shadcn@latest add <component>` (из `apps/web`). ReUI — `pnpm dlx shadcn@latest add @reui/<name>`.
|
||
*Проверка:* файлы в `packages/ui/src/components/` (для shadcn) или `apps/web/src/components/reui/` (для ReUI).
|
||
|
||
**WEB-03** | NEVER | Альтернативные UI-kit'ы (Material, Vuetify, Tabler, Bootstrap утилиты).
|
||
*Проверка:* `apps/web/package.json` review.
|
||
|
||
**WEB-04** | MUST | Композиция по docs: использовать под-компоненты (`CardHeader`, `TableRow`, `TabsList`, …).
|
||
*Проверка:* сверка с shadcn/ReUI docs.
|
||
|
||
**WEB-05** | MUST | Формы — `react-hook-form` + Zod; через `FormField`/`Form` обёртки.
|
||
*Проверка:* https://ui.shadcn.com/docs/components/form
|
||
|
||
**WEB-06** | MUST | Сложные data-списки — Frame + ReUI DataGrid через `reui-kit/ResourcePage` (не Card shell, не shadcn Data Table). Surface lock: `UI_SURFACE = 'frame'` (`lib/ui-surface.ts`). Простые списки — shadcn `Table`.
|
||
*Проверка:* `@/components/reui-kit`, `@/components/reui/data-grid`, `docs/ui-design-contract.md`.
|
||
|
||
**WEB-06a** | MUST | Переключатели по роли UX:
|
||
- секции страницы (Сеть / Операции / Справочники) — native `Tabs` default list (`SegmentedTabs`, [c-tabs-9](https://reui.io/preview/base/components/c-tabs-9));
|
||
- статус грида (Все/Вкл) — `ToggleGroup` в toolbar (`StatusToggleGroup`, [c-toggle-group-5](https://reui.io/preview/base/components/c-toggle-group-5));
|
||
- настройки — вертикальный Tabs rail ([settings-3](https://reui.io/preview/base/settings-3)).
|
||
Не `variant="line"` для page/in-grid tabs.
|
||
*Проверка:* `@/components/segmented-tabs`, `@/components/status-toggle-group`.
|
||
|
||
**WEB-07** | MUST | Toast — `sonner` (`Toaster` в `main.tsx`); `toast.success/error/message` из `sonner`.
|
||
*Проверка:* https://ui.shadcn.com/docs/components/sonner
|
||
|
||
**WEB-08** | MUST | Иконки — `lucide-react` (`components.json` → `iconLibrary: lucide`).
|
||
*Проверка:* imports; нет `@tabler/icons-react`, `@lucide/svelte`.
|
||
|
||
**WEB-09** | MUST | Цвета — CSS-переменные `globals.css` и ReUI semantic токены (`variant="success"/"info"/"warning"`); не hex/rgb на страницах.
|
||
*Проверка:* grep `#[0-9a-f]{3,6}` в `apps/web/src/routes/`.
|
||
|
||
**WEB-10** | SHOULD | Кастомизация — правка `packages/ui`/`reui` (Open Code), не `!important` поверх API.
|
||
|
||
**WEB-11** | MUST | `apps/web/src/routes/**` — композиция `@evobgp/ui/components/*` + `@/components/*` + `@/components/reui/*`; не копировать целые примитивы в route.
|
||
*Проверка:* review.
|
||
|
||
**WEB-12** | NEVER | Примеры Svelte/SvelteKit, Tabler, Bootstrap — без адаптации под текущий React-стек.
|
||
*Проверка:* `pnpm --filter @evobgp/web run typecheck`.
|
||
|
||
**WEB-13** | MUST | Реактивность — React 19 (`useState`, `useEffect`, TanStack Query/Router хуки); не Svelte runes, не `export let`.
|
||
*Проверка:* `pnpm --filter @evobgp/web run typecheck`.
|
||
|
||
**WEB-14** | SHOULD | Нетривиальный UI — прочитать страницу компонента shadcn/ReUI (props, a11y).
|
||
|
||
**WEB-15** | MUST | Сомнения — MCP `user-reui` + `plugin-shadcn-shadcn` + docs + `pnpm --filter @evobgp/web run typecheck`.
|
||
|
||
**WEB-16** | MUST | Подтверждение удаления — `ConfirmDialog` из `@/components/confirm-dialog`, не `window.confirm`.
|
||
|
||
**WEB-17** | MUST | Пустые списки — `EmptyState` или через `QueryState` с `emptyTitle`.
|
||
*Проверка:* review.
|
||
|
||
**WEB-18** | SHOULD | Повторяемая комбинация core (≥2 раза) — вынести в `apps/web/src/components/`.
|
||
|
||
**WEB-19** | MUST | **После любого изменения `apps/web/**` или `packages/ui/**`** — перед завершением задачи агент **обязан**:
|
||
```powershell
|
||
pnpm --filter @evobgp/web run typecheck
|
||
pnpm --filter @evobgp/web run lint
|
||
pnpm --filter @evobgp/web run build
|
||
```
|
||
Все три команды должны exit 0. Не сдавать PR/ответ, пока все три не пройдут.
|
||
*Rationale:* CI job `web` = typecheck + lint + build.
|
||
*Проверка:* CI job `web`.
|
||
|
||
**WEB-20** | MUST | Роутинг — TanStack Router (file-based `apps/web/src/routes/`); типобезопасные `createFileRoute`, `useSearch`, `Link`. Не `react-router-dom`.
|
||
*Проверка:* `tsr generate` в `build`/`typecheck` скриптах.
|
||
|
||
**WEB-21** | MUST | Data fetching — TanStack Query (`useQuery`, `useMutation`, `queryOptions`); query-key factories в `apps/web/src/queries/`. Mutations invalidate keys, не refetch вручную.
|
||
*Проверка:* review `queries/*.ts`.
|
||
|
||
**WEB-22** | NEVER | Legacy Svelte UI удалён. Не восстанавливать `web-legacy-svelte/` и не копировать Svelte-паттерны в React-код.
|
||
*Проверка:* отсутствие каталога `web-legacy-svelte/`; `pnpm --filter @evobgp/web run typecheck`.
|
||
|
||
**WEB-23** | NEVER | **settings-7** как target ([preview](https://reui.io/preview/base/settings-7) — `surface: card`). Новые settings-экраны — [settings-3](https://reui.io/preview/base/settings-3) / [settings-16](https://reui.io/preview/base/settings-16) (`surface: frame`). Существующий `apps/web/src/components/settings/*` на DNA settings-7 **не** копировать как эталон; миграция — отдельный CHANGE.
|
||
*Проверка:* review MCP `get_block` / cite; нет новых экранов с settings-7.
|
||
|
||
---
|
||
|
||
## Documentation Sync (Web)
|
||
|
||
**DOC-SYNC-06** | MUST | UI — первично MCP + shadcn/ui docs (React) + ReUI docs (Base UI); при конфликте с блогами/Stack Overflow побеждает официальная страница.
|
||
**DOC-SYNC-07** | MUST | Перед `add` — сверить Installation/Theming с `apps/web/components.json`, `packages/ui/components.json` и `packages/ui/src/styles/globals.css`.
|
||
|
||
Tailwind v4 + base-nova: https://ui.shadcn.com/docs/migration/tailwind-v4
|
||
ReUI semantic tokens: https://reui.io/docs/styling
|
||
|
||
---
|
||
|
||
## Enforcement
|
||
|
||
**Обязательный финальный шаг агента при правках `apps/web/**` или `packages/ui/**`** (см. **WEB-19**):
|
||
|
||
```powershell
|
||
pnpm --filter @evobgp/web run typecheck
|
||
pnpm --filter @evobgp/web run lint
|
||
pnpm --filter @evobgp/web run build
|
||
```
|
||
|
||
**PR checklist `apps/web/**` / `packages/ui/**`:**
|
||
- [ ] `pnpm --filter @evobgp/web run typecheck` — exit 0
|
||
- [ ] `pnpm --filter @evobgp/web run lint` — exit 0
|
||
- [ ] `pnpm --filter @evobgp/web run build` — exit 0
|
||
- [ ] shadcn-примитивы в `packages/ui/src/components/`, ReUI в `apps/web/src/components/reui/`
|
||
- [ ] Новые примитивы через shadcn CLI (`@shadcn` или `@reui`)
|
||
- [ ] Импорты: `@evobgp/ui/components/*` для shadcn, `@/components/reui/*` для ReUI
|
||
- [ ] Ссылка на docs компонента (если новый паттерн)
|
||
|
||
**CI:** job `web` — `typecheck` + `lint` + `build`.
|