# 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-компонент - не пытаемся ли мы решить локальную проблему новым глобальным паттерном