Establish NODE.DC design system baseline

This commit is contained in:
DCCONSTRUCTIONS
2026-07-10 02:34:36 +03:00
commit 73629d68c3
63 changed files with 6701 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
# Подключение приложений
## Текущее состояние
Первый этап не меняет существующие приложения. Репозиторий фиксирует baseline и создаёт пакетный контракт. Это позволяет продолжать текущую разработку без одномоментной переделки Engine, Ops, BIM, CMS, SEO и Launcher.
## Рекомендуемый порядок
### 1. Catalog validation
Сначала компоненты проверяются как самостоятельная система в dark/light и нескольких accent. До этого они не объявляются заменой production-кода.
### 2. Launcher/Hub pilot
Первый consumer — Launcher/Hub как основной visual reference. Подключение выполняется по одному вертикальному набору:
- tokens/theme;
- Button/IconButton;
- Dropdown/Select;
- Window/Confirmation;
- AppHeader.
Локальные реализации удаляются только после функционального и визуального сравнения.
### 3. CMS и SEO
Используют те же компоненты и механику окон. CMS подключает DOM-layer, SEO — React-layer. Цветовые различия оформляются theme overrides.
### 4. Engine
Сначала библиотека заменяет компоненты только в уже новом Environment Settings и NDC Agent Inspector. Затем остальные инспекторы переводятся на Inspector/ControlRow постепенно. Legacy UI не переносится в библиотеку и не используется как reference.
### 5. Task Manager / Ops
Подключение начинается с floating-layer и modal primitives, где уже сформулирован канон. Массовая замена Plane UI не выполняется одним изменением.
### 6. BIM Viewer
Подключает tokens/styles и `@nodedc/ui-dom`. React в BIM ради дизайн-системы не добавляется.
## Новые приложения
Шаблон приложения пока не входит в scope. До его появления новый проект должен:
- установить опубликованные NODE.DC UI packages;
- выбрать theme и accent;
- использовать AppHeader и Window/Dropdown primitives;
- проверять registry перед созданием локального control;
- хранить доменные компоненты у себя.
## Adoption matrix
| Приложение | Текущий источник | Целевой adapter | Первый набор |
| --- | --- | --- | --- |
| Launcher/Hub | React/local shared | React | header, button, dropdown, window |
| SEO | React/local overrides | React | theme, window, field, select |
| CMS | Vanilla DOM | DOM | theme, header, modal, select |
| Engine | React/mixed generations | React | new inspector and environment settings only |
| Ops | React/Plane packages | React | floating behavior and modal primitives |
| BIM Viewer | Vanilla JS | DOM | tokens, glass select, settings surfaces |
## Не делать
- не переписывать все приложения одновременно;
- не копировать `packages/ui-react/src` в consumer;
- не поддерживать отдельную тему путём fork компонента;
- не использовать legacy Engine inspector как промежуточный канон;
- не удалять production local component до проверки package replacement.
+79
View File
@@ -0,0 +1,79 @@
# Архитектура дизайн-системы
## Цель
NODE.DC состоит из самостоятельных репозиториев и разных frontend-стеков. Поэтому общий UI не может существовать как папка, которую вручную копируют из последнего приложения. Дизайн-система поставляется как версионируемые пакеты, а приложения сохраняют собственную доменную логику.
Репозиторий физически отделён от `NODEDC_PLATFORM`, но логически относится к платформенному слою. Он не является backend-сервисом и не владеет данными приложений.
## Слои
### Tokens
`@nodedc/tokens` хранит геометрию, слои, motion и переменные темы. Геометрия не зависит от выбранного цвета приложения.
### Core
`@nodedc/ui-core` хранит:
- общий CSS-контракт;
- расчёт контрастного текста на акцентной заливке;
- расчёт позиции dropdown/popover относительно viewport;
- применение темы к DOM-контейнеру.
Core не зависит от React.
### React
`@nodedc/ui-react` предоставляет компоненты для Launcher/Hub, Engine, Ops и React-модулей. Компоненты контролируемые: бизнес-состояние остаётся у приложения, а визуальное и базовое интерактивное поведение принадлежит библиотеке.
### DOM
`@nodedc/ui-dom` предоставляет контроллеры для CMS, BIM Viewer и других приложений без React. DOM-слой не создаёт вторую стилизацию: он использует те же классы и токены `@nodedc/ui-core`.
### Catalog
Каталог является исполняемой документацией. Компонент не считается зафиксированным, если его состояния нельзя увидеть и проверить в каталоге.
## Граница shared/domain
В дизайн-системе живут элементы, значение которых не зависит от предметной области:
- поверхности;
- поля и действия;
- floating layers;
- окна;
- навигационная геометрия;
- inspector/settings layout;
- состояния загрузки, пустоты и ошибки.
В приложениях остаются:
- определение агентной ноды;
- схема SEO pipeline;
- BIM tree/model tools;
- модели задач и карточки с уникальной бизнес-логикой;
- запросы к API, права, маршруты и сохранение данных.
Если элемент встречается только в одном приложении, это ещё не причина переносить его сюда. Он переносится, когда имеет независимый UI-контракт или нужен новому приложению как готовый строительный блок.
## Зависимости
Направление зависимостей одностороннее:
1. tokens;
2. core;
3. React/DOM adapters;
4. applications.
Дизайн-система никогда не импортирует исходники приложения. Исторические реализации используются только как audit/reference и фиксируются в `registry/sources.json`.
## Версионирование
- `0.x` — baseline и первоначальная проверка API на реальных приложениях;
- minor — новый компонент или обратно совместимое расширение;
- patch — исправление поведения/стиля без изменения публичного контракта;
- major — удаление/переименование экспорта или несовместимая геометрия/семантика.
Приложение должно зависеть от опубликованной версии пакета, а не от копии файлов или произвольного commit URL.
+35
View File
@@ -0,0 +1,35 @@
# Следующие компоненты
Baseline намеренно отделяет готовые exports от известного инвентаря. Элемент из этого списка нельзя считать отсутствующим и начинать с нуля в новом приложении: сначала проверяется его запись в `registry/candidates.json` и существующие reference sources.
## P1 — следующий reusable слой
- CalendarPopover — согласовать Launcher и Task Manager, включая keyboard/date range.
- ProfileMenu — отделить визуальную карточку от identity/role API приложения.
- ActionDropdown — добавить типизированные command rows поверх готового Dropdown.
- DataTable — вынести toolbar, cells, loading/empty и row actions без entity schemas Launcher/Plane.
- SideNavigation — route-aware навигация отдельно от уже готового Inspector accordion.
- AvatarStack — согласовать overflow, presence и picker mode.
## P2 — продуктовые patterns
- ServiceRailCard — зрелый Launcher pattern, пока связанный с service catalog data.
- WorkItemCard — зрелый Ops pattern, который нужно разделить на общий card shell и task-domain content.
- MediaSourceField — общий preview/picker, но storage adapter остаётся в приложении.
- Toast.
- Tooltip.
- Empty/Loading/Error states.
## Как использовать список
Если новый проект требует candidate:
1. не копировать reference implementation целиком;
2. поднять candidate до package component в этом репозитории;
3. определить независимые props/DOM contract;
4. добавить catalog examples и состояния;
5. обновить `components.json`, удалив запись из candidates;
6. выпустить minor version.
Так список сохраняет уже проделанную работу, но не превращает незавершённый локальный код в ложный канон.
+108
View File
@@ -0,0 +1,108 @@
# Канонические компоненты
Машинный список находится в `registry/components.json`. Ниже зафиксирован смысл компонентов и границы их использования.
## GlassSurface
Базовая поверхность для карточки, панели и большого окна. Варианты меняют плотность материала, но не создают отдельный дизайн.
- `default` — обычная карточка/панель;
- `strong` — dropdown, modal и поверхность над сложным фоном;
- `soft` — вложенная или вторичная область.
Material rim допустим только как часть стекла. Жёсткая цветная рамка, случайный browser outline или debug border не являются rim.
## Button и IconButton
Button используется для всех текстовых действий. IconButton — для действия без текста.
- primary/accent — главное действие текущего контекста;
- secondary — обычное действие на glass surface;
- ghost — малозаметное действие без собственной подложки;
- danger — разрушительное действие, обычно в окне подтверждения.
Icon-only action по умолчанию круглый. Квадратная кнопка с маленьким радиусом допустима только как кнопка закрытия окна или плотный инструмент, где это зафиксировано контрактом.
## Field
FieldFrame объединяет label, control, hint и description. TextField/TextAreaField реализуют стандартные текстовые поля.
Приложение не должно вручную собирать label и input, если подходит Field. Ошибка и validation state будут расширением этого контракта, а не локальным классом приложения.
## Checker
Круглый бинарный контрол из нового Engine settings/agent inspector. Он использует checkbox semantics, но не копирует квадратный системный checkbox.
## RangeControl
Pill-range с заполнением акцентным цветом, встроенной подписью и значением. Домен определяет min/max/step и формат числа.
## ColorField
Связка круглого color picker и текстового значения. Валидация конкретного формата остаётся у формы приложения.
## Dropdown
Dropdown владеет floating-layer поведением:
- рендерится в `document.body`;
- позиционируется относительно viewport;
- переворачивается вверх при недостатке места;
- ограничивает размеры viewport;
- обновляется при resize и scroll;
- закрывается по outside pointer и Escape;
- закрывает другой открытый dropdown.
Содержимое меню передаётся приложением. Selection, action menu и filter menu используют один engine.
## Select
Select добавляет к Dropdown контролируемое значение, options и необязательный поиск. Native select не используется как видимый runtime UI, но может использоваться как fallback только в специально оговорённом legacy-контуре.
## Window
Window — единая механика открытия modal и правой panel:
- приложение контролирует `open`;
- библиотека управляет portal, focus entry/trap/restore, Escape, backdrop и scroll lock;
- `center` — modal;
- `end` — inspector/settings/detail panel.
Содержание, сохранение и запросы принадлежат приложению.
## ConfirmationModal
ConfirmationModal оборачивает Window и защищает async-confirm от повторного запуска. До завершения операции закрытие можно заблокировать.
## SegmentedControl
Pill navigation для верхней панели и компактного переключения режимов. Active segment использует активную поверхность темы; это не обязательно основной accent приложения.
## AppHeader
Трёхосевая верхняя панель:
- слева фиксированная область логотипа и optional context;
- по центру workspace/navigation;
- справа actions/profile.
Компонент фиксирует положение логотипа, высоту и выравнивание, но не знает маршруты конкретного приложения.
## StatusBadge
Статус использует semantic tone: neutral, success, warning, danger или accent. Бизнес-статус приложения маппится на tone в самом приложении.
## Inspector и ControlRow
Единая accordion-панель для settings и definition controls. Источник — только новый Environment Settings и NDC Agent Inspector.
Inspector владеет:
- заголовками разделов;
- открытием/закрытием секций;
- active state;
- вертикальным ритмом;
- раскладкой label/control.
Engine продолжает владеть определениями полей, типами нод и сохранением значений.
+56
View File
@@ -0,0 +1,56 @@
# Правила развития
## Единственный источник истины
Публичный компонент, его CSS, документация, registry entry и catalog example изменяются одним pull/merge request в этом репозитории.
Приложения не должны исправлять общий компонент локальным копированием. Если срочный adapter неизбежен, он должен:
- оборачивать публичный компонент;
- не копировать его внутреннюю реализацию;
- иметь ссылку на issue/design-system change;
- быть внесён в `docs/ADOPTION.md` как временный долг.
## Добавление компонента
Компонент принимается в систему, если:
1. он независим от доменной модели;
2. его API можно описать без упоминания конкретной таблицы/ноды/проекта;
3. он использует существующую тему и layer scale;
4. определены keyboard и disabled/pending states;
5. добавлен React или DOM adapter в зависимости от потребителей;
6. есть catalog example;
7. обновлён registry.
## Изменение геометрии
Геометрия меняется централизованно. Нельзя исправлять высоту/радиус в одном приложении, если изменение относится к общему контролу.
Допустимы density variants, если они имеют устойчивое назначение (`default`, `compact`) и тестируются как часть API.
## Deprecated
Перед удалением export:
- он получает статус deprecated в registry;
- документация указывает replacement;
- минимум один minor release сохраняет совместимость;
- после миграции известных consumers export удаляется в major release.
## Проверки
Минимум для merge:
- typecheck всех пакетов;
- registry validation;
- production build каталога;
- ручная визуальная проверка dark/light и нескольких accent;
- keyboard smoke test для Dropdown, Select, Window и Inspector.
Следующий уровень зрелости — автоматические screenshot regression и interaction tests. Они добавляются до массовой миграции приложений.
## Владение
У дизайн-системы должен быть явный code owner. Product team может предлагать компоненты, но общий API и theme contract проходят отдельное review, потому что изменение распространяется на все будущие приложения.
+59
View File
@@ -0,0 +1,59 @@
# Baseline источников
Дата аудита: 10 июля 2026 года. Точные repository revisions находятся в `registry/sources.json`.
## Launcher / Hub
Основной визуальный источник:
- общая верхняя панель;
- позиция логотипа;
- segmented navigation;
- dark glass family;
- button/modal/dropdown primitives;
- общая логика admin windows.
Существовавший `dc-ui-guideline` использован как исходный инвентарь. Он больше не должен развиваться как независимая копия после подключения центрального репозитория.
## SEO и CMS
Рассматриваются как одна продуктовая семья с Launcher/Hub. Их различия должны выражаться темой и содержанием, а не отдельной реализацией окон и controls.
SEO содержит большой объём накопленных локальных overrides. Они являются материалом аудита, но не переносятся автоматически. В библиотеку попадает очищенный общий контракт.
CMS подтверждает необходимость DOM-пакета без React.
## Engine
Разрешён только строгий subset:
- Environment Settings;
- NdcGlassChecker;
- NdcGlassSelect;
- NdcGlassModal;
- новый NDC Agent Inspector;
- styles, непосредственно обслуживающие эти элементы.
Все остальные legacy inspectors и старые plates не участвуют в принятии решений. Их будущее приведение к новому дизайну должно идти через эту библиотеку.
## Task Manager / Ops
Используются только уже стандартизированные shared patterns и документы по dropdown/modal behavior. Известные legacy CustomMenu и screen-local wrappers не являются источником компонентов.
## BIM Viewer
Используется как ограничение архитектуры: общий UI должен работать без React. В baseline включены общие требования к toolbar, settings menu и glass select, но не BIM-domain controls.
## Почему код не копируется целиком
Исторические реализации содержат:
- зависимости от доменных типов;
- локальные классы;
- дублированные токены;
- наслоившиеся overrides;
- разные z-index;
- различную степень accessibility.
Поэтому библиотека фиксирует очищенный API и поведение, сохраняя происхождение решения в реестре.
+56
View File
@@ -0,0 +1,56 @@
# Темы и цвет приложения
## Основное правило
NODE.DC-приложения отличаются цветовой схемой, а не набором заново нарисованных компонентов. Тема задаёт значения CSS custom properties. Компоненты сохраняют геометрию, состояния и поведение.
## Что меняет тема
- canvas/background;
- основной и вторичный текст;
- accent и автоматически вычисляемый on-accent;
- плотность/цвет glass surfaces;
- field/control surfaces;
- overlay;
- shadows и material rim;
- semantic success/warning/danger tones при необходимости.
## Что тема не меняет
- высоту контролов;
- радиусы по классам компонентов;
- положение логотипа;
- механику окна и dropdown;
- DOM anatomy;
- keyboard behavior;
- расположение footer actions;
- API React/DOM компонентов.
## Presets
В baseline включены `dark` и `light`. Это не два отдельных продукта, а примеры одного контракта:
- dark соответствует текущей основной семье Launcher/Hub/CMS;
- light фиксирует возможность светлой схемы, наблюдаемой в SEO;
- конкретный продукт может поверх preset задать свой accent и surface variables.
## Accent
Accent задаётся RGB tuple. On-accent вычисляется по luminance и не должен вручную прописываться белым или чёрным в отдельном компоненте.
Semantic status не обязан совпадать с accent. Например, ошибка остаётся danger, даже если приложение использует красный брендовый accent.
## Область применения
Тема может быть установлена:
- на корневом `html/body` для всего приложения;
- на контейнере embedded-модуля;
- на catalog preview для сравнения схем.
Portal-компоненты рендерятся в `document.body`, поэтому приложение должно либо задавать тему на `document.documentElement`, либо передавать согласованные переменные на body. Локальная тема глубоко внутри React subtree не сможет автоматически охватить portal без отдельного theme portal root.
## Совместимость
Существующие `--nodedc-*` имена сохранены намеренно. Это уменьшает стоимость будущего подключения Launcher, Engine, Task Manager и BIM Viewer.
+61
View File
@@ -0,0 +1,61 @@
# Окна, dropdown и слои
## Зачем отдельный контракт
В NODE.DC повторяется одна механика: пользователь нажимает trigger, открывается окно или floating surface, взаимодействует и закрывает его. Если каждое приложение реализует outside click, Escape, portal и z-index отдельно, одинаковые окна начинают вести себя по-разному.
## Layer scale
- base: `0`;
- panel: `100`;
- header: `400`;
- overlay/window: `800`;
- dropdown/popover: `900`;
- toast: `950`.
Произвольные значения вроде `30030` допускаются только во временном legacy adapter. Новый код использует scale.
## Dropdown/popover
Обязательное поведение:
1. trigger сообщает `aria-expanded`;
2. surface переносится в body;
3. координаты рассчитываются как fixed;
4. горизонтальная позиция ограничивается viewport;
5. при недостатке места surface меняет bottom/top placement;
6. scroll/resize пересчитывают позицию;
7. outside pointer и Escape закрывают surface;
8. после Escape фокус возвращается на trigger;
9. открытие другого dropdown закрывает предыдущий.
Inline absolute dropdown внутри card/sidebar/sticky container является дефектом.
## Modal window
Обязательное поведение:
1. window рендерится в body;
2. при открытии запоминается текущий focus;
3. focus переносится на первый интерактивный элемент или dialog;
4. Tab не выходит за пределы dialog;
5. Escape закрывает окно, если операция не блокирует закрытие;
6. backdrop закрывает окно только при клике именно на backdrop;
7. body scroll блокируется;
8. после закрытия focus возвращается на предыдущий trigger.
## Side window / inspector
Side window использует ту же механику, но placement `end` и ограниченную ширину. Это канон для:
- настроек окружения;
- инспектора агентной ноды;
- будущих detail/settings panels;
- CMS/SEO side editors, если они не требуют отдельного полноэкранного workflow.
## Управление состоянием
Библиотека не создаёт глобальный store окон. Приложение владеет тем, какое окно открыто и какие данные в нём загружены. Библиотека владеет одинаковым поведением самого слоя.
Если приложению позже потребуется stack нескольких modeless-окон, это будет отдельный пакетный контракт, а не расширение локального z-index.