refactor: establish local frontend workspace boundaries
Conventional commits / commits (pull_request) Successful in 24s
Frontend security / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Successful in 5m18s
Frontend security / security (push) Successful in 10s
Frontend verify / verify (push) Successful in 6m45s
Conventional commits / commits (pull_request) Successful in 24s
Frontend security / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Successful in 5m18s
Frontend security / security (push) Successful in 10s
Frontend verify / verify (push) Successful in 6m45s
OpenSpec change: evolve-frontend-stack
This commit was merged in pull request #34.
This commit is contained in:
+20
-11
@@ -51,23 +51,32 @@ Cross-slice consumer использует `@/` и `index.ts` владельца,
|
||||
композиция принадлежит вышележащему owner. Existing меж-slice исключения
|
||||
не являются разрешением добавлять новые.
|
||||
|
||||
Направление зависимостей и public imports частично проверяет
|
||||
`npm run deps`; Knip проверяет использование exports, а не смысл placement.
|
||||
Направление зависимостей, public imports и запрет соседних slices в
|
||||
`pages`, `features`, `entities` проверяет `npm run deps`. Внутренние imports
|
||||
одного slice и связи shared segments этот запрет не ограничивает.
|
||||
Knip проверяет использование exports, а не смысл placement.
|
||||
|
||||
## UI foundation
|
||||
|
||||
`shared/theme/tokens.json` — переносимый source design tokens; `theme.ts`
|
||||
Private workspace `packages/tokens` экспортирует переносимый source design tokens
|
||||
как `@wealthledger/tokens/tokens.json`. Private workspace `packages/ui`
|
||||
адаптирует доверенный JSON к Mantine без runtime schema. App и Storybook читают
|
||||
public API `shared/theme`. Storybook показывает synthetic presentation states,
|
||||
`@wealthledger/ui/theme` и явно подключают `@wealthledger/ui/styles.css` после
|
||||
Mantine CSS. Потребители используют public exports пакетов напрямую. Storybook показывает synthetic presentation states,
|
||||
не использует application API. RTL/MSW проверяют поведение приложения отдельно.
|
||||
|
||||
Existing route-aware AppShell расположен в shared/ui; это legacy placement,
|
||||
а не образец нового shared primitive. При изменении foundation прочитай
|
||||
Route-aware AppShell и его navigation styles принадлежат `app/ui`;
|
||||
`ProtectedLayout` использует public API этого владельца. При изменении foundation прочитай
|
||||
[UI](conventions/ui.md#визуальная-основа) и [Storybook](conventions/storybook.md).
|
||||
|
||||
Статичные Add/Edit/Delete и публичный `IconProps` принадлежат private
|
||||
`packages/icons`; package не зависит от UI, domain или motion.
|
||||
`BankOperationIcon` и mappings остаются у entity. Card/Cards используют package
|
||||
Add/Edit/Delete; restore/category SVG остаются локальными.
|
||||
|
||||
## Примеры
|
||||
|
||||
- Общая busy-область: существующий [LoadingSkeleton](../src/shared/ui/LoadingSkeleton.tsx), а не domain widget в shared.
|
||||
- Общая busy-область: существующий [LoadingSkeleton](../packages/ui/src/LoadingSkeleton.tsx), а не domain widget в shared.
|
||||
- Account-income state views: [страница](../src/pages/account-income/ui/AccountIncomePage.tsx) и её flat `components/*.view.tsx`; новый page-local filter остаётся здесь.
|
||||
- Portfolio query: [entity public API](../src/entities/portfolio/index.ts); новая UI-сводка с бизнес-смыслом не становится shared только из-за нескольких экранов.
|
||||
|
||||
@@ -75,7 +84,7 @@ Existing route-aware AppShell расположен в shared/ui; это legacy p
|
||||
|
||||
После placement/import change: `npm run deps`, `npm run typecheck`, `npm run knip`;
|
||||
после собственного behavior — применимые tests. Финальный gate указан в AGENTS.
|
||||
Existing dependency config не запрещает все same-layer imports: их и смысл
|
||||
owner проверяет review. Не объявляй Steiger установленным; graph проверяет
|
||||
текущий dependency-cruiser. Review отдельно проверяет смысл owner: разрешённый dependency graph не доказывает
|
||||
правильный выбор слоя.
|
||||
Graph `src` и `packages` проверяет текущий dependency-cruiser; зависимости
|
||||
из packages в код приложения `src` запрещены. Generated `packages/*/dist`
|
||||
не анализируется как исходник; все package sources остаются в graph. Review отдельно проверяет смысл
|
||||
owner: разрешённый dependency graph не доказывает правильный выбор слоя.
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Storybook
|
||||
|
||||
Единый каталог включает stories приложения и `packages/*/src`; общие
|
||||
StateView/LoadingSkeleton и их stories принадлежат `packages/ui`.
|
||||
|
||||
## Когда нужна story
|
||||
|
||||
- Shared UI/theme: показывай принятые visual roles и переиспользуемое поведение.
|
||||
@@ -23,7 +26,7 @@ Stories не достигают application API, auth, VM и query providers д
|
||||
контракт: keyboard activation, доступность действия, local callback. Не повторяй
|
||||
RTL suite и не тестируй внутренности Mantine. Существующий
|
||||
[Button](../../src/shared/ui/Button.stories.tsx) показывает themed control
|
||||
без production wrapper; [LoadingSkeleton](../../src/shared/ui/LoadingSkeleton.stories.tsx)
|
||||
без production wrapper; [LoadingSkeleton](../../packages/ui/src/LoadingSkeleton.stories.tsx)
|
||||
— значимые busy states.
|
||||
|
||||
`npm run typecheck`, `npm run deps:storybook`, `npm run build:catalog` проверяют
|
||||
|
||||
+26
-4
@@ -13,7 +13,10 @@ Mantine component и общую тему. Для выпадающего выбо
|
||||
|
||||
Icons ищи у существующего owner (например,
|
||||
[BankOperationIcon](../../src/entities/bank-card/ui/BankOperationIcon.tsx));
|
||||
общая icon library сейчас не принята. Не добавляй пакет ради одного символа. Business/domain
|
||||
статичные Add/Edit/Delete доступны в `@wealthledger/icons`. Их SVG декоративны
|
||||
по умолчанию; имя action принадлежит кнопке. Standalone meaningful icon получает
|
||||
`aria-hidden={false}`, `role="img"` и доступное имя. Category/kind mappings
|
||||
и анимации остаются в entity. Не добавляй пакет ради одного символа. Business/domain
|
||||
components живут у feature/entity/page, даже при повторном использовании.
|
||||
|
||||
Wrapper нужен для проектной ответственности, а не ради нового имени
|
||||
@@ -107,10 +110,29 @@ loading/error/empty/loaded и recovery по применимости. [Storybook
|
||||
|
||||
## Визуальная основа
|
||||
|
||||
Общая тема живёт в `src/shared/theme`: `tokens.json` задаёт переносимые значения,
|
||||
`theme.ts` адаптирует их к Mantine. Используй public API темы и её semantic roles,
|
||||
без отдельной палитры в page/component. Поддерживается светлая схема.
|
||||
Private workspace `packages/tokens` владеет переносимыми значениями
|
||||
`tokens.json`; `packages/ui/src/theme.ts` читает export пакета
|
||||
`@wealthledger/tokens/tokens.json` и адаптирует его к Mantine. Используй
|
||||
`@wealthledger/ui/theme` и его semantic roles; runtime подключает
|
||||
`@wealthledger/ui/styles.css` после Mantine CSS. Providers остаются у runtime.
|
||||
Палитра page/component следует этим semantic roles. Поддерживается светлая схема.
|
||||
Цвет дополняет подпись или знак; проверяй контраст конкретной пары text/background.
|
||||
Warning не используй для мелкого текста на белом. Деньги сохраняют валюту, знак
|
||||
и различие между нулём и неизвестной суммой. Общие состояния демонстрирует
|
||||
Storybook; presentation stories используют synthetic data без application API.
|
||||
|
||||
EntryCard, StateView и LoadingSkeleton принадлежат `packages/ui`; публичный import —
|
||||
`@wealthledger/ui`. Переводы, retry и формы skeleton остаются у callers.
|
||||
Compatibility re-exports удалены; callers используют public export пакета.
|
||||
|
||||
## Modal animation
|
||||
|
||||
BankCardForm, OperationForm, DeleteOperation и CategoryManager монтируют Modal
|
||||
с `opened=true`: Mantine Transition начинает в состоянии `entered`.
|
||||
CSS `modal-appear`/`modal-backdrop-appear` в `packages/ui/src/styles.css`
|
||||
обеспечивает появление при mount (220ms, только no-preference). Mantine theme
|
||||
владеет exit transition (180ms), overlay blur и completion callback;
|
||||
`onExitTransitionEnd` позволяет дождаться закрытия перед unmount и вернуть фокус.
|
||||
Удаление CSS без изменения mount lifecycle убирает вступительную анимацию.
|
||||
TbankConnection Modal использует toggle `opened`; вывод о разделении фаз
|
||||
банковских форм на этот сценарий автоматически не распространяется.
|
||||
|
||||
Reference in New Issue
Block a user