11 KiB
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
Компоненты:
SearchableSelectSingleSearchableSelectMulti
Использовать, когда:
- нужен поиск по списку
- нужен 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.tsxEventModal.tsxCalendarParticipantsModal.tsxCalendarSubscriptionsModal.tsxViewDayEventsModal.tsxViewEventDetailsModal.tsxcalendar/CalendarSidebar.tsxcalendar/CalendarCard.tsx
Использовать как референс для:
- event forms
- side panels
- selection-heavy dialog flows
С оговоркой:
- calendar UI ещё не является эталоном всей системы и содержит legacy-решения
Documents
Файлы:
DocumentDetailModal.tsxDocumentUploadForm.tsxDocumentPreview.tsxDocumentMetadataEditor.tsxDocumentComments.tsx
Использовать как референс для:
- document-heavy UI
- detail panels
- upload flows
- metadata forms
С оговоркой:
- documents содержит заметный пласт legacy-геометрии и нуждается в дальнейшем выравнивании
Requests
Файлы:
requests/RequestAttachmentPreviewModal.tsxrequests/RequestAvatar.tsxrequests/RequestComposeModal.tsxrequests/RequestDetailModal.tsxrequests/RequestListControls.tsxrequests/RequestListItem.tsxrequests/RequestListSection.tsxrequests/RequestSwipeModePanel.tsxrequests/RequestUserBadge.tsxrequests/SwipeApprovalMode.tsxapp/requests/page.tsxhooks/useRequestsPage.tshooks/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.tsxusers/EditUserProfileModal.tsxusers/EmployeeActionModal.tsxusers/EmployeeActionsTimeline.tsxhooks/useProfilePage.tshooks/useUserDetailPage.ts
Использовать как референс для:
- profile hero
- profile sections
- info cards
- action timeline
- page-level profile controllers, которые держат loading/derived state/API orchestration вне page JSX
Departments
Файлы:
departments/DepartmentPersonChip.tsxapp/departments/[id]/page.tsxhooks/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.tsxmessages/ChatMessageItem.tsxmessages/ChatDialogHeader.tsxScrollableMessageList.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-компонент
- не пытаемся ли мы решить локальную проблему новым глобальным паттерном