Files
docs/development/design-system.md
T

6.5 KiB
Raw Blame History

Дизайн-система WealthLedger

Общий фундамент находится в frontend/src/shared/theme. Его public API экспортирует theme, cssVariablesResolver, colorRoles и подключает базовые CSS. App владеет MantineProvider; Storybook подключает свой изолированный provider к тому же API. Тема и значения не копируются в preview. Оба runtime используют светлую схему; dark theme не заявлена как поддерживаемая.

Тема и токены

theme.ts сохраняет фирменную синюю палитру 0–9, системный sans-serif и default radius md. Именованные шкалы fontSizes, fontWeights, lineHeights, headings, spacing, radius, shadows, breakpoints и monospace явно принимаются из DEFAULT_THEME Mantine 9.5.1. Числовой дубликат шкал не хранится. Font family заголовков совпадает с общей.

Используйте props Mantine (gap="md", p="xl", radius="md", shadow="xs") или --mantine-spacing-*, --mantine-radius-* и другие native CSS variables. Foundations читает эффективную тему, показывает фактические значения и образцы. Обновление Mantine требует повторной проверки шкал и внешнего вида приложения.

colorRoles связывает смысл и native Mantine reference; resolver создаёт --wl-color-<role>, ссылающийся на Mantine variable, без повторного hex-значения.

Role Native reference Применение
canvas gray.2 Фон приложения
surface white Paper и формы в светлой схеме
subtle gray.0 Приглушённая поверхность
text dark.7 Основной текст страницы
muted gray.6 Вторичный текст (dimmed светлой схемы)
border gray.3 Граница поверхности
primary blue filled Основное действие и активная навигация
info blue.6 Информация
positive green.6 Положительный результат с текстом/знаком
negative red.6 Ошибка или отрицательный результат с текстом/знаком
warning yellow.6 Предупреждение, не мелкий текст на белом

Базовые CSS используют canvas/text aliases. Остальные роли доступны для постепенного использования; существующие локальные Mantine references не переписаны массово. Цвет не заменяет подпись статуса. Палитра не гарантирует доступный контраст произвольных сочетаний: для текста и фона проверяйте контекст. Grape остаётся дополнительной палитрой графиков; предметные значения задаёт Product.

Особые card gradients/shadows, размеры страницы и финансовые цвета CSS остаются у своих FSD-владельцев. Это сохранение существующего UI, а не завершённый редизайн или миграция всех literals в tokens. Новую общую шкалу стоит вводить только при реальном повторном использовании, если native Mantine scale не подходит.

Общие компоненты

Public API — shared/ui. Минимальный каталог включает две существующие реализации, реально используемые приложением:

Компонент Контракт и правила
StateView Empty/error с title, text, необязательным action; error получает role alert. Кнопке нужен доступный текст; не использовать для initial loading.
LoadingSkeleton Общая status/busy-область с доступной label; caller задаёт только декоративные shapes без фокуса. Структура skeleton принадлежит section/page.

Они не импортируют API, auth, счета или позиции. Не создаются wrappers над всеми примитивами: для действий используется Mantine Button с общей темой. В каталоге показаны filled для основного действия, default для вторичного/retry и subtle для вспомогательного, а также loading и disabled. Provider не меняет defaults Button или Paper ради каталога. Loading действия не заменяет loading страницы; при refetch сохраняются данные и показывается локальное состояние.

Route-aware AppShell не входит в заявленный общий набор. Бизнес-компоненты и композиции остаются у entities/pages и показываются в Product; витрина не определяет FSD ownership. Подробности запуска, взаимодействий и coverage — UI-каталог Storybook.

Границы доказательств

Каталог использует synthetic fixtures, локальные Actions и MemoryRouter, без application API/auth/storage runtime. Dependency-cruiser проверяет FSD и транзитивную runtime-изоляцию stories. Browser проверяет виды, размеры, focus и действия. Эти примеры не доказывают API recovery и прохождение инвестиционного сценария. Продуктовый пилот остаётся отдельным change и здесь не проводился.