Навигация
Навигация
Список разделов приложения в боковой колонке. Текущий пункт помечен не только цветом: у его края стоит несущая полоса.
Разметка
<nav class="inst-nav" aria-label="Разделы">
<div class="inst-nav-group">
<span class="inst-nav-label">Работа</span>
<a class="inst-nav-item" href="#" aria-current="page">
<svg class="inst-icon" aria-hidden="true"><use href="#i-grid"/></svg>Прогоны
<span class="inst-badge inst-nav-count">7</span></a>
<a class="inst-nav-item" href="#">
<svg class="inst-icon" aria-hidden="true"><use href="#i-list"/></svg>Очередь</a>
<a class="inst-nav-item" href="#">
<svg class="inst-icon" aria-hidden="true"><use href="#i-chart"/></svg>Отчёты</a>
</div>
<div class="inst-nav-group">
<span class="inst-nav-label">Настройка</span>
<a class="inst-nav-item" href="#">
<svg class="inst-icon" aria-hidden="true"><use href="#i-users"/></svg>Доступы</a>
<a class="inst-nav-item" href="#">
<svg class="inst-icon" aria-hidden="true"><use href="#i-settings"/></svg>Параметры</a>
</div>
</nav>
Контракт
| Что | Обязательно | Почему |
|---|---|---|
<nav> + aria-label |
да | На экране больше одной навигации (боковая, крошки, вкладки, страницы) — без имени они неразличимы в списке ориентиров |
<a href> у пункта |
да | Навигация — это адрес. Кнопка ломает средний клик, «открыть в новой вкладке» и копирование ссылки |
aria-current="page" |
да | Единственный источник текущего состояния. Класса для него нет |
aria-hidden="true" у иконки |
да | Имя пункта даёт подпись |
| Текущий пункт — полосой у края, не только цветом | да | Носитель, не зависящий от цвета. aria-current сообщает то же скринридеру |
Доступность
| Клавиатура | Всё от нативных ссылок: Tab — обход, Enter — переход. instrument.js ничего не перехватывает, бегущий tabindex навигации не нужен |
| Ориентир | <nav aria-label> — пункт назначения для «перейти к ориентиру» в скринридере |
| Цвет не единственный носитель | Текущий пункт несёт полосу у края и aria-current, а не один только оттенок фона |
| Цель нажатия | Высота пункта — --control-h-md, 32px. В плотности compact она уменьшается: применяйте compact к табличным видам, а не к основной навигации |
| Контраст | Подпись --text-secondary держит 4.5:1 на приглушённой поверхности колонки в пяти темах |
| Печать | Боковая колонка не печатается: это хром приложения, а не данные |
Устройство
inst-nav-group собирает пункты в смысловой блок, inst-nav-label его
подписывает. Зазор между группами ставится между соседями
(.inst-nav-group + .inst-nav-group), а не вокруг каждой, — иначе первая
группа отступила бы от верхнего края колонки вдвое дальше, чем от боковых.
Подпись — обычное предложение кеглем --text-2xs цветом --text-muted. Капса
здесь нет: подпись не имеет права звучать громче пунктов, которые она
подписывает.
Состояния
Разметка
<nav class="inst-nav" aria-label="Пример текущего пункта">
<div class="inst-nav-group">
<a class="inst-nav-item" href="#" aria-current="page">Прогоны</a>
<a class="inst-nav-item" href="#">Очередь</a>
</div>
</nav>
Метка ставится атрибутом aria-current="page", а не классом. Оформление ловит
селектор [aria-current]:not([aria-current="false"]), поэтому строчка
aria-current="false" у остальных пунктов допустима и ничего не подсвечивает.
| Признак текущего | Что даёт |
|---|---|
| Полоса у внутреннего края | box-shadow: inset шириной --size-marker. Носитель, не зависящий от цвета |
| Поверхность | --surface-selected |
| Цвет подписи | --accent-text |
| Начертание | --weight-medium. Веса 700 в библиотеке нет |
Поведение
В узкой оболочке
Внутри .inst-shell-aside ниже 60rem колонка разворачивается в горизонтальную
полосу: .inst-nav и .inst-nav-group встают в ряд, .inst-nav-label
скрывается, подписи пунктов перестают переноситься. Это единственное место, где
навигация меняет форму, и делает это оболочка, а не
сама навигация.
Композиции
Счётчик в пункте
Разметка
<nav class="inst-nav" aria-label="Пример со счётчиком">
<div class="inst-nav-group">
<a class="inst-nav-item" href="#">Очередь
<span class="inst-badge inst-nav-count">7</span></a>
<a class="inst-nav-item" href="#">История</a>
</div>
</nav>
inst-nav-count — модификатор положения: margin-inline-start: auto прижимает
бейдж к дальнему краю пункта. Сам бейдж остаётся
бейджем и читает те же токены.
API
| Имя | Что делает |
|---|---|
| класс | |
inst-nav | Контейнер списка. Колонка с зазором --space-1 |
inst-nav-group | Смысловой блок пунктов |
inst-nav-label | Подпись группы |
inst-nav-item | Пункт. Ссылка, а не кнопка |
inst-nav-count | Прижать счётчик к дальнему краю пункта |
| Имя | Значение | Откуда |
|---|---|---|
| токен | ||
--control-h-md | 32px | база +14: плотность · масштаб |
--radius-sm | 6px | база +4: масштаб |
--text-sm | 0.875rem | база +4: масштаб |
--text-2xs | 0.6875rem | база +4: масштаб |
--weight-medium | 600 | одно на все ячейки |
--space-1 | 2px | одно на все ячейки |
--space-3 | 6px | одно на все ячейки |
--gap-inline | var(--space-4) | база +14: плотность · масштаб |
--pad-panel | var(--space-5) | база +14: плотность · масштаб |
--size-marker | 2px | база +4: масштаб |
--surface-hover | light-dark(oklch(0 0 0 / 0.035), oklch(1 0 0 / 0.045)) | одно на все ячейки |
--surface-selected | color-mix(in oklab, var(--a-4) 14%, transparent) | одно на все ячейки |
--accent-solid | var(--a-4) | одно на все ячейки |
--accent-text | light-dark(var(--a-5), var(--a-3)) | база +1: тема |
--text-secondary | light-dark(var(--n-9), var(--n-5)) | одно на все ячейки |
--text-muted | light-dark(var(--n-8), var(--n-6)) | одно на все ячейки |
--dur-1 | 80ms | одно на все ячейки |
--ease-out | cubic-bezier(0.22, 0.61, 0.36, 1) | одно на все ячейки |
Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument