FloatingPanel

FloatingPanel — плавающее окно: шапка с заголовком и кнопками, под ней область произвольного контента (children). Окно двигается за шапку (draggable), меняет размер за края и углы (resizable), сворачивается до шапки (minimizable), разворачивается на весь экран (maximizable) и закрывается крестиком (closable) — каждую способность можно отключить по отдельности. Открытость всегда контролируемая — пара open / onOpenChange: onOpenChange(false) приходит при закрытии крестиком, Esc или (при overlayClose) кликом мимо окна, а open меняет хост. Режим modal кладёт под окно невидимый слой-блокиратор, отсекающий страницу. Стартовые размер и позиция — defaultSize / defaultPosition, границы ресайза — minSize / maxSize. Несколько окон наводятся друг на друга через stackIndex (z-index) и onBringToFront (сигнал поднять окно при фокусе). Окно порталится в body, монтируется лениво при открытии и размонтируется при закрытии; первое поле контентной области получает автофокус. Под контентной областью есть подвал — полоса для кнопок действия, отделённая линией и не скроллящаяся с содержимым; заполняется компонентом FloatingPanelFooter из любого места внутри children (портал), без него места не занимает. На мобильном экране (ширина до 767px) окно занимает весь экран: перетаскивание, ресайз, сворачивание и разворачивание отключены, из кнопок шапки остаётся только крестик; открываясь, окно выезжает справа, при закрытии уезжает обратно (anime.js; при prefers-reduced-motion или animated={false} — без анимации). Собрано на Ark UI FloatingPanel в каркасе Panel из ДС. В IDE поверх него построена оболочка модалок ModalWindow (связывает окно со стором модалок, центрирует и каскадирует) — прямо FloatingPanel там обычно не используют.

Анатомия

FloatingPanel
Blocker (modal)
Portal → Positioner (stackIndex) → Content (onBringToFront)
Panel.Header → DragArea (draggable)
Title (title)
Controls (minimizable | maximizable | closable)
Panel.Content → Children
Footer ← FloatingPanelFooter (portal)
ResizeTrigger ×8 (resizable)

Примеры

Модальное окно

modal кладёт под окно невидимый слой-блокиратор: страница не реагирует на клики, пока окно открыто. Само окно при этом по-прежнему двигается и меняет размер.

Отключённые способности

resizable, draggable, minimizable, maximizable, closable выключаются по отдельности. Здесь сняты ресайз и обе кнопки стадии — в шапке остаётся только крестик, окно можно лишь двигать.

Подвал

FloatingPanelFooter кладёт кнопки действия в подвал окна — полосу под контентом, прижатую к правому краю и отделённую линией. Рендерится из любого места внутри окна (например, из формы, которой принадлежит кнопка отправки), в DOM уходит в подвал; кнопка отправки вне тега формы привязывается к ней атрибутом form. cancelText добавляет слева от кнопок кнопку отмены — она закрывает окно как крестик в шапке. left кладёт содержимое к левому краю подвала (раскладка — Triplet, как у Panel.Footer). Подвал не скроллится с содержимым и прячется при сворачивании окна.

Размер и его границы

По высоте окно под контент. defaultSize задаёт ширину и потолок высоты: короче — окно по содержимому, длиннее — содержимое скроллится в заданной высоте (без defaultSize потолок — край экрана). Потянули за край — высоту дальше держит окно. minSize / maxSize — диапазон ресайза (дальше границ края не тянутся). defaultPosition ставит левый верхний угол окна.

animated

API

PropTypeDefault
open*

Открыто ли окно. Компонент контролируемый — состоянием распоряжается хост

boolean-
onOpenChange*

Запрос на смену состояния: false при закрытии крестиком, Esc или кликом мимо окна (при overlayClose). Хост меняет open в ответ

(open: boolean) => void-
title*

Заголовок окна — одна строка, обрезается с многоточием

ReactNode-
children*

Содержимое окна — произвольная вёрстка в области под шапкой

ReactNode-
modal

Блокировать взаимодействие с сайтом, пока окно открыто (невидимый слой-блокиратор под окном)

booleanfalse
overlayClose

Закрывать окно кликом вне его области. При нескольких открытых окнах закрывается только верхнее

booleantrue
draggable

Перетаскивание окна за шапку

booleantrue
resizable

Изменение размера за края и углы окна

booleantrue
defaultSize

Размер окна при открытии (px). Высота — потолок: по высоте окно под контент, а длинный контент скроллится в заданной высоте. Без пропа потолок — край экрана. Потянули за край — дальше размер держит само окно

FloatingPanelSize-
minSize

Нижняя граница размера при ресайзе (px)

FloatingPanelSize-
maxSize

Верхняя граница размера при ресайзе (px)

FloatingPanelSize-
defaultPosition

Позиция левого верхнего угла при открытии (px от края вьюпорта)

FloatingPanelPoint-
minimizable

Кнопка «свернуть» (схлопывает окно до шапки)

booleantrue
maximizable

Кнопка «развернуть на весь экран»

booleantrue
closable

Кнопка «закрыть»

booleantrue
stackIndex

Позиция окна в стеке: z-index = var(--z-modal) + stackIndex

number0
onBringToFront

Вызывается при фокусе/клике внутри окна — сигнал поднять его наверх

() => void-
animated

Анимация открытия/закрытия на мобильном (выезд справа). false — окно появляется и исчезает сразу

booleantrue