Перейти к содержимому
v2.5.0
English
Русский
Документация

Sheet

Sheet (шторка) — составной компонент для оверлеев в виде панели, обычно прикреплённых к низу экрана или рассчитанных в первую очередь на мобильные устройства, с частями для триггера, содержимого и ручки.

Пропсы корня

ПропТипПо умолчанию
snapPointsArray<${number}px | number>—
Высоты, на которых останавливается шторка, как детенты нативной шторки: доля высоты области просмотра (0.5) или высота в пикселях ('200px'). Шторка подстраивается под содержимое, если у SheetContent нет CSS-высоты, а точка привязки выше её высоты останавливается на её верхнем краю. Без точек привязки шторка открывается полностью.
activeSnapPointnumber—
Текущая активная точка привязки (контролируемо) — индекс в snapPoints.
defaultSnapPointnumber—
Точка привязки, в которой открывается шторка в неконтролируемом режиме, — индекс в snapPoints. По умолчанию — самая нижняя.
onChangeActiveSnapPoint(activeSnapPoint: number) => void—
Колбэк, вызываемый, когда пользователь перемещает шторку к другой точке привязки.
steppedSnapPointsbooleanfalse
Перемещает не больше чем на одну точку привязки за одно перетаскивание, как бы далеко или быстро оно ни было.
defaultOpenbooleanfalse
Определяет, открыта ли шторка изначально (неконтролируемо).
openboolean—
Управляет тем, открыта ли шторка сейчас (контролируемо).
onChangeOpen(value: boolean) => void—
Колбэк, вызываемый при изменении состояния открытия.
childrenReactNode | ReactNode[]—
Содержимое, рендерящееся внутри шторки. Может включать любые элементы раскладки или формы.

Дочерние части

SheetTrigger

Действие открытия шторки. Выставляет aria-haspopup="dialog" и aria-expanded.

ПропТипПо умолчанию
asChildboolean—
Если true, рендерит триггер как собственный элемент через Slot. Позволяет гибко компоновать с собственными элементами вроде <a>, <div> или кнопок-иконок.
refRef<HTMLButtonElement>—
Ref, передаваемый на нижележащий элемент триггера. Полезен для управления фокусом или внешнего управления.

Также принимает все атрибуты <button>.

SheetContent

Нативный модальный <dialog>.

ПропТипПо умолчанию
refRef<HTMLDialogElement>—
Ref, передаваемый на нативный элемент <dialog>. Полезен для управления фокусом, измерений или хуков анимации.
shadowedboolean—
Добавляет панели шторки тень. Создаёт глубину и отделяет её от фона.
blurredbooleanfalse
Размывает страницу за шторкой.
overlaybooleantrue
Затемняет страницу за шторкой. При false страница остаётся видимой, а шторка — модальной.
closedByModalDialogClosedBy'any'
Какие действия пользователя закрывают шторку, как нативный атрибут closedby: any — клик по подложке, свайп вниз или Escape, closerequest — только Escape, none — ничего из этого.

Также принимает все атрибуты <dialog>.

  • Сам не выставляет id и aria-labelledby: назовите его через aria-labelledby, указывающий на id вашего заголовка, или через aria-label. onCancel и onClose выполняются после внутренних обработчиков. ref указывает на элемент <dialog>.
  • blurred (по умолчанию false) размывает страницу за шторкой.
  • overlay (по умолчанию true) затемняет страницу; false делает ::backdrop прозрачным, при этом шторка остаётся модальной.
  • shadowed добавляет тень поверхности.
  • Имеет горизонтальные отступы (clamp(var(--spacing-12), 3vw, var(--spacing-16))) и нижний отступ (var(--spacing-12) плюс отступ безопасной зоны). Прокручиваемая область внутри — элемент с overflow: auto.
  • Закрывается при отправке <form method="dialog"> внутри неё, в том числе с closedBy='none'. Закрытие идёт через onChangeOpen(false), а value кнопки отправки становится returnValue диалога.
  • closedBy задаёт, какие действия пользователя закрывают шторку, как нативный атрибут closedby: 'any' (клик по подложке, свайп вниз или Escape, по умолчанию), 'closerequest' (только Escape) или 'none'. Используйте closedBy='none' для шторки, которую нельзя закрыть.
  • Перетаскивание следует за пальцем, сопротивляется за верхней и нижней точками привязки и останавливается на той точке, куда донесла бы инерция, поэтому резкий взмах может проскочить точку привязки. С closedBy='any' перетаскивание вниз ниже самой нижней точки привязки закрывает шторку.
  • Остаётся смонтированной, только пока открыта и пока идёт переход закрытия.

