Corp/docs/guides/frontend/07-DEVELOPER-WORKFLOW.md

155 lines
8.5 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: Developer Workflow
Этот документ отвечает на вопрос: как practically разрабатывать новый UI в этом проекте.
## 1. Порядок работы над новой UI-задачей
Рекомендуемый порядок:
1. определить жанр экрана: operational workspace, profile-like page, dashboard/feed или auth/legal flow
2. понять, это новый паттерн или существующий
3. найти ближайшие shared primitives
4. определить уровень поверхности и геометрии
5. собрать layout из существующих слоёв
6. вынести тяжёлые feature-блоки из page-level файла, если экран уже растёт за счёт list row / detail modal / compose workspace
7. только потом добавлять локальные override
Неправильный порядок:
1. сразу писать JSX с локальными utility-классами
2. потом пытаться “подогнать под проект”
## 2. Как делать новый экран
Перед началом нового экрана:
- определить, это обычная app-page или отдельный auth/legal flow
- определить, это рабочий модуль, profile-like page или обзорный dashboard/feed
- понять, нужен ли `AppShell`
- определить основной primary panel
- определить, сколько secondary blocks реально нужно
Практический шаблон:
1. взять `AppShell`, если это обычная страница приложения
2. использовать `PageHeader`, если нужен стандартный page intro
3. построить крупные контейнеры как `app-surface rounded-2xl`
4. вложенные секции делать через `app-surface-muted rounded-xl`
5. поля формы строить на `app-input` / `app-select`
## 3. Как делать новую карточку
Перед созданием карточки спросить:
- это primary container или secondary grouped block?
- карточка реально нужна, или это просто внутренний helper block?
- не создаём ли мы третью глубину вложенности без необходимости?
Норма:
- primary card: `app-surface rounded-2xl`
- secondary card: `app-surface-muted rounded-xl`
- маленький helper: `rounded-lg` или `rounded-xl`, но не новая “мини-основная карточка”
## 4. Как делать новую форму
Сначала определить тип формы:
- CRUD
- compose
- filters
- settings
- dialog action
После этого:
- выбрать подходящий form contract
- использовать общие primitives
- решить, какие поля главные, а какие вторичные
- если compose-форма превращается в workspace, вынести её из page-level JSX в feature component
Важно:
- не все формы должны выглядеть одинаково
- но все формы должны жить в одной визуальной системе
- page-level файл не должен оставаться местом для длинной compose-модалки, если она уже стала отдельным рабочим сценарием
То же правило для list/detail flow:
- если у страницы появились тяжёлые expandable rows, detail modal или participant-heavy blocks, это уже кандидат на feature components, а не на дальнейшее разрастание page-level JSX
- то же касается toolbar/filter block и attachment preview, если они уже стали самостоятельными зонами сценария
- router-sync, deep-link opening и dismissable menu state тоже можно выносить в feature hook, если это screen orchestration, а не данные домена
- если внутри одной зоны уже несколько leaf-компонентов, стоит ввести feature container вроде `*Section` или `*Panel`, а не возвращать всё обратно в page-level JSX
- если экран уже визуально удачный, первый шаг рефакторинга должен сохранять внешний контракт и чистить структуру под капотом, а не навязывать новый layout только ради декомпозиции
- если у toolbar/filter block пропсы начинают расползаться, можно группировать их локально, но это не должно само по себе заставлять перепридумывать успешный внешний вид блока
- если экран ощущается как “из другого проекта”, причина чаще всего не в одном radius или цвете, а в несовпадении screen genre; это нужно решать на уровне hierarchy, density и panel semantics, а не точечными utility-правками
## 5. Как делать dropdown-поле
Порядок решения:
1. если это простой одиночный выбор без поиска, можно использовать `app-select`
2. если нужен поиск, chips, multi-select или compose-поведение, брать `SearchableSelect*`
3. если хочется “чуть-чуть допилить стрелочку”, сначала проверить, не означает ли это, что нужен shared pattern, а не local fix
Красный флаг:
- локальная стилизация native `select`, чтобы он выглядел как shared dropdown, почти всегда означает неправильный выбор primitive
## 6. Как делать модалку
Если нужен обычный dialog:
- использовать `Modal`
Перед реализацией определить:
- это modal dialog, drawer или workspace?
- нужен ли sticky footer?
- нужна ли длинная scrollable content area?
Нормальный modal workflow:
1. взять `Modal`
2. определить размер
3. собрать shell на `app-surface-elevated`
4. выстроить content hierarchy
5. проверить mobile-скролл и footer actions
## 7. Когда выносить в shared
Выносить в shared, если:
- паттерн повторится минимум ещё раз
- это не доменная логика, а UI-механика
- локальный код начинает превращаться в новый mini-framework внутри страницы
Не выносить рано, если:
- решение ещё сырое
- паттерн пока узкоспецифичный
- компонент завязан на один домен и вряд ли станет общим
## 8. Когда можно делать локальный override
Локальный override допустим, если:
- нет подходящего primitive
- решение реально локально
- не ломается общий visual contract
- override не рождает новый незафиксированный паттерн
Если override начинает повторяться, это уже shared problem, а не local exception.
## 9. Что проверять до завершения работы
Перед тем как считать UI-задачу завершённой, проверить:
- поверхность и радиусы соответствуют guide
- нет лишнего custom radius
- поля используют `app-*` primitives
- dropdown affordance не локально придуман
- mobile layout выглядит естественно
- действия формы и карточки читаются по визуальному весу
- role-based фронтовые эвристики не подменяют API contract там, где источник истины должен приходить с backend