6.6 KiB
Окна, 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
Обязательное поведение:
- trigger сообщает
aria-expanded; - surface переносится в body;
- координаты рассчитываются как fixed;
- горизонтальная позиция ограничивается viewport;
- при недостатке места surface меняет bottom/top placement;
- scroll/resize пересчитывают позицию;
- outside pointer и Escape закрывают surface;
- после Escape фокус возвращается на trigger;
- открытие другого dropdown закрывает предыдущий.
Inline absolute dropdown внутри card/sidebar/sticky container является дефектом.
Modal window
Обязательное поведение:
- window рендерится в body;
- при открытии запоминается текущий focus;
- focus переносится на первый интерактивный элемент или dialog;
- Tab не выходит за пределы dialog;
- Escape закрывает окно, если операция не блокирует закрытие;
- backdrop закрывает окно только при клике именно на backdrop;
- body scroll блокируется;
- после закрытия focus возвращается на предыдущий trigger.
Карта modal-паттернов
| Тип | Источник | Каноническая реализация |
|---|---|---|
| Form/create/save | Launcher, CMS, BIM | Window + Field/Select + footer actions |
| Destructive confirmation | Launcher, Engine, BIM | ConfirmationModal |
| Workflow access sharing | новый Engine | ShareAccessModal |
| Resource link sharing | BIM Viewer | ShareLinkModal / createShareLinkController |
| Context actions | BIM measurement/object | Window size="sm" + application-owned actions |
| Expandable detail | BIM comment workspace | Window или ApplicationPanel, domain content остаётся в BIM |
| Large data/history | BIM version history | Window size="lg", data table остаётся domain composition |
Новый тип появляется только если отличается поведением слоя или имеет устойчивую независимую anatomy. Разная таблица, форма или текст внутри Window не создают новую modal-систему.
Side window / inspector
Side window использует ту же механику, но placement end и ограниченную ширину. Это канон для:
- настроек окружения;
- инспектора агентной ноды;
- будущих detail/settings panels;
- CMS/SEO side editors, если они не требуют отдельного полноэкранного workflow.
По умолчанию это modeless-слой: он не затемняет страницу, не перехватывает клики по основной области, не закрывается по backdrop, не блокирует body scroll и не удерживает Tab внутри панели. Escape и кнопка закрытия остаются доступны. Если конкретный workflow должен быть modal, это задаётся явно, а не получается случайно из placement.
Workspace window
WorkspaceWindow отличается от modal и side inspector границей слоя: это inline modeless-окно, ограниченное конкретной рабочей сценой приложения.
Обязательное поведение:
- окно рендерится внутри bounds-контейнера без portal;
- приложение контролирует rectangle, maximized-state, visibility, active-state и z-order;
- drag доступен за header мышью, touch/pen pointer и стрелками клавиатуры;
- resize выполняется нижней правой ручкой pointer-ом или стрелками клавиатуры;
- move и resize всегда ограничены текущими размерами workspace;
ResizeObserverповторно ограничивает rectangle после изменения layout;- maximize заполняет только workspace, а restore возвращает сохранённый приложением rectangle;
- close сообщает intent приложению и не создаёт внутренний store;
- родительский bounds-контейнер использует
position: relativeиoverflow: hidden.
Workspace window используется для вспомогательных камер, инструментов и сопоставляемых представлений внутри stage. Оно не заменяет modal Window, viewport-level Inspector или ApplicationPanel.
Управление состоянием
Библиотека не создаёт глобальный store окон. Приложение владеет тем, какое окно открыто и какие данные в нём загружены. Библиотека владеет одинаковым поведением самого слоя.
Stack workspace-окон остаётся контролируемым приложением: оно передаёт active-state и zIndex, а компонент отвечает только за одинаковую геометрию и взаимодействие. Глобальный stack viewport-level modeless-окон остаётся отдельным будущим контрактом.