Обратная связь
Сноска
Врезка в поток: поясняет то, рядом с чем стоит. Только полоса у ближнего края и значок — ни заливки, ни рамки, ни места под кнопку.
Разметка
<div class="inst-note" data-tone="warn">Необратимо: восстановление из резервной копии занимает до суток.</div>
<div class="inst-note" data-tone="neutral">Лимит проверяется перед стартом каждого агента, а не по факту.</div>
Использование
<div class="inst-note" data-tone="warn">Необратимо: восстановление занимает до суток.</div>
| Что | Обязательно | Почему |
|---|---|---|
aria-live="polite" на контейнере |
да, если сноска появилась в ответ на действие | Кит роли не ставит: он не знает, появилась она сейчас или была изначально |
| Текст, называющий суть | да | Тон несёт значок, но смысл несут слова |
data-tone |
нет | Без атрибута значка нет, полоса нейтральная |
У сноски нет частей: заголовка и действий у неё не бывает по определению. Если понадобились — это баннер.
Когда использовать
Сноску и баннер путают чаще всего, и разница не в размере, а в области действия.
| Сноска | Баннер | |
|---|---|---|
| К чему относится | К соседнему абзацу, полю, блоку | Ко всему экрану |
| Где стоит | В потоке, там, где нужна | Наверху вида или области |
| Оформление | Полоса у края, углы прямые | Заливка, рамка, скруглённые углы |
| Действие | Нет места и не предполагается | inst-banner-actions |
| Заголовок | Нет | inst-banner-title |
Проверка в одну фразу: если сообщение осмысленно вне того места, где стоит, это баннер. «Артефакты недоступны до 21:00» верно для всего экрана — баннер. «Необратимо» верно только рядом с кнопкой удаления — сноска.
| Используйте | Возьмите другое |
|---|---|
| Оговорка к соседнему абзацу или полю | Условие уровня страницы — баннер |
| Предупреждение рядом с разрушительным действием | Вопрос, требующий ответа — модалка |
| Пояснение внутри панели или тела модалки | Подсказка, всплывающая по наведению — тултип |
| Комментарий к тому, что пользователь сейчас читает | Сбой, у которого должен быть выход — блок отказа: у сноски нет действия |
Устройство
Углы прямые намеренно: у сноски только одна граница — левая, — и скругление на одной стороне выглядит как обрезанный блок.
Значок центрируется по первой строке текста: calc((1lh - var(--size-icon)) / 2). 1lh — реальная высота строки, поэтому формула подстраивается под кегль
и плотность сама. Ручной сдвиг на -1px, который тут был раньше, задирал
значок на 2.1px вверх.
Варианты
Разметка
<div class="inst-note">Без тона: значка нет, полоса нейтральная.</div>
<div class="inst-note" data-tone="neutral">Информация. Синий в ките занят акцентом, поэтому роль info исполняет neutral.</div>
<div class="inst-note" data-tone="running">Идёт прямо сейчас.</div>
<div class="inst-note" data-tone="ok">Проверка пройдена.</div>
<div class="inst-note" data-tone="warn">Прогон завершится, но с замечаниями.</div>
<div class="inst-note" data-tone="error">Валидация путей не прошла.</div>
Тон несёт иконку, а полосы одной мало. Раньше warn и error
отличались друг от друга исключительно цветом — прямое нарушение собственного
закона «цвет не может быть единственным носителем». Набор масок общий с
баннером: одна форма значка на два компонента.
| Тон | Значок |
|---|---|
| без атрибута | Значка нет, полоса --border-strong |
data-tone="neutral" |
«i» в круге |
data-tone="running" |
«i» в круге |
data-tone="ok" |
Галка в круге |
data-tone="warn" |
Треугольник |
data-tone="error" |
Крест в круге |
Правила
Так Сноска рядом с тем, что поясняет
«Необратимо» верно только рядом с кнопкой удаления. Вне этого места фраза теряет смысл — значит, это сноска.
Не так Сноска уровня страницы
Если сообщение осмысленно вне места, где стоит, — это баннер: у него есть заголовок, заливка и место под действие.
Так Появившаяся сноска — в живой регион
Иначе для скринридера ничего не произошло. Кит роли не ставит: он не знает, появилась сноска сейчас или была изначально.
Не так Действие внутри сноски
Места под кнопку у неё нет по определению. Сбой с выходом — блок отказа.
Доступность
| Появление | Сноска, возникшая в ответ на действие, обязана попасть в aria-live="polite". Кит роли не ставит: он не знает, появилась она сейчас или была изначально |
| Цвет не единственный носитель | Тон несёт значок и текст. Ради этого значок и появился |
| Контраст | Текст берёт --text-secondary — 4.5:1 в шести темах |
| Полоса не носитель смысла | Смысл несут значок и слова; полоса только группирует |
| Печать | Печатается: это часть содержимого, а не оформление |
| Режим принудительных цветов | Значок переводится на системный цвет текста и переживает сброс |
API
| Имя | Значение | Что делает |
|---|---|---|
| класс | ||
inst-note | — | Всё. У сноски нет частей: заголовка и действий у неё не бывает по определению |
| атрибут | ||
data-tone | — | neutral running ok warn error. Закрыт. Без атрибута значок не рисуется |
| токен | ||
--size-marker | 2px | |
--size-icon | 16px | |
--tone-ink | var(--accent-text) | |
--border-strong | light-dark(oklch(0 0 0 / 0.22), oklch(1 0 0 / 0.20)) | |
--pad-panel | var(--space-5) | |
--space-3 | 6px | |
--gap-inline | var(--space-4) | |
--text-sm | 0.8125rem | |
--text-secondary | light-dark(var(--n-9), var(--n-5)) | |
--leading-ui | 1.4 | |
Почему кит устроен именно так — конституция · Открытый код под MIT, github.com/keshon/instrument