SheetHandle

Ручка в верхней части шторки. Это всегда <button> без собственного имени, поэтому передайте aria-label, например Resize sheet. Если у шторки несколько точек привязки, ручка перемещает её на следующую точку, а с верхней — обратно на самую нижнюю. Иначе она disabled и aria-hidden.

ПропТипПо умолчанию
refRef<HTMLButtonElement>—
Ref, передаваемый на <button> ручки.

Также принимает все атрибуты <button>.

SheetClose

Закрывает шторку по клику. У неё нет стилей, иконки и aria-label по умолчанию: отрендерите внутри свою кнопку через asChild и подпишите её.

ПропТипПо умолчанию
asChildboolean—
Если true, рендерит действие закрытия как дочерний элемент через Slot, поэтому любая ваша кнопка закрывает шторку.
refRef<HTMLButtonElement>—
Ref, передаваемый на нижележащую кнопку.

Также принимает все атрибуты <button>.

  • Закрытие идёт через onChangeOpen(false), поэтому проигрывается переход закрытия, а контролирующий родитель может оставить шторку открытой.
  • Используйте её для отдельной кнопки закрытия, например крестика в шапке. Для кнопок, которые отвечают на шторку (Cancel, Confirm, returnValue), используйте <form method="dialog">. Без asChild она рендерит type="button", поэтому работает и внутри вашей собственной формы, не отправляя её; с asChild задайте своей кнопке type="button".
minimal-composition.tsx · 46 строк
import { useId, type CSSProperties } from 'react';
import {
  Button,
  Heading,
  Icon,
  IconButton,
  Sheet,
  SheetClose,
  SheetContent,
  SheetHandle,
  SheetTrigger,
  Text,

Типы

  • SheetProps
  • SheetContentProps
  • SheetCloseProps
  • SheetTriggerProps
  • SheetHandleProps

Модель состояния

  • Состояние открытия может быть контролируемым через open или неконтролируемым через defaultOpen.
  • Каждый запрос на закрытие (клик по подложке, Escape, свайп, клик по SheetClose, отправка <form method="dialog">) идёт через onChangeOpen(false); контролируемая шторка остаётся открытой, пока open не станет false.
  • Пока шторка открыта, прокрутка страницы блокируется через CSS (html:has(dialog:modal) { overflow: hidden }), как у Dialog и Drawer.
  • Точки привязки влияют на видимую модель взаимодействия, а не только на раскладку.
  • Шторка подстраивается под содержимое вплоть до высоты вьюпорта. Задайте CSS-высоту на SheetContent (style={{ height: '80dvh' }} или класс), чтобы сделать высоту фиксированной. Точки привязки — доли высоты вьюпорта или высоты в пикселях, и точка выше высоты шторки останавливается у её верха, так что с коротким содержимым шторка остаётся по размеру содержимого. Без snapPoints шторка останавливается полностью открытой.
  • defaultSnapPoint, activeSnapPoint и значение onChangeActiveSnapPoint — индексы в snapPoints в том порядке, в котором вы их передали, независимо от визуального порядка.
  • Шторка открывается на самой нижней точке привязки, если defaultSnapPoint не говорит иначе, и неконтролируемая шторка снова открывается там же.
  • onChangeActiveSnapPoint срабатывает, только когда пользователь перемещает шторку на другую точку привязки.
  • steppedSnapPoints перемещает шторку не больше чем на одну точку привязки за перетаскивание и сопротивляется движению дальше.
  • Взмах проносит шторку через точки привязки дальше, чем к закрытию: лёгкий взмах вниз с самой нижней точки оставляет её открытой, а взмах с более высокой точки останавливает её на точке привязки.
  • closedBy='none' на SheetContent стоит оставлять для сценариев с понятным путём завершения.
  • useSheetContext доступен для продвинутых обёрток и контролов. Он возвращает { open, changeOpen, contentRef, height, viewport, offsets, activeSnapPoint, changeActiveSnapPoint, steppedSnapPoints } и больше не предоставляет contentId, context из floating-ui, triggerProps, contentProps, transitionStatus и isMounted.