77 lines
4.9 KiB
Markdown
77 lines
4.9 KiB
Markdown
# Окна, 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.
|
||
|
||
## Карта 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.
|
||
|
||
## Управление состоянием
|
||
|
||
Библиотека не создаёт глобальный store окон. Приложение владеет тем, какое окно открыто и какие данные в нём загружены. Библиотека владеет одинаковым поведением самого слоя.
|
||
|
||
Если приложению позже потребуется stack нескольких modeless-окон, это будет отдельный пакетный контракт, а не расширение локального z-index.
|