Обратная связь
Пустое состояние
Область, в которой пока нечего показать. Пустое состояние — не отсутствие интерфейса, а полноценный экран: оно объясняет, почему пусто, и даёт выход.
Разметка
<div class="inst-panel">
<div class="inst-empty">
<div class="inst-empty-title">Прогонов пока нет</div>
<div class="inst-empty-desc">Запуск создаст очередь агентов и лог, которые появятся здесь.</div>
<button class="inst-btn inst-btn--sm" type="button">Запустить первый</button>
</div>
</div>
Использование
<div class="inst-empty">
<div class="inst-empty-title">Прогонов пока нет</div>
<div class="inst-empty-desc">Запуск создаст очередь агентов и лог.</div>
<button class="inst-btn inst-btn--sm" type="button">Запустить первый</button>
</div>
| Что | Обязательно | Почему |
|---|---|---|
| Заголовок, называющий причину | да | «Ничего не найдено» без причины читается как поломка |
aria-live="polite" на контейнере |
да, если список опустел из-за фильтра | Иначе для скринридера просто ничего не произошло |
| Настоящий заголовок нужного уровня | да, если занимает целую область | inst-empty-title оформляет, но не объявляет |
| Действие | нет | Обычная кнопка, своего класса не имеет |
Когда использовать
| Возьмите другое | Когда |
|---|---|
| Блок отказа | Пусто из-за ошибки: там нужна причина и то, что уже пробовали |
| Скелетон | Данные ещё грузятся: пустое состояние в этот момент врёт |
Варианты
Три разных «пусто». Их путают, и каждое требует своего текста.
| Почему пусто | Что писать | Действие |
|---|---|---|
| Ещё не начинали | Что здесь появится и откуда | Кнопка, создающая первый объект |
| Фильтр ничего не нашёл | Какой фильтр применён | «Сбросить фильтр» |
| Всё сделано | Что список пуст по хорошей причине | Обычно не нужно |
Разметка
<div class="inst-empty">
<div class="inst-empty-title">Прогонов пока нет</div>
<div class="inst-empty-desc">Запуск создаст очередь агентов и лог, которые появятся здесь.</div>
<button class="inst-btn inst-btn--sm" type="button">Запустить первый</button>
</div>
<div class="inst-empty">
<div class="inst-empty-title">Под фильтр «упало» ничего не подошло</div>
<div class="inst-empty-desc">За последние сутки все прогоны завершились успешно.</div>
<button class="inst-btn inst-btn--sm" type="button">Сбросить фильтр</button>
</div>
<div class="inst-empty">
<div class="inst-empty-title">Очередь пуста</div>
<div class="inst-empty-desc">Все задачи разобраны.</div>
</div>
Текст «Ничего не найдено» без указания причины подходит только второму случаю и в первом читается как поломка.
Правила
Так Заголовок называет причину
«Прогонов пока нет» и «Под фильтр ничего не подошло» — разные экраны, и текст у них разный.
Не так «Ничего не найдено» на первом запуске
Читается как поломка. Пользователь ещё ничего не искал — ему надо сказать, что здесь появится.
Так Выход из пустоты
Кнопка, создающая первый объект, или сброс фильтра. Пустое состояние — полноценный экран, а не заглушка.
Не так Пустое состояние во время загрузки
Данные ещё идут — нужен скелетон. Пустое состояние в этот момент врёт.
Доступность
| Появление после действия | Если список опустел из-за фильтра, сообщение обязано попасть в aria-live="polite" — иначе для скринридера просто ничего не произошло |
| Заголовок | Настоящий заголовок нужного уровня, если пустое состояние занимает целую область |
| Не только иллюстрация | Кит намеренно не даёт картинки: смысл несёт текст. Пустое состояние из одной иконки не сообщает ничего |
| Контраст | Текст берёт --text-muted (4.5:1), а не --text-faint: это данные, которые читают, а не декорация |
API
| Имя | Значение | Что делает |
|---|---|---|
| класс | ||
inst-empty | — | Контейнер, центрирует содержимое |
inst-empty-title | — | Заголовок: почему пусто |
inst-empty-desc | — | Пояснение |
| токен | ||
--space-9 | 48px | |
--space-6 | 16px | |
--gap-inline | var(--space-4) | |
--text-sm | 0.8125rem | |
--text-muted | light-dark(var(--n-8), var(--n-6)) | |
Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument