Отображение данных
Панель
Область приложения: она стоит на экране постоянно и имеет своё имя. Панель — не карточка: её нельзя перетащить, потому что она и есть место.
Разметка
<div class="inst-panel">
<div class="inst-panel-header">
<span class="inst-panel-title">Прогоны</span>
<div class="inst-panel-actions">
<button class="inst-btn inst-btn--sm" type="button">Обновить</button>
</div>
</div>
<div class="inst-panel-body">
Содержимое области.
</div>
</div>
Использование
<div class="inst-panel">
<div class="inst-panel-header">
<span class="inst-panel-title">Прогоны</span>
<div class="inst-panel-actions">…</div>
</div>
<div class="inst-panel-body">…</div>
</div>
| Что | Обязательно | Почему |
|---|---|---|
role="region" и aria-labelledby |
да, если панель — ориентир | Иначе она не попадёт в список областей у скринридера |
tabindex="0" на теле |
да, если внутри нет фокусируемого | Область прокрутки обязана получать фокус с клавиатуры |
| Ширина приходит снаружи | да | Панель объявлена контейнером; container-type отключает интринсик и схлопнет элемент, получающий ширину от содержимого |
Когда использовать
Вопрос, на который надо ответить до выбора класса: какую работу делает элемент.
| Панель | Карточка | |
|---|---|---|
| Что это | Область приложения | Объект в списке |
| Их на экране | Несколько, и они не меняются | Сколько угодно, приходят из данных |
| Можно перетащить | нет | да, по смыслу |
| Своя прокрутка | да, у тела | нет |
| Пример | «Очередь», «Инспектор», «Лог» | Карточка прогона, карточка агента |
Если ответа нет — компонент не нужен: нужен существующий с другим содержимым.
| Используйте | Возьмите другое |
|---|---|
| Постоянная область экрана со своим именем | Объект из данных — карточка |
| Области нужна своя прокрутка и действия в шапке | Смысловой блок внутри одной страницы — секция: у неё нет рамки и своей прокрутки |
| Панелей на экране несколько и они не меняются | Каркас всего приложения — оболочка |
| — | Ограничение ширины прозы или формы — контейнер |
Устройство
Тело панели
<div class="inst-panel-body inst-panel-body--list">…</div>
| Класс | Когда |
|---|---|
inst-panel-body |
Умолчание: внутренний отступ, своя прокрутка |
inst-panel-body--flush |
Отступ снят — содержимое само знает про края (таблица, диф) |
inst-panel-body--list |
Для списка строк: отступ по вертикали, но не по горизонтали |
Поведение
Панель — контейнер
Панель объявлена контейнером (container: panel / inline-size), поэтому
компоненты внутри отвечают на её ширину. Одна и та же панель стоит и в
узкой колонке инспектора, и во всю ширину дашборда.
/* Своё правило под узкую панель */
@container panel (inline-size < 20rem) {
.my-thing { grid-template-columns: 1fr; }
}
Ширина к панели всегда приходит снаружи, поэтому объявлять её контейнером
безопасно. Объявлять контейнером то, что получает ширину от содержимого,
нельзя: container-type отключает интринсик по инлайновой оси и схлопнет
элемент.
Всплывающее внутри панели
Правила
Так Панель для постоянной области
У неё есть имя, действия в шапке и своя прокрутка. Их на экране несколько, и они не меняются.
Не так Панель для объекта из данных
Объектов столько, сколько пришло из данных, — это карточка. Панель и есть место на экране.
Так Всплывающее в верхнем слое
[popover] или портал: у панели overflow: hidden ради радиуса, и всё внутри
потока обрежется.
Не так container-type на том, что меряется содержимым
container-type отключает интринсик по инлайновой оси и схлопнет элемент.
Панели ширина всегда приходит снаружи — поэтому у неё это безопасно.
Доступность
| Заголовок | inst-panel-title — визуальный. Если панель является ориентиром, дайте ей role="region" и aria-labelledby на заголовок, иначе она не попадёт в список областей |
| Прокрутка | Тело прокручивается само. Область прокрутки должна получать фокус с клавиатуры — браузеры дают это tabindex="0", если внутри нет фокусируемого |
| Глубина | Передаётся поверхностью, а не тенью: --surface-raised над --surface-page. В forced-colors поверхности схлопываются, поэтому панель получает явную рамку CanvasText |
API
| Имя | Значение | Что делает |
|---|---|---|
| класс | ||
inst-panel | — | Область. Контейнер по инлайновой оси |
inst-panel-header | — | Шапка: имя и действия |
inst-panel-title | — | Имя области |
inst-panel-actions | — | Действия в шапке, прижаты к концу |
inst-panel-body | — | Тело с прокруткой |
| модификатор | ||
inst-panel-body--flush | — | Без внутреннего отступа |
inst-panel-body--list | — | Отступ только по вертикали |
| токен | ||
--surface-raised | light-dark(var(--n-0), var(--n-12)) | |
--border | light-dark(oklch(0 0 0 / 0.12), oklch(1 0 0 / 0.11)) | |
--hairline | 1px | |
--radius-lg | 11px | |
--pad-panel | var(--space-5) | |
--text-sm | 0.8125rem | |
Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument