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

Sheet

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

Именование

SheetContent не называет себя сам. Назвать шторку — ваша задача, и это обязательно: шторка без имени недоступна, потому что скринридеры объявляют её только как «dialog». Сошлитесь на видимый заголовок через aria-labelledby на SheetContent или задайте aria-label, если видимого заголовка нет. Незакрываемые шторки должны объяснять, зачем пользователь оказался в этом сценарии и как его завершить.

sheet-with-heading-and-close-button.tsx · 71 строка
import { useId, useState, type CSSProperties } from 'react';
import {
  Button,
  Heading,
  Icon,
  IconButton,
  Sheet,
  SheetClose,
  SheetContent,
  SheetHandle,
  SheetTrigger,
  Text,

Поведение клавиатуры

ОбъявлениеПереведите фокус на демо и нажмите клавишу из таблицы.
КлавишаДействие
EnterSpaceНа триггере: открывает шторку. Фокус получает сама шторка или дочерний элемент с autoFocus.
TabShift + TabПереносит фокус на следующий или предыдущий элемент управления внутри шторки. Страница за ней инертна, и фокус на неё не попадает. SheetHandle без нескольких точек остановки отключён и пропускается.
EnterSpaceНа SheetHandle с несколькими точками остановки: переводит шторку в следующую, более высокую точку, а из самой высокой — обратно в самую низкую.
EscapeЗакрывает шторку и возвращает фокус на элемент, который её открыл. С closedBy='none' ничего не делает.
Каждая строка проверена в настоящем браузере: Playwright нажимает клавишу в Chromium и смотрит, где оказались фокус и активный элемент.

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

Поведение фокуса

  • При открытии фокус должен переходить в шторку.
  • При закрытии фокус должен разумно восстанавливаться.

Работа с фокусом обеспечивается нативным <dialog>: пока шторка открыта, остальная страница инертна, Tab остаётся внутри шторки (но может дойти до интерфейса браузера), а закрытие возвращает фокус на элемент, который был в фокусе до открытия.

При открытии фокус получает сама шторка, поэтому внутри ничего не подсвечено, а скринридеры объявляют её заголовок; Tab переходит к первому контролу. Поставьте autoFocus на дочерний элемент, чтобы фокусировать его, — например, на первое поле формы.

Семантика для скринридеров

  • Браузер предоставляет шторку как role=dialog с aria-modal, а имя ей дают ваши aria-labelledby или aria-label.
  • Триггер предоставляет aria-haspopup='dialog' и aria-expanded.
  • У SheetClose нет метки по умолчанию, поэтому кнопке только с иконкой внутри неё нужен aria-label; встроенных строк библиотека не поставляет.
  • Шторка должна восприниматься как одна цельная поверхность оверлея.
  • Незакрываемым шторкам нужна особенно понятная цель.

Семантика формы

  • Если в шторке есть форма, обязательные поля и сообщения об ошибках должны оставаться видимыми на каждой точке привязки.
  • Раскладка, удобная для жестов, не должна скрывать настоящую семантику отправки и закрытия.
  • Кнопки в <form method="dialog"> закрывают шторку через onChangeOpen(false), а value кнопки отправки становится returnValue диалога. Это работает и с closedBy='none', так что у незакрываемой шторки всё равно есть путь завершения.

Риски доступности

  • Шторка без aria-labelledby или aria-label.
  • Опора только на понимание жестов.
  • Точки привязки, при которых частично видимое содержимое становится непригодным.
  • Незакрываемые сценарии без понятного пути завершения.