Архитектура компонентов¶
Уровень: L2 (детали) | Вверх: ../README.md
Иерархия¶
Компоненты организованы в 4-уровневую иерархию по степени абстракции:
Pages (16) — экраны приложения, маршрутизация, бизнес-логика
└── Layout (3) — каркас: AppLayout, BottomNav, PageHeader
└── Common (6) — бизнес-компоненты: ItemCard, OutfitCard, SimilarItemsRail
└── UI (17) — базовые элементы: MediaCard, FilterChip, BottomSheet, EmptyState
Зависимости строго однонаправленные: верхний слой может использовать нижний, но не наоборот.
Дерево компонентов¶
graph TD
App["App"]
App --> PRoute["ProtectedRoute"]
App --> PublicRoutes["Public Routes"]
PRoute --> AppLayout["AppLayout"]
AppLayout --> OfflineBanner["OfflineBanner"]
AppLayout --> BottomNav["BottomNav"]
AppLayout --> Pages["Pages (Outlet)"]
Pages --> HomePage
Pages --> FeedPage
Pages --> WardrobePage
Pages --> OutfitsPage
Pages --> ProfilePage
Pages --> Other["Другие страницы"]
HomePage --> ProfileAvatarButton
HomePage --> OutfitCard
FeedPage --> FilterChip
FeedPage --> OutfitCard
WardrobePage --> FilterChip
WardrobePage --> ItemCard
OutfitCard --> MediaCard
ItemCard --> MediaCard
ItemCard --> SkeletonCard
PublicRoutes --> LoginPage
PublicRoutes --> RegisterPage
LoginPage --> AuthShell
RegisterPage --> AuthShell
AuthShell --> TextField
AuthShell --> PrimaryButton
Каталог компонентов¶
UI-компоненты (базовый слой)¶
| Компонент | Назначение | Ключевые пропсы |
|---|---|---|
| MediaCard | Карточка с изображением и метаданными | title, imageUrl, meta, onClick, badge, aspectRatio, imageFit |
| FilterChip | Кнопка-фильтр с опциональной точкой | active, softActive, dotTone, dotColor, icon |
| BottomSheet | Модальное окно снизу (обёртка Drawer) | DrawerProps (placement, height) |
| EmptyState | Пустое состояние с иконкой и действием | icon, title, description, action |
| AuthShell | Каркас страниц авторизации | icon, title, description, tone, footer |
| ActionIconButton | Круглая кнопка с иконкой | icon, tone ('accent' | 'surface') |
| TextField | Поле ввода (обёртка Form.Item + Input) | name, label, rules, password, type |
| SelectField | Поле выбора (обёртка Form.Item + Select) | name, label, rules, selectProps |
| PrimaryButton | Основная кнопка | ButtonProps (Ant Design) |
| SecondaryButton | Вторичная кнопка | ButtonProps |
| DangerButton | Кнопка опасного действия | ButtonProps |
| SkeletonCard | Skeleton-лоадер карточки | imageHeight, lines, mediaLayout |
| SharedAccessRow | Строка shared-контента с действием | title, stats, imageUrl, onAction, actionIcon |
| OfflineBanner | Баннер офлайн-статуса | — (авто: useNetworkStatus) |
| OfflineUnavailable | Экран "нет подключения" | description |
| OfflineErrorBoundary | Error Boundary для offline | fallbackDescription |
| UpdateAvailableToast | Уведомление об обновлении PWA | onUpdate |
| PendingChangesBadge | Бейдж ожидающих синхронизации | — (авто: usePendingCount) |
Common-компоненты (бизнес-слой)¶
| Компонент | Назначение | Ключевые пропсы |
|---|---|---|
| ItemCard | Карточка вещи (обёртка MediaCard) | item: Item, onClick, meta, compact |
| OutfitCard | Карточка образа (обёртка MediaCard) | outfit: Outfit, onClick, compact |
| SharedOutfitCard | Карточка shared-образа | item: SharedOutfitItem, onRevoke, revoking |
| ProfileAvatarButton | Кнопка-аватар профиля | — (авто: useAuthStore) |
| SimilarItemsRail | Горизонтальная лента похожих вещей | items, isLoading, onItemClick |
| SimilarOutfitsGrid | Сетка похожих образов (2 колонки, макс. 6) | outfits, isLoading, onOutfitClick |
Layout-компоненты (каркас)¶
| Компонент | Назначение | Ключевые пропсы |
|---|---|---|
| AppLayout | Основной каркас: banner + content + nav | — (Outlet) |
| BottomNav | Нижняя навигация (5 вкладок, floating pill) | — (авто: useLocation) |
| PageHeader | Заголовок страницы с кнопкой назад | title, showBack, onBack, rightContent |
Паттерны¶
Composition over inheritance¶
Все компоненты — функциональные. Переиспользование реализовано через композицию: ItemCard оборачивает MediaCard, AuthShell оборачивает Form и TextField. Наследование не используется (единственное исключение — OfflineErrorBoundary как class component для Error Boundary API React).
Controlled vs Uncontrolled¶
Формы используют Ant Design Form с onFinish — uncontrolled по умолчанию. Фильтры (FilterChip) — controlled через active проп и onClick. Конструктор образов управляется через Zustand store.
-> Полный код UI: ui-components.md | Common: common-components.md | Layout: layout-components.md