Corp/docs/guides/frontend/06-COMPONENT-INVENTORY.md

295 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Frontend Guide: Component Inventory
Этот документ отвечает на вопрос: какие UI-примитивы и повторно используемые компоненты уже есть в коде и когда их нужно брать вместо создания нового решения.
## 1. Foundation primitives
Это первый выбор для любого нового экрана.
### `frontend/src/app/globals.css`
Назначение:
- цветовые токены
- surface hierarchy
- базовые form primitives
- action states
- feedback states
Использовать, когда:
- нужен новый экран на существующей дизайн-системе
- нужно собрать карточку, поле, кнопку или feedback-блок без изобретения новой визуальной базы
Не использовать как:
- место для локального feature-хака без повторного применения
### `frontend/src/components/AppShell.tsx`
Что даёт:
- shell background
- header
- global search
- mobile navigation drawers
- `PageHeader`
Использовать, когда:
- нужен normal page внутри основного приложения
Не использовать, когда:
- экран является отдельным auth/legal flow и у него другой layout-contract
### `frontend/src/components/ui/Modal.tsx`
Что даёт:
- единый modal shell
- focus trap
- close handling
- header/footer contract
- responsive sizing
Использовать, когда:
- нужен обычный modal dialog
- нет отдельного сценария drawer/workspace/fullscreen flow
Не использовать как:
- основание для новой параллельной modal-системы
### `frontend/src/components/shared/SearchableSelect.tsx`
Компоненты:
- `SearchableSelectSingle`
- `SearchableSelectMulti`
Использовать, когда:
- нужен поиск по списку
- нужен multi-select
- нужно chip-представление выбранных значений
- нужен compose-like address field
Не использовать native `select`, если:
- начинаются локальные доработки стрелки
- нужен поиск
- нужен выбор нескольких пользователей
## 2. Shell-level и системные компоненты
### `NotificationCenter`
Роль:
- системный блок уведомлений
Когда использовать:
- в shell или system-level surface
- не как основу для произвольных выпадающих списков
### `MobileLeftDrawer` и `MobileCalendarDrawer`
Роль:
- мобильные системные drawer-паттерны
Когда использовать:
- для app-level mobile navigation / side panels
Не использовать:
- как shortcut для каждой произвольной feature-модалки
## 3. Feature-shared компоненты
Эти компоненты полезны как референс и иногда как основа для похожих сценариев, но они уже ближе к домену.
### Calendar
Файлы:
- `CalendarModal.tsx`
- `EventModal.tsx`
- `CalendarParticipantsModal.tsx`
- `CalendarSubscriptionsModal.tsx`
- `ViewDayEventsModal.tsx`
- `ViewEventDetailsModal.tsx`
- `calendar/CalendarSidebar.tsx`
- `calendar/CalendarCard.tsx`
Использовать как референс для:
- event forms
- side panels
- selection-heavy dialog flows
С оговоркой:
- calendar UI ещё не является эталоном всей системы и содержит legacy-решения
### Documents
Файлы:
- `DocumentDetailModal.tsx`
- `DocumentUploadForm.tsx`
- `DocumentPreview.tsx`
- `DocumentMetadataEditor.tsx`
- `DocumentComments.tsx`
Использовать как референс для:
- document-heavy UI
- detail panels
- upload flows
- metadata forms
С оговоркой:
- documents содержит заметный пласт legacy-геометрии и нуждается в дальнейшем выравнивании
### Requests
Файлы:
- `requests/RequestAttachmentPreviewModal.tsx`
- `requests/RequestAvatar.tsx`
- `requests/RequestComposeModal.tsx`
- `requests/RequestDetailModal.tsx`
- `requests/RequestListControls.tsx`
- `requests/RequestListItem.tsx`
- `requests/RequestListSection.tsx`
- `requests/RequestSwipeModePanel.tsx`
- `requests/RequestUserBadge.tsx`
- `requests/SwipeApprovalMode.tsx`
- `app/requests/page.tsx`
- `hooks/useRequestsPage.ts`
- `hooks/useRequestsPageScreen.ts`
Использовать как референс для:
- compose-like form pattern
- detail modal с participant-heavy content
- page-level toolbar/filter block, который вынесен из страницы в feature component
- feature container для list shell, который собирает rows + empty state + load more
- отдельный mode-panel для alternate flow вроде swipe-review
- attachment preview modal как отдельный feature block, а не хвост page-level JSX
- локальный avatar/media wrapper вокруг `next/image`, когда feature уже использует несколько однотипных аватаров и preview
- participant badge pattern для request-like доменов
- participant-only UI decisions
- conditional action rendering по данным API
- разделения page-level orchestration и feature-level compose workspace
- screen-specific router/menu/deep-link orchestration без засорения page-level JSX
`requests/RequestUserBadge.tsx` использовать как ориентир, когда нужен person-chip паттерн:
- `avatar + name` внутри capsule
- опциональная ссылка на профиль
- compact и large варианты внутри одного feature wrapper
Не копировать компонент дословно во все модули, но сохранять приоритет этого паттерна над сырой строкой получателя или локально собранным badge.
С оговоркой:
- `requests` сейчас хороший ориентир по декомпозиции и compose/detail flow, но не должен автоматически становиться visual-template для всех dense lists
### Users / profile-like screens
Файлы:
- `users/ProfileSections.tsx`
- `users/EditUserProfileModal.tsx`
- `users/EmployeeActionModal.tsx`
- `users/EmployeeActionsTimeline.tsx`
- `hooks/useProfilePage.ts`
- `hooks/useUserDetailPage.ts`
Использовать как референс для:
- profile hero
- profile sections
- info cards
- action timeline
- page-level profile controllers, которые держат loading/derived state/API orchestration вне page JSX
### Departments
Файлы:
- `departments/DepartmentPersonChip.tsx`
- `app/departments/[id]/page.tsx`
- `hooks/useDepartmentPage.ts`
Использовать как референс для:
- detail screen, который должен уметь переключаться между `showcase` и `management` без смены route и без ощущения двух разных страниц
- page-level controller для domain actions вокруг одного объекта: overview, members и inline management actions
- entry-point с detail page в уже существующий object-chat, когда объекту нужен access к реальной message history без локального duplicate UI
- richer detail layout, где есть сильный header и один основной roster/workspace-блок, без раздувания служебных summary-panels и вторичных management-panels
- member roster с role assignment и person-chip подачей вместо сырых строк участников
- role management на уровне названий ролей и назначений участникам, встроенный в roster, без фронтового permission-editor
С оговоркой:
- `departments/[id]` должен оставаться привязанным к реальным backend-capabilities; если у отдела уже есть живой object-chat, не дублировать его локальной discussion-панелью на странице
### Messages
Файлы:
- `messages/MessageComposer.tsx`
- `messages/ChatMessageItem.tsx`
- `messages/ChatDialogHeader.tsx`
- `ScrollableMessageList.tsx`
Использовать как референс для:
- dense interactive lists
- composer area
- dialog-like chat surface
С оговоркой:
- chat решает очень специфический UX, поэтому не должен автоматически становиться шаблоном для остальных модулей
## 4. Что считать shared, а что нет
Компонент нужно считать shared, если:
- он решает повторяемую визуальную механику
- у него нет жёсткой доменной привязки
- он пригоден минимум для двух feature-зон
Компонент не нужно тащить в shared, если:
- он глубоко привязан к одному домену
- у него много domain-specific props и состояний
- он служит хорошим референсом, но плохим универсальным primitive
## 5. Быстрый выбор перед новой разработкой
Если нужен:
- page shell: `AppShell`, `PageHeader`
- modal: `Modal`
- searchable dropdown: `SearchableSelect*`
- compose address line: `SearchableSelectMulti` с compose-like layout
- comment composer / delete action: `shared/CommentControls.tsx`
- primary/secondary surface: `app-surface` / `app-surface-muted`
- feedback block: `app-selected`, `app-feedback-*`
Если после этого всё ещё хочется создать новый primitive, сначала проверить:
- нет ли уже похожего решения в `components`
- нельзя ли расширить существующий shared-компонент
- не пытаемся ли мы решить локальную проблему новым глобальным паттерном