Раскладка
Шапка экрана
Название экрана, его пояснение и главные действия. Одна на экран — ровно как
одно <h1>.
Прогоны
Каждая область прокручивается сама: боковая навигация не уезжает, пока читают таблицу.
Разметка
<div class="inst-page-header">
<div class="inst-page-header-main">
<h1 class="inst-page-title">Прогоны</h1>
<p class="inst-page-desc">Каждая область прокручивается сама: боковая навигация
не уезжает, пока читают таблицу.</p>
</div>
<div class="inst-page-actions">
<button class="inst-btn inst-btn--sm" type="button">Фильтры</button>
<button class="inst-btn inst-btn--sm inst-btn--primary" type="button">Запустить</button>
</div>
</div>
Контракт
Обёртка inst-page-header-main обязательна: она держит название и пояснение
одной колонкой с зазором --space-2 и несёт flex: 1 1 20rem — порог, ниже
которого действия переносятся под заголовок, а не сжимают его в столбик из
одного слова.
min-inline-size: 0 на ней — не украшение: без него длинное название без
пробелов растягивает всю шапку и выталкивает действия за край.
| Что | Почему |
|---|---|
<h1> под inst-page-title |
Класс даёт кегль, а не уровень. Уровень — работа тега, и скринридер читает именно его |
inst-page-header-main как обёртка |
Без неё название и пояснение становятся отдельными детьми ряда и встают в строку |
type="button" у действий |
Иначе внутри формы они её отправят |
Доступность
| Уровень заголовка | <h1> один на документ. Автоматически он не назначается: ставит автор разметки |
| Мера пояснения | 68ch. Строка длиннее теряется на возврате к началу |
| Перенос | Шапка переносится сама; при увеличении кегля до 200% действия уходят под заголовок, а не за край экрана |
| Контраст | Пояснение — --text-secondary (4.5:1). --text-faint для текста, который читают, не применяется |
| Печать | Название и пояснение печатаются, inst-page-actions — нет: действия на бумаге не действия |
| Порядок | Действия стоят в разметке после заголовка и обходятся после него. order не применяется |
Устройство
inst-page-actions прижимается к дальнему краю (margin-inline-start: auto) и
переносится внутри себя. Держите здесь одно primary: экран, где всё
primary, не имеет primary вовсе — см. кнопку.
Четвёртое и следующие действия уходят в меню. Полоса из шести кнопок над экраном не читается ни глазом, ни с клавиатуры.
Композиции
Прогон #4127 идёт
worldgen · начат 14:02
Разметка
<div class="inst-page-header">
<div class="inst-page-header-main">
<h1 class="inst-page-title">Прогон #4127
<span class="inst-badge" data-tone="running"><span class="inst-dot"></span>идёт</span></h1>
<p class="inst-page-desc">worldgen · начат 14:02</p>
</div>
<div class="inst-page-actions">
<button class="inst-btn inst-btn--sm inst-btn--danger" type="button">Остановить</button>
</div>
</div>
API
| Имя | Что делает |
|---|---|
| класс | |
inst-page-header | Контейнер. Ряд с переносом, выравнивание по верху |
inst-page-header-main | Колонка «название + пояснение». Порог переноса 20rem |
inst-page-title | Название экрана. Кегль --text-xl |
inst-page-desc | Пояснение. --text-sm, --text-secondary, мера 68ch |
inst-page-actions | Действия. Прижаты к дальнему краю, переносятся |
| Имя | Значение | Откуда |
|---|---|---|
| токен | ||
--gap-inline | var(--space-4) | база +14: плотность · масштаб |
--pad-panel | var(--space-5) | база +14: плотность · масштаб |
--space-2 | 4px | одно на все ячейки |
--space-3 | 6px | одно на все ячейки |
--text-xl | 1.375rem | база +4: масштаб |
--text-sm | 0.875rem | база +4: масштаб |
--text-secondary | light-dark(var(--n-9), var(--n-5)) | одно на все ячейки |
Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument